@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.
- package/agent/START-HERE.md +6 -6
- package/agent/components/CodeBlock.json +7 -1
- package/agent/components/OrgChart.json +59 -0
- package/agent/components/Tabs.json +5 -0
- package/agent/components-index.json +5 -0
- package/agent/components.json +71 -1
- package/agent/index.json +7 -7
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +141 -3
- package/dist/components/data-display/code-block.js +90 -4
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/org-chart.d.ts +5 -0
- package/dist/components/data-display/org-chart.js +169 -0
- package/dist/components/data-entry/upload.js +12 -1
- package/dist/components/general/typography.d.ts +32 -0
- package/dist/components/general/typography.js +11 -2
- package/dist/components/navigation/tabs.d.ts +2 -2
- package/dist/components/navigation/tabs.js +57 -10
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +10 -0
- package/dist/i18n/messages/ja.json +10 -0
- package/dist/i18n/messages/vi.json +10 -0
- package/dist/props/components/data-display.prop.d.ts +51 -1
- package/dist/props/components/navigation.prop.d.ts +19 -1
- package/dist/props/registry.d.ts +40 -1
- package/dist/props/registry.js +50 -0
- package/dist/styles/alert-layout.css +12 -12
- package/dist/styles/control.css +18 -2
- package/dist/styles/data-display-layout.css +173 -0
- package/dist/styles/data-entry-layout.css +4 -0
- package/dist/styles/form-layout.css +47 -5
- package/dist/styles/layers.json +14 -1
- package/dist/styles/layout.css +2 -1
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/org-chart.css +27 -0
- package/dist/tokens/components/segmented.css +4 -0
- package/dist/tokens/semantic/layout.css +2 -0
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/data-display/code-block.tsx +27 -0
- package/docs/data-display/org-chart.tsx +165 -0
- package/docs/data-entry/segmented.tsx +2 -0
- package/docs/navigation/tabs.tsx +45 -0
- package/docs/query/data-state.tsx +30 -8
- package/docs/showcase/table-view-tabs.tsx +15 -13
- package/docs/themes/flat.css +4 -0
- package/docs/themes/glassmorphism.css +2 -0
- package/docs/themes/neubrutalism.css +6 -0
- package/package.json +2 -2
|
@@ -1,15 +1,96 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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({
|
|
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
|
-
() => ({
|
|
156
|
-
|
|
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
|
-
({
|
|
516
|
-
|
|
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__ */
|
|
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
|
-
|
|
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
|
+
"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": {
|