@godxjp/ui 23.2.1 → 23.4.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/dist/app/timezones.js +2 -1
- package/dist/components/charts/chart-cartesian.js +2 -4
- package/dist/components/charts/chart-frame.js +2 -1
- package/dist/components/data-display/card.d.ts +87 -1
- package/dist/components/data-display/card.js +88 -15
- package/dist/components/data-display/index.d.ts +5 -1
- package/dist/components/data-display/index.js +5 -0
- package/dist/components/data-display/thought-chain.d.ts +42 -0
- package/dist/components/data-display/thought-chain.js +177 -0
- package/dist/components/data-display/welcome.d.ts +26 -0
- package/dist/components/data-display/welcome.js +37 -0
- package/dist/components/data-entry/attachments.d.ts +19 -0
- package/dist/components/data-entry/attachments.js +322 -0
- package/dist/components/data-entry/date-picker.js +12 -14
- package/dist/components/data-entry/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/data-entry/number-input.js +2 -1
- package/dist/components/feedback/dialog.d.ts +10 -7
- package/dist/components/feedback/dialog.js +40 -17
- package/dist/components/feedback/index.d.ts +3 -3
- package/dist/components/feedback/index.js +2 -0
- package/dist/components/feedback/skeleton.d.ts +11 -2
- package/dist/components/feedback/skeleton.js +8 -0
- package/dist/components/general/actions.d.ts +59 -0
- package/dist/components/general/actions.js +253 -0
- package/dist/components/general/activity.js +1 -0
- package/dist/components/general/button.js +2 -1
- package/dist/components/general/float-button.d.ts +41 -0
- package/dist/components/general/float-button.js +336 -0
- package/dist/components/general/index.d.ts +6 -2
- package/dist/components/general/index.js +12 -1
- package/dist/components/general/typography.d.ts +79 -4
- package/dist/components/general/typography.js +598 -54
- package/dist/components/layout/draggable-panel.d.ts +18 -0
- package/dist/components/layout/draggable-panel.js +189 -0
- package/dist/components/layout/error-surface.js +3 -2
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/navigation/conversations.d.ts +39 -0
- package/dist/components/navigation/conversations.js +371 -0
- package/dist/components/navigation/index.d.ts +2 -0
- package/dist/components/navigation/index.js +2 -0
- package/dist/components/ui/card.js +1 -0
- package/dist/components/ui/toggle.js +2 -1
- package/dist/i18n/messages/en.json +53 -0
- package/dist/i18n/messages/ja.json +53 -0
- package/dist/i18n/messages/vi.json +53 -0
- package/dist/i18n/translate.js +3 -2
- package/dist/lib/datetime/picker-format.js +2 -1
- package/dist/lib/format.js +3 -2
- package/dist/lib/intl-cache.d.ts +32 -0
- package/dist/lib/intl-cache.js +29 -0
- package/dist/props/components/data-display.prop.d.ts +143 -1
- package/dist/props/components/data-entry.prop.d.ts +87 -0
- package/dist/props/components/feedback.prop.d.ts +53 -1
- package/dist/props/components/general.prop.d.ts +440 -3
- package/dist/props/components/index.d.ts +2 -2
- package/dist/props/components/layout.prop.d.ts +63 -1
- package/dist/props/components/navigation.prop.d.ts +150 -0
- package/dist/props/registry.d.ts +431 -0
- package/dist/props/registry.js +551 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +113 -0
- package/dist/styles/alert-layout.css +22 -0
- package/dist/styles/card-layout.css +34 -0
- package/dist/styles/core.css +1 -0
- package/dist/styles/data-display-layout.css +236 -0
- package/dist/styles/float-button-layout.css +168 -0
- package/dist/styles/form-layout.css +11 -1
- package/dist/styles/index.css +1 -0
- package/dist/styles/layout.css +196 -0
- package/dist/styles/navigation-layout.css +139 -0
- package/dist/styles/text-layout.css +156 -0
- package/dist/tokens/axes.css +5 -0
- package/dist/tokens/base.css +7 -0
- package/dist/tokens/components/actions.css +14 -0
- package/dist/tokens/components/attachments.css +15 -0
- package/dist/tokens/components/conversations.css +28 -0
- package/dist/tokens/components/draggable-panel.css +25 -0
- package/dist/tokens/components/float-button.css +39 -0
- package/dist/tokens/components/text.css +13 -0
- package/dist/tokens/components/thought-chain.css +31 -0
- package/dist/tokens/components/welcome.css +19 -0
- package/dist/tokens/foundation.css +6 -4
- package/docs/DESIGN-AUTHORITY.md +133 -20
- package/docs/FRAME-COVERAGE-REPORT.md +5 -2
- package/docs/data-display/card/examples/tab-list.tsx +97 -0
- package/docs/data-display/thought-chain.tsx +176 -0
- package/docs/data-display/welcome.tsx +115 -0
- package/docs/data-entry/attachments.tsx +160 -0
- package/docs/feedback/dialog.tsx +50 -0
- package/docs/general/actions.tsx +175 -0
- package/docs/general/float-button.tsx +133 -0
- package/docs/general/typography.tsx +63 -1
- package/docs/layout/draggable-panel.tsx +127 -0
- package/docs/navigation/conversations.tsx +176 -0
- package/docs/roadmap/parity-audit-layout-navigation-general.md +17 -16
- package/package.json +20 -4
- package/scripts/_agent-setup.mjs +36 -5
- package/scripts/guinea-pig-skill.md +14 -0
- package/scripts/ui-audit.mjs +69 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ImageIcon } from "lucide-react";
|
|
3
|
+
import { ResponsiveGrid } from "../layout/responsive-grid.js";
|
|
3
4
|
import { cn } from "../../lib/utils.js";
|
|
4
5
|
import { tableCellPaddingClass, tableRowHeightClass } from "../../lib/control-styles.js";
|
|
5
6
|
function measureStyle(width) {
|
|
@@ -169,6 +170,12 @@ function SkeletonRows({ rows = 6, columns = 4, className }) {
|
|
|
169
170
|
j
|
|
170
171
|
)) }, i)) });
|
|
171
172
|
}
|
|
173
|
+
function SkeletonForm({ columns = 1, fields = 6, active, className }) {
|
|
174
|
+
return /* @__PURE__ */ jsx("div", { className: cn("ui-skeleton-form", className), "aria-busy": "true", children: /* @__PURE__ */ jsx(ResponsiveGrid, { columns, children: Array.from({ length: fields }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "ui-skeleton-form-field", children: [
|
|
175
|
+
/* @__PURE__ */ jsx(Skeleton, { active, className: "ui-skeleton-form-label" }),
|
|
176
|
+
/* @__PURE__ */ jsx(Skeleton, { active, className: "ui-skeleton-form-control" })
|
|
177
|
+
] }, i)) }) });
|
|
178
|
+
}
|
|
172
179
|
function SkeletonTable({ rows = 8, columns = 5 }) {
|
|
173
180
|
return /* @__PURE__ */ jsxs("div", { className: "ui-skeleton-table", "aria-busy": "true", children: [
|
|
174
181
|
/* @__PURE__ */ jsx("div", { className: cn("ui-skeleton-table-head", tableCellPaddingClass, tableRowHeightClass), children: Array.from({ length: columns }).map((_, j) => /* @__PURE__ */ jsx(Skeleton, { className: cn("ui-skeleton-caption", j === 0 ? "w-1/5" : "flex-1") }, j)) }),
|
|
@@ -205,6 +212,7 @@ export {
|
|
|
205
212
|
SkeletonAvatar,
|
|
206
213
|
SkeletonButton,
|
|
207
214
|
SkeletonDetail,
|
|
215
|
+
SkeletonForm,
|
|
208
216
|
SkeletonImage,
|
|
209
217
|
SkeletonInput,
|
|
210
218
|
SkeletonNode,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ActionsCopyProp, ActionsFeedbackProp, ActionsItemProp, ActionsProp } from "../../props/components/general.prop.js";
|
|
3
|
+
export type { ActionsProp, ActionsProp as ActionsProps, ActionsItemsProp, ActionsItemProp, ActionsItemProp as ActionsItemProps, ActionsCopyProp, ActionsCopyProp as ActionsCopyProps, ActionsFeedbackProp, ActionsFeedbackProp as ActionsFeedbackProps, ActionsVariantProp, ActionsStatusProp, ActionsFeedbackValueProp, } from "../../props/components/general.prop.js";
|
|
4
|
+
/**
|
|
5
|
+
* Actions — the strip of actions under an assistant message (Ant Design X `Actions`).
|
|
6
|
+
*
|
|
7
|
+
* ## What Ant X ships, measured
|
|
8
|
+
*
|
|
9
|
+
* `@ant-design/x@2.9.0`, `es/actions/Item.js`: each action is
|
|
10
|
+
* `<div className="…-item" onClick>` wrapping `<div className="…-icon">{item.icon}</div>`, with
|
|
11
|
+
* the label supplied only as a `Tooltip` title. Three consequences, all of them defects rather
|
|
12
|
+
* than choices: the strip cannot be reached by keyboard at all, the actions have no accessible
|
|
13
|
+
* name, and on a touch device — where `useMobile()` drops the Tooltip entirely — they have no
|
|
14
|
+
* visible name either.
|
|
15
|
+
*
|
|
16
|
+
* ## What this port does about it, while keeping the API
|
|
17
|
+
*
|
|
18
|
+
* `items`, `onClick({ item, key, keyPath, domEvent })`, `onItemClick` winning over `onClick`,
|
|
19
|
+
* `danger`, `subItems`, `actionRender`, `variant`, `fadeIn` / `fadeInLeft` — all Ant's, with Ant's
|
|
20
|
+
* semantics. What changes is what they render onto: a real `Button` per action carrying `label` as
|
|
21
|
+
* its accessible name AND its tooltip, inside a WAI-ARIA APG **Toolbar** — one tab stop for the
|
|
22
|
+
* whole strip, the logical arrows moving between the actions, `Home` / `End` at its ends. That is
|
|
23
|
+
* the same trade `Conversations` makes and for the same reason: a strip of eight actions under
|
|
24
|
+
* every message would otherwise be eight tab stops between the reader and the next message.
|
|
25
|
+
*/
|
|
26
|
+
export declare const Actions: React.ForwardRefExoticComponent<ActionsProp & React.RefAttributes<HTMLDivElement>>;
|
|
27
|
+
/**
|
|
28
|
+
* ActionsItem — one status-aware action (Ant Design X `Actions.Item`).
|
|
29
|
+
*
|
|
30
|
+
* It is a NAMED export rather than `Actions.Item`, because this library has no compound-static
|
|
31
|
+
* convention: `CardHeader`, `TabsList` and `DropdownMenuItem` are all separate exports, and one
|
|
32
|
+
* component attaching statics would be the only one of its kind.
|
|
33
|
+
*
|
|
34
|
+
* The status table is Ant's, from `es/actions/ActionsItem.js`: `loading` and `error` bring their
|
|
35
|
+
* own glyph, `running` takes `runningIcon`, anything else takes `defaultIcon`. What is added is
|
|
36
|
+
* that the status is ANNOUNCED — `aria-busy` while loading, and the state in the accessible name —
|
|
37
|
+
* because a glyph swap is a colour-and-shape-only signal (WCAG 1.4.1).
|
|
38
|
+
*/
|
|
39
|
+
export declare const ActionsItem: React.ForwardRefExoticComponent<ActionsItemProp & React.RefAttributes<HTMLButtonElement>>;
|
|
40
|
+
/**
|
|
41
|
+
* ActionsCopy — copy the message to the clipboard (Ant Design X `Actions.Copy`).
|
|
42
|
+
*
|
|
43
|
+
* Ant X hands this to antd's `Typography copyable`, which swaps the glyph to a tick for 3s. The
|
|
44
|
+
* tick is reproduced at the same 3s, and the change is also SPOKEN through a polite status region:
|
|
45
|
+
* a glyph that only changes shape tells a screen-reader user nothing about whether the copy
|
|
46
|
+
* worked, which is the one thing this control exists to report.
|
|
47
|
+
*/
|
|
48
|
+
export declare const ActionsCopy: React.ForwardRefExoticComponent<ActionsCopyProp & React.RefAttributes<HTMLButtonElement>>;
|
|
49
|
+
/**
|
|
50
|
+
* ActionsFeedback — the like / dislike pair (Ant Design X `Actions.Feedback`).
|
|
51
|
+
*
|
|
52
|
+
* `value` / `onChange` and the clear-on-second-click behaviour are Ant's, byte for byte. ONE
|
|
53
|
+
* rendering difference, and it is deliberate: Ant hides the opposite button once an opinion is
|
|
54
|
+
* recorded (`[default, like].includes(value) && likeNode`), so a reader who mis-clicked "dislike"
|
|
55
|
+
* finds no "like" button on the screen at all and has to guess that clicking dislike again brings
|
|
56
|
+
* it back. Both buttons stay here, and the recorded opinion is carried by `aria-pressed` — the APG
|
|
57
|
+
* toggle-button pattern, which states the value instead of removing its alternative.
|
|
58
|
+
*/
|
|
59
|
+
export declare const ActionsFeedback: React.ForwardRefExoticComponent<ActionsFeedbackProp & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Check, Copy, MoreHorizontal, ThumbsDown, ThumbsUp, TriangleAlert } from "lucide-react";
|
|
5
|
+
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../feedback/tooltip.js";
|
|
8
|
+
import {
|
|
9
|
+
DropdownMenu,
|
|
10
|
+
DropdownMenuContent,
|
|
11
|
+
DropdownMenuItem,
|
|
12
|
+
DropdownMenuTrigger
|
|
13
|
+
} from "../navigation/dropdown-menu.js";
|
|
14
|
+
import { Button } from "./button.js";
|
|
15
|
+
import { VisuallyHidden } from "./visually-hidden.js";
|
|
16
|
+
function isRtl(element) {
|
|
17
|
+
return element?.closest("[dir]")?.getAttribute("dir")?.toLowerCase() === "rtl";
|
|
18
|
+
}
|
|
19
|
+
function LabelledIconButton({
|
|
20
|
+
label,
|
|
21
|
+
children,
|
|
22
|
+
...props
|
|
23
|
+
}) {
|
|
24
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
25
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { type: "button", size: "icon-sm", variant: "ghost", "aria-label": label, ...props, children }) }),
|
|
26
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: label })
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
const Actions = React.forwardRef(
|
|
30
|
+
({ items, onClick, variant = "borderless", fadeIn, fadeInLeft, label, id, className, ...rest }, ref) => {
|
|
31
|
+
const { t } = useTranslation();
|
|
32
|
+
const nodes = React.useRef(/* @__PURE__ */ new Map());
|
|
33
|
+
const [focusKey, setFocusKey] = React.useState(null);
|
|
34
|
+
const navKeys = items.filter((item) => !item.actionRender).map((item) => item.key);
|
|
35
|
+
const tabStop = focusKey && navKeys.includes(focusKey) ? focusKey : navKeys[0];
|
|
36
|
+
const moveTo = (key) => {
|
|
37
|
+
if (!key) return;
|
|
38
|
+
setFocusKey(key);
|
|
39
|
+
nodes.current.get(key)?.focus();
|
|
40
|
+
};
|
|
41
|
+
const handleKeyDown = (key) => (event) => {
|
|
42
|
+
const rtl = isRtl(event.currentTarget);
|
|
43
|
+
const forward = rtl ? "ArrowLeft" : "ArrowRight";
|
|
44
|
+
const backward = rtl ? "ArrowRight" : "ArrowLeft";
|
|
45
|
+
const index = navKeys.indexOf(key);
|
|
46
|
+
if (event.key === forward) {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
moveTo(navKeys[(index + 1) % navKeys.length]);
|
|
49
|
+
} else if (event.key === backward) {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
moveTo(navKeys[(index - 1 + navKeys.length) % navKeys.length]);
|
|
52
|
+
} else if (event.key === "Home") {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
moveTo(navKeys[0]);
|
|
55
|
+
} else if (event.key === "End") {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
moveTo(navKeys[navKeys.length - 1]);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const dispatch = (item, keyPath, domEvent) => {
|
|
61
|
+
if (item.onItemClick) {
|
|
62
|
+
item.onItemClick(item);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
onClick?.({ item, key: keyPath[0], keyPath, domEvent });
|
|
66
|
+
};
|
|
67
|
+
return /* @__PURE__ */ jsx(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
ref,
|
|
71
|
+
id,
|
|
72
|
+
role: "toolbar",
|
|
73
|
+
"aria-label": label ?? t("general.actions.label"),
|
|
74
|
+
"aria-orientation": "horizontal",
|
|
75
|
+
"data-slot": "actions",
|
|
76
|
+
"data-variant": variant,
|
|
77
|
+
"data-fade-in": fadeIn || fadeInLeft ? "" : void 0,
|
|
78
|
+
"data-fade-in-inline": fadeInLeft ? "" : void 0,
|
|
79
|
+
className: cn("ui-actions", className),
|
|
80
|
+
...rest,
|
|
81
|
+
children: items.map((item) => {
|
|
82
|
+
if (item.actionRender) {
|
|
83
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: typeof item.actionRender === "function" ? item.actionRender(item) : item.actionRender }, item.key);
|
|
84
|
+
}
|
|
85
|
+
const name = item.label ?? item.key;
|
|
86
|
+
const shared = {
|
|
87
|
+
ref: (node) => {
|
|
88
|
+
if (node) nodes.current.set(item.key, node);
|
|
89
|
+
else nodes.current.delete(item.key);
|
|
90
|
+
},
|
|
91
|
+
tabIndex: tabStop === item.key ? 0 : -1,
|
|
92
|
+
onFocus: () => setFocusKey(item.key),
|
|
93
|
+
onKeyDown: handleKeyDown(item.key),
|
|
94
|
+
variant: item.danger ? "destructive" : "ghost"
|
|
95
|
+
};
|
|
96
|
+
if (item.subItems && item.subItems.length > 0) {
|
|
97
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
98
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { type: "button", size: "icon-sm", "aria-label": name, ...shared, children: item.icon ?? /* @__PURE__ */ jsx(MoreHorizontal, { "aria-hidden": "true" }) }) }),
|
|
99
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", children: item.subItems.map((sub) => /* @__PURE__ */ jsxs(
|
|
100
|
+
DropdownMenuItem,
|
|
101
|
+
{
|
|
102
|
+
variant: sub.danger ? "destructive" : void 0,
|
|
103
|
+
onSelect: (event) => dispatch(
|
|
104
|
+
sub,
|
|
105
|
+
[sub.key, item.key],
|
|
106
|
+
event
|
|
107
|
+
),
|
|
108
|
+
children: [
|
|
109
|
+
sub.icon,
|
|
110
|
+
sub.label ?? sub.key
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
sub.key
|
|
114
|
+
)) })
|
|
115
|
+
] }, item.key);
|
|
116
|
+
}
|
|
117
|
+
return /* @__PURE__ */ jsx(
|
|
118
|
+
LabelledIconButton,
|
|
119
|
+
{
|
|
120
|
+
label: name,
|
|
121
|
+
onClick: (event) => dispatch(item, [item.key], event),
|
|
122
|
+
...shared,
|
|
123
|
+
children: item.icon
|
|
124
|
+
},
|
|
125
|
+
item.key
|
|
126
|
+
);
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
Actions.displayName = "Actions";
|
|
133
|
+
const ActionsItem = React.forwardRef(
|
|
134
|
+
({ status = "default", defaultIcon, runningIcon, label, id, className, ...rest }, ref) => {
|
|
135
|
+
const { t } = useTranslation();
|
|
136
|
+
const base = label ?? t("general.actions.label");
|
|
137
|
+
const name = status === "default" ? base : `${base} \xB7 ${t(`general.actions.status.${status}`)}`;
|
|
138
|
+
const glyph = status === "loading" ? null : status === "error" ? /* @__PURE__ */ jsx(TriangleAlert, { "aria-hidden": "true" }) : status === "running" ? runningIcon ?? defaultIcon : defaultIcon;
|
|
139
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
140
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
141
|
+
Button,
|
|
142
|
+
{
|
|
143
|
+
ref,
|
|
144
|
+
id,
|
|
145
|
+
type: "button",
|
|
146
|
+
size: "icon-sm",
|
|
147
|
+
variant: "ghost",
|
|
148
|
+
"data-slot": "actions-item",
|
|
149
|
+
"data-status": status,
|
|
150
|
+
"aria-label": name,
|
|
151
|
+
"aria-busy": status === "loading" || void 0,
|
|
152
|
+
loading: status === "loading",
|
|
153
|
+
className: cn("ui-actions-item", className),
|
|
154
|
+
...rest,
|
|
155
|
+
children: glyph
|
|
156
|
+
}
|
|
157
|
+
) }),
|
|
158
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: name })
|
|
159
|
+
] });
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
ActionsItem.displayName = "ActionsItem";
|
|
163
|
+
const ActionsCopy = React.forwardRef(
|
|
164
|
+
({ text = "", icon, label, onCopy, id, className, ...rest }, ref) => {
|
|
165
|
+
const { t } = useTranslation();
|
|
166
|
+
const [copied, setCopied] = React.useState(false);
|
|
167
|
+
const timer = React.useRef(void 0);
|
|
168
|
+
React.useEffect(() => () => clearTimeout(timer.current), []);
|
|
169
|
+
const name = label ?? t("general.actions.copy");
|
|
170
|
+
const run = async () => {
|
|
171
|
+
try {
|
|
172
|
+
await navigator.clipboard?.writeText(text);
|
|
173
|
+
} catch {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
onCopy?.(text);
|
|
177
|
+
setCopied(true);
|
|
178
|
+
clearTimeout(timer.current);
|
|
179
|
+
timer.current = setTimeout(() => setCopied(false), 3e3);
|
|
180
|
+
};
|
|
181
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
182
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
183
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
184
|
+
Button,
|
|
185
|
+
{
|
|
186
|
+
ref,
|
|
187
|
+
id,
|
|
188
|
+
type: "button",
|
|
189
|
+
size: "icon-sm",
|
|
190
|
+
variant: "ghost",
|
|
191
|
+
"data-slot": "actions-copy",
|
|
192
|
+
"data-copied": copied ? "" : void 0,
|
|
193
|
+
"aria-label": name,
|
|
194
|
+
className: cn("ui-actions-copy", className),
|
|
195
|
+
onClick: run,
|
|
196
|
+
...rest,
|
|
197
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }) : icon ?? /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true" })
|
|
198
|
+
}
|
|
199
|
+
) }),
|
|
200
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: name })
|
|
201
|
+
] }),
|
|
202
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { role: "status", "aria-live": "polite", children: copied ? t("general.actions.copied") : "" })
|
|
203
|
+
] });
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
ActionsCopy.displayName = "ActionsCopy";
|
|
207
|
+
const ActionsFeedback = React.forwardRef(
|
|
208
|
+
({ value = "default", onChange, label, likeLabel, dislikeLabel, id, className, ...rest }, ref) => {
|
|
209
|
+
const { t } = useTranslation();
|
|
210
|
+
const toggle = (next) => onChange?.(value === next ? "default" : next);
|
|
211
|
+
return /* @__PURE__ */ jsxs(
|
|
212
|
+
"div",
|
|
213
|
+
{
|
|
214
|
+
ref,
|
|
215
|
+
id,
|
|
216
|
+
role: "group",
|
|
217
|
+
"aria-label": label ?? t("general.actions.feedback"),
|
|
218
|
+
"data-slot": "actions-feedback",
|
|
219
|
+
className: cn("ui-actions-feedback", className),
|
|
220
|
+
...rest,
|
|
221
|
+
children: [
|
|
222
|
+
/* @__PURE__ */ jsx(
|
|
223
|
+
LabelledIconButton,
|
|
224
|
+
{
|
|
225
|
+
label: likeLabel ?? t("general.actions.like"),
|
|
226
|
+
"aria-pressed": value === "like",
|
|
227
|
+
"data-pressed": value === "like" ? "" : void 0,
|
|
228
|
+
onClick: () => toggle("like"),
|
|
229
|
+
children: /* @__PURE__ */ jsx(ThumbsUp, { "aria-hidden": "true" })
|
|
230
|
+
}
|
|
231
|
+
),
|
|
232
|
+
/* @__PURE__ */ jsx(
|
|
233
|
+
LabelledIconButton,
|
|
234
|
+
{
|
|
235
|
+
label: dislikeLabel ?? t("general.actions.dislike"),
|
|
236
|
+
"aria-pressed": value === "dislike",
|
|
237
|
+
"data-pressed": value === "dislike" ? "" : void 0,
|
|
238
|
+
onClick: () => toggle("dislike"),
|
|
239
|
+
children: /* @__PURE__ */ jsx(ThumbsDown, { "aria-hidden": "true" })
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
ActionsFeedback.displayName = "ActionsFeedback";
|
|
248
|
+
export {
|
|
249
|
+
Actions,
|
|
250
|
+
ActionsCopy,
|
|
251
|
+
ActionsFeedback,
|
|
252
|
+
ActionsItem
|
|
253
|
+
};
|
|
@@ -6,6 +6,7 @@ import { cva } from "class-variance-authority";
|
|
|
6
6
|
import { Loader2 } from "lucide-react";
|
|
7
7
|
import { cn } from "../../lib/utils.js";
|
|
8
8
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
9
|
+
import { numberFormat } from "../../lib/intl-cache.js";
|
|
9
10
|
const buttonVariants = cva("ui-button", {
|
|
10
11
|
variants: {
|
|
11
12
|
variant: {
|
|
@@ -78,7 +79,7 @@ const Button = React.forwardRef(
|
|
|
78
79
|
loadingText ?? children
|
|
79
80
|
] }) : children;
|
|
80
81
|
const showCount = !asChild && count != null && (count !== 0 || showZero);
|
|
81
|
-
const countLabel = showCount && count != null && count > overflowCount ? `${
|
|
82
|
+
const countLabel = showCount && count != null && count > overflowCount ? `${numberFormat(locale).format(overflowCount)}+` : count != null ? numberFormat(locale).format(count) : "";
|
|
82
83
|
const countNode = showCount ? /* @__PURE__ */ jsx("span", { "data-slot": "button-count", className: "ui-button-count", children: countLabel }) : null;
|
|
83
84
|
return /* @__PURE__ */ jsx(
|
|
84
85
|
Comp,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { FloatButtonBackTopProp, FloatButtonGroupProp, FloatButtonShapeProp, FloatButtonTooltipProp, FloatButtonTypeProp } from "../../props/components/general.prop.js";
|
|
3
|
+
export type { FloatButtonBackTopProp, FloatButtonBackTopProp as FloatButtonBackTopProps, FloatButtonBadgeProp, FloatButtonGroupProp, FloatButtonGroupProp as FloatButtonGroupProps, FloatButtonPlacementProp, FloatButtonProp, FloatButtonProp as FloatButtonProps, FloatButtonShapeProp, FloatButtonTooltipProp, FloatButtonTriggerProp, FloatButtonTypeProp, } from "../../props/components/general.prop.js";
|
|
4
|
+
/**
|
|
5
|
+
* FloatButton.Group — a stack of corner actions, optionally behind one trigger.
|
|
6
|
+
*
|
|
7
|
+
* Two modes, and `trigger` is the switch, exactly as in antd: WITHOUT it every child is visible and
|
|
8
|
+
* no trigger is drawn; WITH it the children collapse behind a trigger that opens them on click or
|
|
9
|
+
* on hover.
|
|
10
|
+
*/
|
|
11
|
+
declare function FloatButtonGroup({ children, trigger, open, onOpenChange, closeIcon, placement, shape, type, icon, disabled, className, onClick, ...rest }: FloatButtonGroupProp): React.JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* FloatButton.BackTop — the corner action that returns a scroll container to the top.
|
|
14
|
+
*
|
|
15
|
+
* `target` is antd's, and it is the answer to the objection that a document-bound BackTop competes
|
|
16
|
+
* with a shell that owns its own scroll: pass `() => element` and this watches that element, not
|
|
17
|
+
* the document. Under `prefers-reduced-motion` the scroll is instant rather than tweened
|
|
18
|
+
* (WCAG 2.3.3), which is antd's behaviour too.
|
|
19
|
+
*/
|
|
20
|
+
declare function FloatButtonBackTop({ visibilityHeight, target, duration, showProgress, onClick, icon, tooltip, className, ...rest }: FloatButtonBackTopProp): React.JSX.Element | null;
|
|
21
|
+
/**
|
|
22
|
+
* The compound, exactly as antd exports it: one name, two sub-parts on it. A consumer porting a
|
|
23
|
+
* screen writes `<FloatButton.Group>` / `<FloatButton.BackTop>` unchanged.
|
|
24
|
+
*/
|
|
25
|
+
export declare const FloatButton: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color" | "content" | "type"> & {
|
|
26
|
+
icon?: import("../../props/index.js").ChildrenProp;
|
|
27
|
+
description?: import("../../props/index.js").DescriptionProp;
|
|
28
|
+
content?: import("../../props/index.js").ChildrenProp;
|
|
29
|
+
type?: FloatButtonTypeProp;
|
|
30
|
+
shape?: FloatButtonShapeProp;
|
|
31
|
+
tooltip?: import("../../props/index.js").ChildrenProp | FloatButtonTooltipProp;
|
|
32
|
+
href?: string;
|
|
33
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
34
|
+
badge?: import("./float-button.js").FloatButtonBadgeProp;
|
|
35
|
+
disabled?: import("../../props/index.js").DisabledProp;
|
|
36
|
+
htmlType?: "button" | "submit" | "reset";
|
|
37
|
+
className?: import("../../props/index.js").ClassNameProp;
|
|
38
|
+
} & React.RefAttributes<HTMLElement>> & {
|
|
39
|
+
Group: typeof FloatButtonGroup;
|
|
40
|
+
BackTop: typeof FloatButtonBackTop;
|
|
41
|
+
};
|