@godxjp/ui 31.3.0 → 31.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/agent/START-HERE.md +6 -6
  2. package/agent/components/CodeBlock.json +7 -1
  3. package/agent/components/OrgChart.json +59 -0
  4. package/agent/components/Tabs.json +5 -0
  5. package/agent/components-index.json +5 -0
  6. package/agent/components.json +71 -1
  7. package/agent/index.json +7 -7
  8. package/agent/llms.txt +6 -6
  9. package/agent/tokens.json +141 -3
  10. package/dist/components/data-display/code-block.js +90 -4
  11. package/dist/components/data-display/index.d.ts +2 -0
  12. package/dist/components/data-display/index.js +2 -0
  13. package/dist/components/data-display/org-chart.d.ts +5 -0
  14. package/dist/components/data-display/org-chart.js +169 -0
  15. package/dist/components/data-entry/upload.js +12 -1
  16. package/dist/components/general/typography.d.ts +32 -0
  17. package/dist/components/general/typography.js +11 -2
  18. package/dist/components/navigation/tabs.d.ts +2 -2
  19. package/dist/components/navigation/tabs.js +57 -10
  20. package/dist/contracts/measurement.json +1 -1
  21. package/dist/i18n/messages/en.json +10 -0
  22. package/dist/i18n/messages/ja.json +10 -0
  23. package/dist/i18n/messages/vi.json +10 -0
  24. package/dist/props/components/data-display.prop.d.ts +51 -1
  25. package/dist/props/components/navigation.prop.d.ts +19 -1
  26. package/dist/props/registry.d.ts +40 -1
  27. package/dist/props/registry.js +50 -0
  28. package/dist/styles/alert-layout.css +12 -12
  29. package/dist/styles/control.css +18 -2
  30. package/dist/styles/data-display-layout.css +173 -0
  31. package/dist/styles/data-entry-layout.css +4 -0
  32. package/dist/styles/form-layout.css +47 -5
  33. package/dist/styles/layers.json +14 -1
  34. package/dist/styles/layout.css +2 -1
  35. package/dist/tokens/base.css +1 -0
  36. package/dist/tokens/components/org-chart.css +27 -0
  37. package/dist/tokens/components/segmented.css +4 -0
  38. package/dist/tokens/semantic/layout.css +2 -0
  39. package/docs/FRAME-COVERAGE-REPORT.md +3 -2
  40. package/docs/data-display/code-block.tsx +27 -0
  41. package/docs/data-display/org-chart.tsx +165 -0
  42. package/docs/data-entry/segmented.tsx +2 -0
  43. package/docs/navigation/tabs.tsx +45 -0
  44. package/docs/query/data-state.tsx +30 -8
  45. package/docs/showcase/table-view-tabs.tsx +15 -13
  46. package/docs/themes/flat.css +4 -0
  47. package/docs/themes/glassmorphism.css +2 -0
  48. package/docs/themes/neubrutalism.css +6 -0
  49. package/package.json +2 -2
@@ -1,15 +1,96 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
3
  import * as React from "react";
4
+ import { Check, Copy, LoaderCircle } from "lucide-react";
5
+ import { useTranslation } from "../../i18n/use-translation.js";
3
6
  import { cn } from "../../lib/utils.js";
4
- const CodeBlock = React.forwardRef(function CodeBlock2({ children, wrap = true, maxHeight = "none", size = "sm", language, className, style, ...rest }, ref) {
7
+ import { Button } from "../general/button.js";
8
+ import {
9
+ ActionTooltip,
10
+ COPIED_RESET_MS,
11
+ getNode,
12
+ toCopyConfigList,
13
+ useMergedConfig,
14
+ writeClipboard
15
+ } from "../general/typography.js";
16
+ function CodeBlockCopy({
17
+ config,
18
+ codeRef
19
+ }) {
20
+ const { t } = useTranslation();
21
+ const [copied, setCopied] = React.useState(false);
22
+ const [copyLoading, setCopyLoading] = React.useState(false);
23
+ const copyTimer = React.useRef(null);
24
+ React.useEffect(
25
+ () => () => {
26
+ if (copyTimer.current) clearTimeout(copyTimer.current);
27
+ },
28
+ []
29
+ );
30
+ const onCopyClick = async (event) => {
31
+ setCopyLoading(true);
32
+ try {
33
+ const configured = typeof config.text === "function" ? await config.text() : config.text;
34
+ await writeClipboard(configured || codeRef.current?.textContent || "", config.format);
35
+ setCopyLoading(false);
36
+ setCopied(true);
37
+ if (copyTimer.current) clearTimeout(copyTimer.current);
38
+ copyTimer.current = setTimeout(() => setCopied(false), COPIED_RESET_MS);
39
+ config.onCopy?.(event);
40
+ } catch {
41
+ setCopyLoading(false);
42
+ }
43
+ };
44
+ const copyLabels = toCopyConfigList(config.tooltips);
45
+ const copyIcons = toCopyConfigList(config.icon);
46
+ const systemCopyLabel = copied ? t("ui.codeBlock.copied") : t("ui.codeBlock.copy");
47
+ const copyTitle = getNode(copyLabels[copied ? 1 : 0], systemCopyLabel);
48
+ const copyAriaLabel = typeof copyTitle === "string" ? copyTitle : systemCopyLabel;
49
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
50
+ /* @__PURE__ */ jsx(ActionTooltip, { title: copyTitle, children: /* @__PURE__ */ jsx(
51
+ Button,
52
+ {
53
+ type: "button",
54
+ variant: "ghost",
55
+ size: "icon-xs",
56
+ "data-slot": "code-block-copy",
57
+ "data-state": copied ? "copied" : "idle",
58
+ "aria-label": copyAriaLabel,
59
+ tabIndex: config.tabIndex,
60
+ onClick: onCopyClick,
61
+ className: "ui-code-block-copy",
62
+ children: copied ? getNode(copyIcons[1], /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }), true) : getNode(
63
+ copyIcons[0],
64
+ copyLoading ? /* @__PURE__ */ jsx(LoaderCircle, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true" }),
65
+ true
66
+ )
67
+ }
68
+ ) }),
69
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", "data-slot": "code-block-status", children: copied ? t("ui.codeBlock.copiedAnnounce") : "" })
70
+ ] });
71
+ }
72
+ const CodeBlock = React.forwardRef(function CodeBlock2({
73
+ children,
74
+ wrap = true,
75
+ maxHeight = "none",
76
+ size = "sm",
77
+ language,
78
+ copyable,
79
+ className,
80
+ style,
81
+ ...rest
82
+ }, ref) {
83
+ const [enableCopy, copyConfig] = useMergedConfig(copyable);
84
+ const codeRef = React.useRef(null);
5
85
  const scrolls = maxHeight !== "none" || !wrap;
6
- return /* @__PURE__ */ jsx(
86
+ const pre = /* @__PURE__ */ jsx(
7
87
  "pre",
8
88
  {
9
89
  ref,
10
90
  "data-slot": "code-block",
11
91
  "data-wrap": wrap ? void 0 : "false",
12
92
  "data-max-height": typeof maxHeight === "string" && maxHeight !== "none" ? maxHeight : void 0,
93
+ "data-copyable": enableCopy ? "" : void 0,
13
94
  style: {
14
95
  ...style,
15
96
  ...typeof maxHeight === "object" ? { maxBlockSize: maxHeight.value, overflow: "auto" } : void 0
@@ -19,9 +100,14 @@ const CodeBlock = React.forwardRef(function CodeBlock2({ children, wrap = true,
19
100
  tabIndex: scrolls ? 0 : void 0,
20
101
  className: cn("ui-code-block", className),
21
102
  ...rest,
22
- children: /* @__PURE__ */ jsx("code", { children })
103
+ children: /* @__PURE__ */ jsx("code", { ref: codeRef, children })
23
104
  }
24
105
  );
106
+ if (!enableCopy) return pre;
107
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "code-block-frame", className: "ui-code-block-frame", children: [
108
+ pre,
109
+ /* @__PURE__ */ jsx(CodeBlockCopy, { config: copyConfig, codeRef })
110
+ ] });
25
111
  });
26
112
  export {
27
113
  CodeBlock
@@ -53,6 +53,8 @@ export { ChatBubble, ChatBubbleList } from "./chat-bubble.js";
53
53
  export type { ChatBubbleListProp, ChatBubbleListProps, ChatBubblePlacementProp, ChatBubbleProp, ChatBubbleProps, ChatBubbleToneProp, ChatBubbleTypingProp, ChatBubbleVariantProp, ChatMessageProp, } from "./chat-bubble.js";
54
54
  export { Tree } from "./tree.js";
55
55
  export type { TreeNodeProp, TreeProp, TreeProps } from "./tree.js";
56
+ export { OrgChart } from "./org-chart.js";
57
+ export type { OrgChartNodeProp, OrgChartNodeVariantProp, OrgChartProp, OrgChartProps, } from "./org-chart.js";
56
58
  export { Welcome } from "./welcome.js";
57
59
  export type { WelcomeProp, WelcomeProps, WelcomeVariantProp } from "./welcome.js";
58
60
  export { ThoughtChain, ThoughtChainItem } from "./thought-chain.js";
@@ -60,6 +60,7 @@ import { PermissionMatrix } from "./permission-matrix.js";
60
60
  import { RangeTimeline } from "./range-timeline.js";
61
61
  import { ChatBubble, ChatBubbleList } from "./chat-bubble.js";
62
62
  import { Tree } from "./tree.js";
63
+ import { OrgChart } from "./org-chart.js";
63
64
  import { Welcome } from "./welcome.js";
64
65
  import { ThoughtChain, ThoughtChainItem } from "./thought-chain.js";
65
66
  export {
@@ -103,6 +104,7 @@ export {
103
104
  Legend,
104
105
  ListRow,
105
106
  Marquee,
107
+ OrgChart,
106
108
  PermissionMatrix,
107
109
  Popover,
108
110
  PopoverAnchor,
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ import type { OrgChartProp } from "../../props/components/data-display.prop.js";
3
+ export type { OrgChartNodeProp, OrgChartNodeVariantProp, OrgChartProp, OrgChartProp as OrgChartProps, } from "../../props/components/data-display.prop.js";
4
+ /** `ref` reaches the root `<div>` — the container the breakpoint is measured against. */
5
+ export declare const OrgChart: React.ForwardRefExoticComponent<OrgChartProp & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,169 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useTranslation } from "../../i18n/use-translation.js";
5
+ import { useScrollsHorizontally } from "../../lib/hooks.js";
6
+ import { cn } from "../../lib/utils.js";
7
+ import { Tree } from "./tree.js";
8
+ function flatten(nodes) {
9
+ const out = [];
10
+ const walk = (list, depth, parent) => {
11
+ for (const node of list) {
12
+ const index = out.length;
13
+ out.push({ node, depth, parent, firstChild: null });
14
+ if (node.children?.length) {
15
+ out[index].firstChild = out.length;
16
+ walk(node.children, depth + 1, index);
17
+ }
18
+ }
19
+ };
20
+ walk(nodes, 0, null);
21
+ return out;
22
+ }
23
+ function toTreeData(nodes) {
24
+ return nodes.map((node) => ({
25
+ value: node.key,
26
+ label: node.name,
27
+ children: node.children?.length ? toTreeData(node.children) : void 0
28
+ }));
29
+ }
30
+ function isRtl(element) {
31
+ return element.closest("[dir]")?.getAttribute("dir")?.toLowerCase() === "rtl";
32
+ }
33
+ function OrgChartRoot({
34
+ data,
35
+ renderNode,
36
+ label,
37
+ className,
38
+ id,
39
+ forwardedRef,
40
+ ...rest
41
+ }) {
42
+ const { t } = useTranslation();
43
+ const reactId = React.useId();
44
+ const baseId = id ?? `${reactId}-org-chart`;
45
+ const treeLabel = label ?? t("dataDisplay.orgChart.label");
46
+ const flat = React.useMemo(() => flatten(data), [data]);
47
+ const indexByKey = React.useMemo(
48
+ () => new Map(flat.map((entry, index) => [entry.node.key, index])),
49
+ [flat]
50
+ );
51
+ const scrollRef = React.useRef(null);
52
+ const scrolls = useScrollsHorizontally(scrollRef, true);
53
+ const [activeKey, setActiveKey] = React.useState(null);
54
+ const rovingKey = (activeKey && indexByKey.has(activeKey) ? activeKey : null) ?? flat[0]?.node.key ?? null;
55
+ const nodeRefs = React.useRef(/* @__PURE__ */ new Map());
56
+ const moveTo = (index) => {
57
+ if (index == null) return;
58
+ const entry = flat[index];
59
+ if (!entry) return;
60
+ setActiveKey(entry.node.key);
61
+ nodeRefs.current.get(entry.node.key)?.focus();
62
+ };
63
+ const onKeyDown = (event, index) => {
64
+ const entry = flat[index];
65
+ const rtl = isRtl(event.currentTarget);
66
+ const inward = rtl ? "ArrowLeft" : "ArrowRight";
67
+ const outward = rtl ? "ArrowRight" : "ArrowLeft";
68
+ let target;
69
+ if (event.key === "ArrowDown") target = index + 1 < flat.length ? index + 1 : null;
70
+ else if (event.key === "ArrowUp") target = index > 0 ? index - 1 : null;
71
+ else if (event.key === "Home") target = 0;
72
+ else if (event.key === "End") target = flat.length - 1;
73
+ else if (event.key === inward) target = entry.firstChild;
74
+ else if (event.key === outward) target = entry.parent;
75
+ else return;
76
+ event.preventDefault();
77
+ moveTo(target ?? null);
78
+ };
79
+ const renderBranch = (nodes) => nodes.map((node, position) => {
80
+ const index = indexByKey.get(node.key);
81
+ const { depth } = flat[index];
82
+ const nodeId = `${baseId}-n${index}`;
83
+ const groupId = `${nodeId}-group`;
84
+ const hasChildren = Boolean(node.children?.length);
85
+ const isAgent = node.variant === "agent";
86
+ const labelledBy = renderNode ? void 0 : [
87
+ `${nodeId}-name`,
88
+ node.title ? `${nodeId}-title` : null,
89
+ isAgent ? `${nodeId}-kind` : null
90
+ ].filter(Boolean).join(" ");
91
+ return /* @__PURE__ */ jsxs("li", { role: "none", className: "ui-org-chart-branch", children: [
92
+ /* @__PURE__ */ jsxs(
93
+ "div",
94
+ {
95
+ ref: (element) => {
96
+ nodeRefs.current.set(node.key, element);
97
+ },
98
+ id: nodeId,
99
+ role: "treeitem",
100
+ "aria-level": depth + 1,
101
+ "aria-setsize": nodes.length,
102
+ "aria-posinset": position + 1,
103
+ "aria-labelledby": labelledBy,
104
+ "aria-describedby": !renderNode && node.extra ? `${nodeId}-extra` : void 0,
105
+ "aria-owns": hasChildren ? groupId : void 0,
106
+ tabIndex: rovingKey === node.key ? 0 : -1,
107
+ "data-key": node.key,
108
+ "data-variant": isAgent ? "agent" : "person",
109
+ className: "ui-org-chart-node ui-focus-ring",
110
+ onFocus: () => setActiveKey(node.key),
111
+ onKeyDown: (event) => onKeyDown(event, index),
112
+ children: [
113
+ renderNode ? renderNode(node) : /* @__PURE__ */ jsxs(Fragment, { children: [
114
+ node.avatar ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ui-org-chart-avatar", children: node.avatar }) : null,
115
+ /* @__PURE__ */ jsxs("span", { className: "ui-org-chart-text", children: [
116
+ /* @__PURE__ */ jsx("span", { id: `${nodeId}-name`, className: "ui-org-chart-name", children: node.name }),
117
+ node.title ? /* @__PURE__ */ jsx("span", { id: `${nodeId}-title`, className: "ui-org-chart-title", children: node.title }) : null,
118
+ node.extra ? /* @__PURE__ */ jsx("span", { id: `${nodeId}-extra`, className: "ui-org-chart-extra", children: node.extra }) : null
119
+ ] })
120
+ ] }),
121
+ isAgent ? /* @__PURE__ */ jsx("span", { id: `${nodeId}-kind`, className: "sr-only", children: t("dataDisplay.orgChart.agent") }) : null
122
+ ]
123
+ }
124
+ ),
125
+ hasChildren ? /* @__PURE__ */ jsx("ul", { id: groupId, role: "group", className: "ui-org-chart-children", children: renderBranch(node.children) }) : null
126
+ ] }, node.key);
127
+ });
128
+ const treeData = React.useMemo(() => toTreeData(data), [data]);
129
+ const nodeByKey = React.useMemo(
130
+ () => new Map(flat.map((entry) => [entry.node.key, entry.node])),
131
+ [flat]
132
+ );
133
+ return /* @__PURE__ */ jsxs("div", { ...rest, ref: forwardedRef, id, className: cn("ui-org-chart", className), children: [
134
+ /* @__PURE__ */ jsx(
135
+ "div",
136
+ {
137
+ ref: scrollRef,
138
+ className: "ui-org-chart-scroll",
139
+ ...scrolls ? { role: "region", "aria-label": t("dataDisplay.orgChart.scrollRegion"), tabIndex: 0 } : {},
140
+ children: /* @__PURE__ */ jsx("ul", { role: "tree", "aria-label": treeLabel, className: "ui-org-chart-tree", children: renderBranch(data) })
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx("div", { className: "ui-org-chart-list", children: /* @__PURE__ */ jsx(
144
+ Tree,
145
+ {
146
+ "aria-label": treeLabel,
147
+ treeData,
148
+ defaultExpandAll: true,
149
+ titleRender: (treeNode) => {
150
+ const node = nodeByKey.get(treeNode.value);
151
+ if (!node) return treeNode.label;
152
+ if (renderNode) return renderNode(node);
153
+ return /* @__PURE__ */ jsxs("span", { className: "ui-org-chart-list-row", children: [
154
+ node.avatar ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ui-org-chart-avatar", children: node.avatar }) : null,
155
+ /* @__PURE__ */ jsx("span", { className: "ui-org-chart-name", children: node.name }),
156
+ node.title ? /* @__PURE__ */ jsx("span", { className: "ui-org-chart-title", children: node.title }) : null,
157
+ node.variant === "agent" ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("dataDisplay.orgChart.agent") }) : null,
158
+ node.extra ? /* @__PURE__ */ jsx("span", { className: "ui-org-chart-extra", children: node.extra }) : null
159
+ ] });
160
+ }
161
+ }
162
+ ) })
163
+ ] });
164
+ }
165
+ const OrgChart = React.forwardRef((props, ref) => /* @__PURE__ */ jsx(OrgChartRoot, { ...props, forwardedRef: ref }));
166
+ OrgChart.displayName = "OrgChart";
167
+ export {
168
+ OrgChart
169
+ };
@@ -497,6 +497,7 @@ function Upload({
497
497
  disabled,
498
498
  onClick: openPicker,
499
499
  "aria-label": triggerAriaLabel,
500
+ className: "ui-upload-trigger",
500
501
  children: [
501
502
  /* @__PURE__ */ jsx(
502
503
  TriggerIcon,
@@ -553,7 +554,17 @@ function Upload({
553
554
  hiddenInput,
554
555
  liveRegion,
555
556
  rejection && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-error-strong", children: rejection }),
556
- /* @__PURE__ */ jsx(Button, { type: "button", disabled, variant: triggerVariant, onClick: openPicker, children: children ?? t("dataEntry.upload.addImage") }),
557
+ /* @__PURE__ */ jsx(
558
+ Button,
559
+ {
560
+ type: "button",
561
+ disabled,
562
+ variant: triggerVariant,
563
+ onClick: openPicker,
564
+ className: "ui-upload-trigger",
565
+ children: children ?? t("dataEntry.upload.addImage")
566
+ }
567
+ ),
557
568
  list
558
569
  ] });
559
570
  }
@@ -2,6 +2,38 @@ import * as React from "react";
2
2
  import type { TextProp, TypographyBlockProp } from "../../props/components/general.prop.js";
3
3
  import type { TypographyEllipsisConfigProp } from "../../props/vocabulary/index.js";
4
4
  export type { TextProp, TextProp as TextProps, HeadingProp, HeadingProp as HeadingProps, TypographyProp, TypographyProp as TypographyProps, TypographyBlockProp, TypographyTitleProp, TypographyTitleProp as TitleProps, ParagraphProp, ParagraphProp as ParagraphProps, LinkProp, LinkProp as LinkProps, } from "../../props/components/general.prop.js";
5
+ /** How long the copy button shows its confirmed state. antd's value (`useCopyClick`). */
6
+ export declare const COPIED_RESET_MS = 3000;
7
+ /** antd `getNode` — `true`/`undefined` take the default; `false` suppresses unless a DOM node is required. */
8
+ export declare function getNode(node: React.ReactNode | boolean | undefined, fallback: React.ReactNode, needDom?: boolean): React.ReactNode;
9
+ /** antd `toCopyConfigList` — `false` suppresses BOTH states, otherwise index 0 = idle, 1 = copied. */
10
+ export declare function toCopyConfigList(value: React.ReactNode | false | undefined): (string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined)[] | readonly [false, false];
11
+ /**
12
+ * antd `useMergedConfig` — `true` means "on, all defaults"; an object means "on, these overrides".
13
+ * The boolean is the SUPPORT flag, so `copyable={false}` and `copyable={undefined}` are both off.
14
+ */
15
+ export declare function useMergedConfig<T extends object>(propConfig: boolean | T | undefined, template?: Partial<T>): [boolean, T];
16
+ /**
17
+ * The clipboard write, antd's `_util/copy` reduced to the one path a modern browser takes.
18
+ *
19
+ * antd keeps a `document.execCommand("copy")` fallback for browsers without the async Clipboard
20
+ * API. It is NOT ported: `execCommand` is deprecated, every browser in this package's support
21
+ * matrix ships `navigator.clipboard`, and the fallback's failure mode is worse than none — it
22
+ * reports success from a synchronous flag that a permission prompt can leave stale, so the UI
23
+ * claims a copy that never happened. Here a refusal throws, `onCopy` never fires, and the button
24
+ * never shows its confirmed state.
25
+ */
26
+ export declare function writeClipboard(text: string, format: "text/plain" | "text/html" | undefined): Promise<void>;
27
+ /**
28
+ * A tooltip that disappears entirely when its title is suppressed.
29
+ *
30
+ * antd wraps every action in `<Tooltip>`; this library's Tooltip is the house primitive and is
31
+ * composed (`Tooltip > TooltipTrigger > TooltipContent`), so the wrapper lives here.
32
+ */
33
+ export declare function ActionTooltip({ title, children, }: {
34
+ title: React.ReactNode;
35
+ children: React.ReactNode;
36
+ }): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | null | undefined;
5
37
  /**
6
38
  * Text — the typographic primitive, and antd's `Typography.Text`.
7
39
  *
@@ -62,7 +62,10 @@ async function writeClipboard(text, format) {
62
62
  function childrenToText(children) {
63
63
  return React.Children.toArray(children).map((node) => typeof node === "string" || typeof node === "number" ? String(node) : "").join("");
64
64
  }
65
- function ActionTooltip({ title, children }) {
65
+ function ActionTooltip({
66
+ title,
67
+ children
68
+ }) {
66
69
  if (title === null || title === void 0 || title === false || title === "") return children;
67
70
  return /* @__PURE__ */ jsxs(Tooltip, { children: [
68
71
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
@@ -654,10 +657,16 @@ const Typography = Object.assign(TypographyRoot, {
654
657
  Link
655
658
  });
656
659
  export {
660
+ ActionTooltip,
661
+ COPIED_RESET_MS,
657
662
  Heading,
658
663
  Link,
659
664
  Paragraph,
660
665
  Text,
661
666
  Title,
662
- Typography
667
+ Typography,
668
+ getNode,
669
+ toCopyConfigList,
670
+ useMergedConfig,
671
+ writeClipboard
663
672
  };
@@ -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, bodied, extra, destroyOnHidden, onEdit, addIcon, hideAdd, closeIcon, onTabClick, overflow, animated, indicator, moreIcon, onTabScroll, 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, bodied, extra, destroyOnHidden, onEdit, addIcon, hideAdd, closeIcon, onTabClick, overflow, animated, indicator, moreIcon, onTabScroll, controls, listClassName, contentClassName, children, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...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
  /**
@@ -24,7 +24,7 @@ export declare const TabsTrigger: React.ForwardRefExoticComponent<Omit<Omit<Reac
24
24
  value: string;
25
25
  /** RAC `isDisabled`; ALSO written to the button so `disabled:` utilities keep matching. */
26
26
  disabled?: boolean;
27
- } & React.RefAttributes<HTMLButtonElement>>;
27
+ } & Pick<TabItemProp, "count" | "countLabel" | "overflowCount" | "showZero"> & React.RefAttributes<HTMLButtonElement>>;
28
28
  export declare const TabsContent: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "value"> & {
29
29
  /** The panel's key — must match a `TabsTrigger value`. RAC `id`. */
30
30
  value: string;
@@ -41,11 +41,14 @@ function TabCount({
41
41
  const { pill } = useCounterPill({ count, overflowCount, showZero, countLabel, slot: "tabs" });
42
42
  return pill;
43
43
  }
44
+ const NO_LIST_LABEL = {};
44
45
  const TabsFrameContext = React.createContext({
45
46
  orientation: "horizontal",
46
47
  selectionSuppressed: false,
47
48
  size: "md",
48
- panels: null
49
+ panels: null,
50
+ controls: void 0,
51
+ listLabel: NO_LIST_LABEL
49
52
  });
50
53
  function resolveFallbackTabValue(items, requested) {
51
54
  if (!items || items.length === 0) return requested;
@@ -122,9 +125,12 @@ function Tabs({
122
125
  indicator,
123
126
  moreIcon,
124
127
  onTabScroll,
128
+ controls,
125
129
  listClassName,
126
130
  contentClassName,
127
131
  children,
132
+ "aria-label": ariaLabel,
133
+ "aria-labelledby": ariaLabelledby,
128
134
  ...props
129
135
  }) {
130
136
  const { t } = useTranslation();
@@ -151,9 +157,20 @@ function Tabs({
151
157
  return next;
152
158
  });
153
159
  }, []);
160
+ const listLabel = React.useMemo(
161
+ () => ariaLabel === void 0 && ariaLabelledby === void 0 ? NO_LIST_LABEL : { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby },
162
+ [ariaLabel, ariaLabelledby]
163
+ );
154
164
  const frame = React.useMemo(
155
- () => ({ orientation: resolvedOrientation, selectionSuppressed, size, panels }),
156
- [resolvedOrientation, selectionSuppressed, size, panels]
165
+ () => ({
166
+ orientation: resolvedOrientation,
167
+ selectionSuppressed,
168
+ size,
169
+ panels,
170
+ controls,
171
+ listLabel
172
+ }),
173
+ [resolvedOrientation, selectionSuppressed, size, panels, controls, listLabel]
157
174
  );
158
175
  const editable = variant === "editable-card";
159
176
  const collapsible = items != null && overflow === "menu";
@@ -444,7 +461,7 @@ function Tabs({
444
461
  ] }) : null,
445
462
  extraEnd ? /* @__PURE__ */ jsx("div", { "data-slot": "tabs-extra", "data-side": "end", className: "ui-tabs-extra", children: extraEnd }) : null
446
463
  ] }) : list,
447
- items.map((item) => {
464
+ controls !== void 0 ? null : items.map((item) => {
448
465
  const keepMounted = !destroyOnHidden || item.forceRender === true;
449
466
  return /* @__PURE__ */ jsx(
450
467
  TabsContent,
@@ -465,6 +482,9 @@ function Tabs({
465
482
  }
466
483
  const TabsList = React.forwardRef(
467
484
  ({ className, variant = "default", loop: _loop, children, ...props }, ref) => {
485
+ const { listLabel } = React.useContext(TabsFrameContext);
486
+ const ownName = props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0;
487
+ const name = ownName ? { "aria-label": props["aria-label"], "aria-labelledby": props["aria-labelledby"] } : listLabel;
468
488
  const listRef = React.useRef(null);
469
489
  const setListRef = React.useCallback(
470
490
  (node) => {
@@ -479,6 +499,8 @@ const TabsList = React.forwardRef(
479
499
  AriaTabList,
480
500
  {
481
501
  ref: setListRef,
502
+ "aria-label": name["aria-label"],
503
+ "aria-labelledby": name["aria-labelledby"],
482
504
  className: cn(
483
505
  // `min-w-0 max-w-full` let the list shrink to (and never exceed) whatever width its
484
506
  // ancestors actually give it instead of forcing them wider; horizontal orientation then
@@ -512,10 +534,22 @@ const TabsList = React.forwardRef(
512
534
  );
513
535
  TabsList.displayName = "TabsList";
514
536
  const TabsTrigger = React.forwardRef(
515
- ({ className, value, disabled, children, onKeyDown, onClick, ...props }, ref) => {
516
- const { orientation, selectionSuppressed, size, panels } = React.useContext(TabsFrameContext);
537
+ ({
538
+ className,
539
+ value,
540
+ disabled,
541
+ count,
542
+ overflowCount,
543
+ showZero,
544
+ countLabel,
545
+ children,
546
+ onKeyDown,
547
+ onClick,
548
+ ...props
549
+ }, ref) => {
550
+ const { orientation, selectionSuppressed, size, panels, controls } = React.useContext(TabsFrameContext);
517
551
  const controlsAPanel = panels === null || panels.has(value);
518
- return /* @__PURE__ */ jsx(
552
+ return /* @__PURE__ */ jsxs(
519
553
  AriaTab,
520
554
  {
521
555
  ref,
@@ -565,8 +599,10 @@ const TabsTrigger = React.forwardRef(
565
599
  // here for BOTH states, exactly as Radix did.
566
600
  "data-state": renderProps.isSelected && !selectionSuppressed ? "active" : "inactive",
567
601
  "aria-selected": renderProps.isSelected && !selectionSuppressed,
568
- // RAC writes this unconditionally; see `TabsFrame.panels` (gh#643).
569
- "aria-controls": controlsAPanel ? domProps["aria-controls"] : void 0,
602
+ // RAC writes this unconditionally; see `TabsFrame.panels` (gh#643). With no panel
603
+ // declared, a strip-only root's `controls` region takes its place — on the SELECTED
604
+ // tab only, the same rule RAC applies to a real panel (gh#1021).
605
+ "aria-controls": controlsAPanel ? domProps["aria-controls"] : renderProps.isSelected && !selectionSuppressed ? controls : void 0,
570
606
  "data-orientation": orientation,
571
607
  disabled,
572
608
  // CHAINED, not spread — the same reason `onKeyDown` below is. `withDomProps` lays the
@@ -591,7 +627,18 @@ const TabsTrigger = React.forwardRef(
591
627
  },
592
628
  tabIndex: props.tabIndex ?? domProps.tabIndex
593
629
  }),
594
- children
630
+ children: [
631
+ children,
632
+ /* @__PURE__ */ jsx(
633
+ TabCount,
634
+ {
635
+ count,
636
+ overflowCount,
637
+ showZero,
638
+ countLabel
639
+ }
640
+ )
641
+ ]
595
642
  }
596
643
  );
597
644
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "31.3.0",
3
+ "version": "31.5.0",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
@@ -371,6 +371,11 @@
371
371
  "abort": "stopped"
372
372
  }
373
373
  },
374
+ "orgChart": {
375
+ "label": "Organization chart",
376
+ "scrollRegion": "Scrollable organization chart",
377
+ "agent": "AI agent"
378
+ },
374
379
  "timeline": {
375
380
  "statusDone": "Completed: ",
376
381
  "statusCurrent": "Current: ",
@@ -419,6 +424,11 @@
419
424
  "edit": "Edit",
420
425
  "expand": "Expand",
421
426
  "collapse": "Collapse"
427
+ },
428
+ "codeBlock": {
429
+ "copy": "Copy code",
430
+ "copied": "Copied",
431
+ "copiedAnnounce": "Code copied to clipboard"
422
432
  }
423
433
  },
424
434
  "navigation": {
@@ -364,6 +364,11 @@
364
364
  "abort": "中断"
365
365
  }
366
366
  },
367
+ "orgChart": {
368
+ "label": "組織図",
369
+ "scrollRegion": "スクロールできる組織図",
370
+ "agent": "AIエージェント"
371
+ },
367
372
  "timeline": {
368
373
  "statusDone": "完了: ",
369
374
  "statusCurrent": "現在: ",
@@ -412,6 +417,11 @@
412
417
  "edit": "編集",
413
418
  "expand": "展開",
414
419
  "collapse": "折りたたむ"
420
+ },
421
+ "codeBlock": {
422
+ "copy": "コードをコピー",
423
+ "copied": "コピーしました",
424
+ "copiedAnnounce": "コードをクリップボードにコピーしました"
415
425
  }
416
426
  },
417
427
  "navigation": {
@@ -365,6 +365,11 @@
365
365
  "abort": "đã dừng"
366
366
  }
367
367
  },
368
+ "orgChart": {
369
+ "label": "Sơ đồ tổ chức",
370
+ "scrollRegion": "Sơ đồ tổ chức có thể cuộn",
371
+ "agent": "Tác tử AI"
372
+ },
368
373
  "timeline": {
369
374
  "statusDone": "Đã xong: ",
370
375
  "statusCurrent": "Hiện tại: ",
@@ -413,6 +418,11 @@
413
418
  "edit": "Sửa",
414
419
  "expand": "Mở rộng",
415
420
  "collapse": "Thu gọn"
421
+ },
422
+ "codeBlock": {
423
+ "copy": "Sao chép mã",
424
+ "copied": "Đã sao chép",
425
+ "copiedAnnounce": "Đã sao chép mã vào bộ nhớ tạm"
416
426
  }
417
427
  },
418
428
  "navigation": {