@godxjp/ui 23.3.0 → 23.4.1
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/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/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/feedback/dialog.d.ts +10 -7
- package/dist/components/feedback/dialog.js +40 -17
- package/dist/components/feedback/index.d.ts +1 -1
- 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/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/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/i18n/messages/en.json +53 -0
- package/dist/i18n/messages/ja.json +53 -0
- package/dist/i18n/messages/vi.json +53 -0
- package/dist/props/components/data-display.prop.d.ts +143 -1
- package/dist/props/components/data-entry.prop.d.ts +76 -0
- package/dist/props/components/feedback.prop.d.ts +34 -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 +426 -0
- package/dist/props/registry.js +546 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +113 -0
- package/dist/styles/card-layout.css +30 -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/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/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 +2 -0
- package/docs/DESIGN-AUTHORITY.md +89 -0
- 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 +3 -3
- package/scripts/ui-audit.mjs +66 -2
|
@@ -2,6 +2,9 @@ import type { GapProp, PadProp, PadRawProp } from "../../props/vocabulary/index.
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import type { LucideIcon } from "lucide-react";
|
|
4
4
|
import type { HeadingLevelProp } from "../../props/vocabulary/index.js";
|
|
5
|
+
import type { CardTabItemProp } from "../../props/components/data-display.prop.js";
|
|
6
|
+
import { type TabsExtraProp, type TabsProps } from "../navigation/tabs.js";
|
|
7
|
+
export type { CardTabItemProp, CardTabItemProp as CardTabItemProps, } from "../../props/components/data-display.prop.js";
|
|
5
8
|
/** Semantic accent tone. `accentPlacement` decides WHERE it is drawn — a leading-edge
|
|
6
9
|
* stripe (default) or the full perimeter. */
|
|
7
10
|
type CardAccent = "primary" | "success" | "warning" | "info" | "attention" | "destructive";
|
|
@@ -41,6 +44,48 @@ export type CardProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
|
41
44
|
* bare `onClick` on this div, which a keyboard or screen-reader user cannot reach.
|
|
42
45
|
*/
|
|
43
46
|
hoverable?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Ant Design `tabList` — the tab strip that lives IN THE CARD'S HEAD, under the title, inside
|
|
49
|
+
* the same border and on the same surface, so the card and its tabs read as one object. The
|
|
50
|
+
* card's remaining children become the selected tab's body.
|
|
51
|
+
*
|
|
52
|
+
* Ported name for name and semantic for semantic (docs/DESIGN-AUTHORITY.md): the entry is
|
|
53
|
+
* antd's `{ key, tab, disabled }`, not the `Tabs` component's `{ value, label, content }`.
|
|
54
|
+
* @see CardTabItemProp for why the two item shapes stay apart.
|
|
55
|
+
*/
|
|
56
|
+
tabList?: CardTabItemProp[];
|
|
57
|
+
/** Ant Design `activeTabKey` — the controlled selection. Pair it with `onTabChange`. */
|
|
58
|
+
activeTabKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Ant Design `defaultActiveTabKey` — the uncontrolled initial selection. Without it the first
|
|
61
|
+
* entry of `tabList` opens, which is antd's own fallback.
|
|
62
|
+
*/
|
|
63
|
+
defaultActiveTabKey?: string;
|
|
64
|
+
/** Ant Design `onTabChange` — fires with the newly selected `key`, however the selection moved. */
|
|
65
|
+
onTabChange?: (key: string) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Ant Design `tabBarExtraContent`, RENAMED to `extra` and made logical — the one deviation from
|
|
68
|
+
* antd's spelling here, and it follows the precedent this package already set on
|
|
69
|
+
* `TabsProp.extra` ("Ant Design `tabBarExtraContent`, renamed and made logical"). A second
|
|
70
|
+
* spelling of a slot the package has already named once is exactly what
|
|
71
|
+
* `check:prop-vocabulary` exists to prevent, and antd's `{ left, right }` keys cannot mirror
|
|
72
|
+
* for an RTL locale where `{ start, end }` can.
|
|
73
|
+
*
|
|
74
|
+
* Inert without `tabList`: antd draws this content in the tab bar, and with no tab bar there is
|
|
75
|
+
* nowhere for it to go. A header-level action is `<CardAction>` inside `<CardHeader>`.
|
|
76
|
+
*/
|
|
77
|
+
extra?: TabsExtraProp;
|
|
78
|
+
/**
|
|
79
|
+
* Ant Design `tabProps` — passed straight down to the `Tabs` that draws the strip, so
|
|
80
|
+
* `variant`, `size`, `centered`, `overflow`, `indicator` and the rest are reachable.
|
|
81
|
+
*
|
|
82
|
+
* The four fields the CARD owns are omitted rather than passed through: `items` is built from
|
|
83
|
+
* `tabList`, and `value` / `defaultValue` / `onValueChange` are what `activeTabKey` /
|
|
84
|
+
* `defaultActiveTabKey` / `onTabChange` already say. antd drops the same fields — it spreads
|
|
85
|
+
* `tabProps` first and then writes its own `items`/`activeKey`/`onChange` over them — so this
|
|
86
|
+
* is that behaviour made visible in the type instead of silent at runtime.
|
|
87
|
+
*/
|
|
88
|
+
tabProps?: Omit<TabsProps, "items" | "value" | "defaultValue" | "onValueChange" | "extra" | "children">;
|
|
44
89
|
};
|
|
45
90
|
export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
46
91
|
accent?: CardAccent;
|
|
@@ -61,6 +106,48 @@ export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<
|
|
|
61
106
|
* bare `onClick` on this div, which a keyboard or screen-reader user cannot reach.
|
|
62
107
|
*/
|
|
63
108
|
hoverable?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Ant Design `tabList` — the tab strip that lives IN THE CARD'S HEAD, under the title, inside
|
|
111
|
+
* the same border and on the same surface, so the card and its tabs read as one object. The
|
|
112
|
+
* card's remaining children become the selected tab's body.
|
|
113
|
+
*
|
|
114
|
+
* Ported name for name and semantic for semantic (docs/DESIGN-AUTHORITY.md): the entry is
|
|
115
|
+
* antd's `{ key, tab, disabled }`, not the `Tabs` component's `{ value, label, content }`.
|
|
116
|
+
* @see CardTabItemProp for why the two item shapes stay apart.
|
|
117
|
+
*/
|
|
118
|
+
tabList?: CardTabItemProp[];
|
|
119
|
+
/** Ant Design `activeTabKey` — the controlled selection. Pair it with `onTabChange`. */
|
|
120
|
+
activeTabKey?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Ant Design `defaultActiveTabKey` — the uncontrolled initial selection. Without it the first
|
|
123
|
+
* entry of `tabList` opens, which is antd's own fallback.
|
|
124
|
+
*/
|
|
125
|
+
defaultActiveTabKey?: string;
|
|
126
|
+
/** Ant Design `onTabChange` — fires with the newly selected `key`, however the selection moved. */
|
|
127
|
+
onTabChange?: (key: string) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Ant Design `tabBarExtraContent`, RENAMED to `extra` and made logical — the one deviation from
|
|
130
|
+
* antd's spelling here, and it follows the precedent this package already set on
|
|
131
|
+
* `TabsProp.extra` ("Ant Design `tabBarExtraContent`, renamed and made logical"). A second
|
|
132
|
+
* spelling of a slot the package has already named once is exactly what
|
|
133
|
+
* `check:prop-vocabulary` exists to prevent, and antd's `{ left, right }` keys cannot mirror
|
|
134
|
+
* for an RTL locale where `{ start, end }` can.
|
|
135
|
+
*
|
|
136
|
+
* Inert without `tabList`: antd draws this content in the tab bar, and with no tab bar there is
|
|
137
|
+
* nowhere for it to go. A header-level action is `<CardAction>` inside `<CardHeader>`.
|
|
138
|
+
*/
|
|
139
|
+
extra?: TabsExtraProp;
|
|
140
|
+
/**
|
|
141
|
+
* Ant Design `tabProps` — passed straight down to the `Tabs` that draws the strip, so
|
|
142
|
+
* `variant`, `size`, `centered`, `overflow`, `indicator` and the rest are reachable.
|
|
143
|
+
*
|
|
144
|
+
* The four fields the CARD owns are omitted rather than passed through: `items` is built from
|
|
145
|
+
* `tabList`, and `value` / `defaultValue` / `onValueChange` are what `activeTabKey` /
|
|
146
|
+
* `defaultActiveTabKey` / `onTabChange` already say. antd drops the same fields — it spreads
|
|
147
|
+
* `tabProps` first and then writes its own `items`/`activeKey`/`onChange` over them — so this
|
|
148
|
+
* is that behaviour made visible in the type instead of silent at runtime.
|
|
149
|
+
*/
|
|
150
|
+
tabProps?: Omit<TabsProps, "items" | "value" | "defaultValue" | "onValueChange" | "extra" | "children">;
|
|
64
151
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
65
152
|
/** Full-bleed cover media — first child; header below uses section top (φ⁰), not shell. */
|
|
66
153
|
export type CardCoverProps = React.HTMLAttributes<HTMLDivElement>;
|
|
@@ -190,4 +277,3 @@ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
|
190
277
|
export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, accentPlacement, className, ...props }: StatCardProps): React.JSX.Element;
|
|
191
278
|
/** Header actions slot — compose beside CardTitle inside CardHeader; the header owns positioning. */
|
|
192
279
|
export declare const CardAction: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
193
|
-
export {};
|
|
@@ -1,22 +1,95 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { padStyle, padStepToken } from "../../lib/variants.js";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { Tabs } from "../navigation/tabs.js";
|
|
7
|
+
function resolveActiveCardTabKey(tabList, requested) {
|
|
8
|
+
if (requested !== void 0) {
|
|
9
|
+
const item = tabList.find((entry) => entry.key === requested);
|
|
10
|
+
if (item && !item.disabled) return requested;
|
|
11
|
+
}
|
|
12
|
+
return tabList.find((entry) => !entry.disabled)?.key;
|
|
13
|
+
}
|
|
14
|
+
function splitCardBands(children) {
|
|
15
|
+
const head = [];
|
|
16
|
+
const body = [];
|
|
17
|
+
const foot = [];
|
|
18
|
+
for (const child of React.Children.toArray(children)) {
|
|
19
|
+
const type = React.isValidElement(child) ? child.type : void 0;
|
|
20
|
+
if (type === CardCover || type === CardHeader) head.push(child);
|
|
21
|
+
else if (type === CardFooter) foot.push(child);
|
|
22
|
+
else body.push(child);
|
|
23
|
+
}
|
|
24
|
+
return { head, body, foot };
|
|
25
|
+
}
|
|
5
26
|
const Card = React.forwardRef(
|
|
6
|
-
({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
({
|
|
28
|
+
className,
|
|
29
|
+
accent,
|
|
30
|
+
accentPlacement,
|
|
31
|
+
variant,
|
|
32
|
+
density,
|
|
33
|
+
hoverable,
|
|
34
|
+
tabList,
|
|
35
|
+
activeTabKey,
|
|
36
|
+
defaultActiveTabKey,
|
|
37
|
+
onTabChange,
|
|
38
|
+
extra,
|
|
39
|
+
tabProps,
|
|
40
|
+
children,
|
|
41
|
+
...props
|
|
42
|
+
}, ref) => {
|
|
43
|
+
const [mirroredKey, setMirroredKey] = React.useState(void 0);
|
|
44
|
+
const activeKey = tabList?.length ? resolveActiveCardTabKey(tabList, activeTabKey ?? mirroredKey ?? defaultActiveTabKey) : void 0;
|
|
45
|
+
const handleTabChange = React.useCallback(
|
|
46
|
+
(key) => {
|
|
47
|
+
setMirroredKey(key);
|
|
48
|
+
onTabChange?.(key);
|
|
49
|
+
},
|
|
50
|
+
[onTabChange]
|
|
51
|
+
);
|
|
52
|
+
const { head, body, foot } = tabList?.length ? splitCardBands(children) : { head: void 0, body: void 0, foot: void 0 };
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
ref,
|
|
57
|
+
className: cn("group/card", className),
|
|
58
|
+
"data-slot": "card",
|
|
59
|
+
"data-accent": accent,
|
|
60
|
+
"data-hoverable": hoverable ? "" : void 0,
|
|
61
|
+
"data-accent-placement": accentPlacement === "perimeter" ? "perimeter" : void 0,
|
|
62
|
+
"data-variant": variant && variant !== "default" ? variant : void 0,
|
|
63
|
+
"data-density": density,
|
|
64
|
+
"data-tab-list": tabList?.length ? "" : void 0,
|
|
65
|
+
...props,
|
|
66
|
+
children: tabList?.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
|
+
head,
|
|
68
|
+
/* @__PURE__ */ jsx(
|
|
69
|
+
Tabs,
|
|
70
|
+
{
|
|
71
|
+
variant: "line",
|
|
72
|
+
...tabProps,
|
|
73
|
+
items: tabList.map((item) => ({
|
|
74
|
+
value: item.key,
|
|
75
|
+
label: item.tab,
|
|
76
|
+
disabled: item.disabled,
|
|
77
|
+
// The body belongs to the SELECTED tab and to no other: the card has exactly one
|
|
78
|
+
// set of children, so handing them to every panel would render them N times the
|
|
79
|
+
// moment `destroyOnHidden={false}` kept the hidden panels mounted.
|
|
80
|
+
content: item.key === activeKey ? body : null
|
|
81
|
+
})),
|
|
82
|
+
value: activeKey,
|
|
83
|
+
onValueChange: handleTabChange,
|
|
84
|
+
extra,
|
|
85
|
+
listClassName: cn("px-[var(--card-space-inset)]", tabProps?.listClassName)
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
foot
|
|
89
|
+
] }) : children
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
20
93
|
);
|
|
21
94
|
Card.displayName = "Card";
|
|
22
95
|
const CardCover = React.forwardRef(
|
|
@@ -17,7 +17,7 @@ export type { QrCodeProps } from "./qr-code.js";
|
|
|
17
17
|
export type { QrCodeProp } from "../../props/components/data-display.prop.js";
|
|
18
18
|
export { Avatar, AvatarImage, AvatarFallback } from "./avatar.js";
|
|
19
19
|
export { Card, CardBar, CardContent, CardCover, CardDescription, CardFooter, CardHeader, CardTitle, CardAction, StatCard, } from "./card.js";
|
|
20
|
-
export type { StatCardProps, CardBarProps } from "./card.js";
|
|
20
|
+
export type { StatCardProps, CardBarProps, CardTabItemProp, CardTabItemProps } from "./card.js";
|
|
21
21
|
export { ServiceCatalogCta, ServiceLauncherCard, ServiceLauncherCardSkeleton, } from "./service-launcher-card.js";
|
|
22
22
|
export type { ServiceCatalogCtaProps, ServiceLauncherCardProps, ServiceLauncherCardSkeletonProps, ServiceLauncherStatusTone, } from "./service-launcher-card.js";
|
|
23
23
|
export { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table.js";
|
|
@@ -51,3 +51,7 @@ export { ChatBubble, ChatBubbleList } from "./chat-bubble.js";
|
|
|
51
51
|
export type { ChatBubbleListProp, ChatBubbleListProps, ChatBubblePlacementProp, ChatBubbleProp, ChatBubbleProps, ChatBubbleToneProp, ChatBubbleTypingProp, ChatBubbleVariantProp, ChatMessageProp, } from "./chat-bubble.js";
|
|
52
52
|
export { Tree } from "./tree.js";
|
|
53
53
|
export type { TreeNodeProp, TreeProp, TreeProps } from "./tree.js";
|
|
54
|
+
export { Welcome } from "./welcome.js";
|
|
55
|
+
export type { WelcomeProp, WelcomeProps, WelcomeVariantProp } from "./welcome.js";
|
|
56
|
+
export { ThoughtChain, ThoughtChainItem } from "./thought-chain.js";
|
|
57
|
+
export type { ThoughtChainProp, ThoughtChainProps, ThoughtChainItemsProp, ThoughtChainItemProp, ThoughtChainItemProps, ThoughtChainStatusProp, ThoughtChainLineProp, ThoughtChainVariantProp, } from "./thought-chain.js";
|
|
@@ -59,6 +59,8 @@ import { PermissionMatrix } from "./permission-matrix.js";
|
|
|
59
59
|
import { RangeTimeline } from "./range-timeline.js";
|
|
60
60
|
import { ChatBubble, ChatBubbleList } from "./chat-bubble.js";
|
|
61
61
|
import { Tree } from "./tree.js";
|
|
62
|
+
import { Welcome } from "./welcome.js";
|
|
63
|
+
import { ThoughtChain, ThoughtChainItem } from "./thought-chain.js";
|
|
62
64
|
export {
|
|
63
65
|
Accordion,
|
|
64
66
|
AccordionContent,
|
|
@@ -125,10 +127,13 @@ export {
|
|
|
125
127
|
TableHead,
|
|
126
128
|
TableHeader,
|
|
127
129
|
TableRow,
|
|
130
|
+
ThoughtChain,
|
|
131
|
+
ThoughtChainItem,
|
|
128
132
|
Thumbnail,
|
|
129
133
|
Timeline,
|
|
130
134
|
TimelineGrid,
|
|
131
135
|
Tree,
|
|
136
|
+
Welcome,
|
|
132
137
|
flexRender,
|
|
133
138
|
useCarousel
|
|
134
139
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ThoughtChainItemProp, ThoughtChainProp } from "../../props/components/data-display.prop.js";
|
|
3
|
+
export type { ThoughtChainProp, ThoughtChainProp as ThoughtChainProps, ThoughtChainItemsProp, ThoughtChainItemProp, ThoughtChainItemProp as ThoughtChainItemProps, ThoughtChainStatusProp, ThoughtChainLineProp, ThoughtChainVariantProp, } from "../../props/components/data-display.prop.js";
|
|
4
|
+
/**
|
|
5
|
+
* ThoughtChain — the assistant's reasoning, step by step (Ant Design X `ThoughtChain`).
|
|
6
|
+
*
|
|
7
|
+
* ## The shape, and why it is an `<ol>`
|
|
8
|
+
*
|
|
9
|
+
* Ant renders the whole chain as nested `<div>`s and paints the step number itself
|
|
10
|
+
* (`index + 1` in `es/thought-chain/Node.js`). The order of the steps IS the content here — step 3
|
|
11
|
+
* only makes sense after step 2 — so the chain is an ordered list and a screen reader gets "list,
|
|
12
|
+
* 4 items" plus each step's position for free. The visible ordinal stays, because the same number
|
|
13
|
+
* has to be on screen for a sighted reader following a long chain.
|
|
14
|
+
*
|
|
15
|
+
* ## The disclosure is a real button
|
|
16
|
+
*
|
|
17
|
+
* A `collapsible` step's title in Ant is a `<div onClick>` with a rotating chevron — no role, no
|
|
18
|
+
* `tabIndex`, no `aria-expanded`. Here it is a `<button aria-expanded aria-controls>` over the
|
|
19
|
+
* body it opens: the WAI-ARIA APG Disclosure pattern, so the step can be opened from the keyboard
|
|
20
|
+
* and its state is announced rather than inferred from a rotation.
|
|
21
|
+
*
|
|
22
|
+
* Everything a caller passes keeps Ant's spelling: `items` (with `icon`, `title`, `description`,
|
|
23
|
+
* `content`, `footer`, `status`, `collapsible`, `blink`, `destroyOnHidden`), the
|
|
24
|
+
* `defaultExpandedKeys` / `expandedKeys` / `onExpand` triad, and `line`. `styles` / `classNames` /
|
|
25
|
+
* `prefixCls` / `rootClassName` are not ported — the standing style-hole decision
|
|
26
|
+
* (docs/WHAT-BELONGS-HERE.md, docs/DESIGN-AUTHORITY.md); the chain is retuned through
|
|
27
|
+
* `src/tokens/components/thought-chain.css`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ThoughtChain: React.ForwardRefExoticComponent<ThoughtChainProp & React.RefAttributes<HTMLOListElement>>;
|
|
30
|
+
/**
|
|
31
|
+
* ThoughtChainItem — one step OUTSIDE a chain (Ant Design X `ThoughtChain.Item`).
|
|
32
|
+
*
|
|
33
|
+
* A named export rather than `ThoughtChain.Item`, for the same reason `ActionsItem` is: every
|
|
34
|
+
* compound in this library is separate named exports (`CardHeader`, `TabsList`), and attaching
|
|
35
|
+
* statics to one component would be the only instance of it here.
|
|
36
|
+
*
|
|
37
|
+
* ONE DEVIATION: Ant renders the chip as a `<div>` and hangs `onClick` on it, so a clickable step
|
|
38
|
+
* is invisible to the keyboard and to assistive technology. Here an item WITH `onClick` renders a
|
|
39
|
+
* real `<button>` and one without renders a plain `<div>` — the element follows whether the thing
|
|
40
|
+
* is actually a control.
|
|
41
|
+
*/
|
|
42
|
+
export declare const ThoughtChainItem: React.ForwardRefExoticComponent<ThoughtChainItemProp & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronRight, CircleCheck, CircleMinus, CircleX, Loader2 } from "lucide-react";
|
|
5
|
+
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { VisuallyHidden } from "../general/visually-hidden.js";
|
|
8
|
+
import { Text } from "../general/typography.js";
|
|
9
|
+
const STATUS_GLYPH = {
|
|
10
|
+
loading: /* @__PURE__ */ jsx(Loader2, { "aria-hidden": "true", className: "ui-thought-chain-spinner" }),
|
|
11
|
+
success: /* @__PURE__ */ jsx(CircleCheck, { "aria-hidden": "true" }),
|
|
12
|
+
error: /* @__PURE__ */ jsx(CircleX, { "aria-hidden": "true" }),
|
|
13
|
+
abort: /* @__PURE__ */ jsx(CircleMinus, { "aria-hidden": "true" })
|
|
14
|
+
};
|
|
15
|
+
function StatusMark({
|
|
16
|
+
status,
|
|
17
|
+
fallback
|
|
18
|
+
}) {
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
if (!status) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
21
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22
|
+
STATUS_GLYPH[status],
|
|
23
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { children: t(`dataDisplay.thoughtChain.status.${status}`) })
|
|
24
|
+
] });
|
|
25
|
+
}
|
|
26
|
+
const ThoughtChain = React.forwardRef(
|
|
27
|
+
({
|
|
28
|
+
items = [],
|
|
29
|
+
defaultExpandedKeys,
|
|
30
|
+
expandedKeys,
|
|
31
|
+
onExpand,
|
|
32
|
+
line = true,
|
|
33
|
+
label,
|
|
34
|
+
id,
|
|
35
|
+
className,
|
|
36
|
+
...rest
|
|
37
|
+
}, ref) => {
|
|
38
|
+
const { t } = useTranslation();
|
|
39
|
+
const reactId = React.useId();
|
|
40
|
+
const [uncontrolled, setUncontrolled] = React.useState(() => [
|
|
41
|
+
...defaultExpandedKeys ?? []
|
|
42
|
+
]);
|
|
43
|
+
const open = expandedKeys ? [...expandedKeys] : uncontrolled;
|
|
44
|
+
const toggle = (key) => {
|
|
45
|
+
const next = open.includes(key) ? open.filter((k) => k !== key) : [...open, key];
|
|
46
|
+
if (!expandedKeys) setUncontrolled(next);
|
|
47
|
+
onExpand?.(next);
|
|
48
|
+
};
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
"ol",
|
|
51
|
+
{
|
|
52
|
+
ref,
|
|
53
|
+
id,
|
|
54
|
+
"aria-label": label ?? t("dataDisplay.thoughtChain.label"),
|
|
55
|
+
"data-slot": "thought-chain",
|
|
56
|
+
"data-line": line === false ? "none" : line === true ? "solid" : line,
|
|
57
|
+
className: cn("ui-thought-chain", className),
|
|
58
|
+
...rest,
|
|
59
|
+
children: items.map((item, index) => {
|
|
60
|
+
const key = item.key ?? `${reactId}-${index}`;
|
|
61
|
+
const bodyId = `${reactId}-body-${index}`;
|
|
62
|
+
const collapsible = Boolean(item.collapsible && item.content);
|
|
63
|
+
const expanded = collapsible ? open.includes(key) : true;
|
|
64
|
+
const glyph = item.icon === false ? null : item.icon ?? index + 1;
|
|
65
|
+
return /* @__PURE__ */ jsxs(
|
|
66
|
+
"li",
|
|
67
|
+
{
|
|
68
|
+
"data-slot": "thought-chain-node",
|
|
69
|
+
"data-status": item.status,
|
|
70
|
+
className: "ui-thought-chain-node",
|
|
71
|
+
children: [
|
|
72
|
+
glyph === null ? null : /* @__PURE__ */ jsx(
|
|
73
|
+
"span",
|
|
74
|
+
{
|
|
75
|
+
"data-slot": "thought-chain-icon",
|
|
76
|
+
"data-status": item.status,
|
|
77
|
+
className: "ui-thought-chain-icon",
|
|
78
|
+
children: /* @__PURE__ */ jsx(StatusMark, { status: item.status, fallback: glyph })
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-thought-chain-body", children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-thought-chain-header", children: [
|
|
83
|
+
collapsible ? /* @__PURE__ */ jsxs(
|
|
84
|
+
"button",
|
|
85
|
+
{
|
|
86
|
+
type: "button",
|
|
87
|
+
"aria-expanded": expanded,
|
|
88
|
+
"aria-controls": bodyId,
|
|
89
|
+
"data-blink": item.blink ? "" : void 0,
|
|
90
|
+
className: "ui-thought-chain-trigger",
|
|
91
|
+
onClick: () => toggle(key),
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
ChevronRight,
|
|
95
|
+
{
|
|
96
|
+
"aria-hidden": "true",
|
|
97
|
+
"data-expanded": expanded ? "true" : void 0,
|
|
98
|
+
className: "ui-thought-chain-chevron"
|
|
99
|
+
}
|
|
100
|
+
),
|
|
101
|
+
/* @__PURE__ */ jsx(Text, { weight: "medium", children: item.title })
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
) : /* @__PURE__ */ jsx(Text, { weight: "medium", "data-blink": item.blink ? "" : void 0, children: item.title }),
|
|
105
|
+
item.description ? /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: item.description }) : null
|
|
106
|
+
] }),
|
|
107
|
+
item.content && (expanded || item.destroyOnHidden === false) ? /* @__PURE__ */ jsx(
|
|
108
|
+
"div",
|
|
109
|
+
{
|
|
110
|
+
id: bodyId,
|
|
111
|
+
hidden: !expanded,
|
|
112
|
+
"data-blink": item.blink ? "" : void 0,
|
|
113
|
+
className: "ui-thought-chain-content",
|
|
114
|
+
children: item.content
|
|
115
|
+
}
|
|
116
|
+
) : null,
|
|
117
|
+
item.footer ? /* @__PURE__ */ jsx("div", { className: "ui-thought-chain-footer", children: item.footer }) : null
|
|
118
|
+
] })
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
key
|
|
122
|
+
);
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
ThoughtChain.displayName = "ThoughtChain";
|
|
129
|
+
const ThoughtChainItem = React.forwardRef(
|
|
130
|
+
({
|
|
131
|
+
title,
|
|
132
|
+
description,
|
|
133
|
+
icon,
|
|
134
|
+
status,
|
|
135
|
+
variant = "solid",
|
|
136
|
+
blink,
|
|
137
|
+
disabled,
|
|
138
|
+
onClick,
|
|
139
|
+
id,
|
|
140
|
+
className
|
|
141
|
+
}, ref) => {
|
|
142
|
+
const shared = {
|
|
143
|
+
id,
|
|
144
|
+
"data-slot": "thought-chain-item",
|
|
145
|
+
"data-variant": variant,
|
|
146
|
+
"data-status": status,
|
|
147
|
+
"data-blink": blink ? "" : void 0,
|
|
148
|
+
className: cn("ui-thought-chain-item", className)
|
|
149
|
+
};
|
|
150
|
+
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
151
|
+
status || icon ? /* @__PURE__ */ jsx("span", { "data-status": status, className: "ui-thought-chain-icon", children: /* @__PURE__ */ jsx(StatusMark, { status, fallback: icon }) }) : null,
|
|
152
|
+
/* @__PURE__ */ jsxs("span", { className: "ui-thought-chain-item-text", children: [
|
|
153
|
+
title ? /* @__PURE__ */ jsx(Text, { weight: "medium", children: title }) : null,
|
|
154
|
+
description ? /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: description }) : null
|
|
155
|
+
] })
|
|
156
|
+
] });
|
|
157
|
+
if (!onClick) {
|
|
158
|
+
return /* @__PURE__ */ jsx("div", { ref, ...shared, children: inner });
|
|
159
|
+
}
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
"button",
|
|
162
|
+
{
|
|
163
|
+
ref,
|
|
164
|
+
type: "button",
|
|
165
|
+
disabled,
|
|
166
|
+
onClick,
|
|
167
|
+
...shared,
|
|
168
|
+
children: inner
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
ThoughtChainItem.displayName = "ThoughtChainItem";
|
|
174
|
+
export {
|
|
175
|
+
ThoughtChain,
|
|
176
|
+
ThoughtChainItem
|
|
177
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { WelcomeProp } from "../../props/components/data-display.prop.js";
|
|
3
|
+
export type { WelcomeProp, WelcomeProp as WelcomeProps, WelcomeVariantProp, } from "../../props/components/data-display.prop.js";
|
|
4
|
+
/**
|
|
5
|
+
* Welcome — the greeting block at the head of an empty conversation (Ant Design X `Welcome`).
|
|
6
|
+
*
|
|
7
|
+
* ## Why this is a component and not four lines of composition
|
|
8
|
+
*
|
|
9
|
+
* It is close to the line, and the honest answer is that the SHAPE is the value: an assistant's
|
|
10
|
+
* first screen is the same object in every product — glyph, greeting, one line under it, one
|
|
11
|
+
* trailing action — and Ant X named it, so every consumer that builds a chat now expects the name.
|
|
12
|
+
* What it owns beyond a `Flex` is the `extra` slot's placement (on the TITLE row, not below the
|
|
13
|
+
* description, which is where a hand-roll puts it) and the `icon`-as-URL rule below.
|
|
14
|
+
*
|
|
15
|
+
* ## Two deliberate differences from Ant X, both in the same direction
|
|
16
|
+
*
|
|
17
|
+
* - **The image icon is decorative.** Ant renders `alt="icon"` — a screen reader then reads the
|
|
18
|
+
* word "icon" beside a title the glyph is only decorating. Here it is `alt=""`, which is what an
|
|
19
|
+
* image that duplicates adjacent text is supposed to be.
|
|
20
|
+
* - **The heading level is Ant's.** Ant hardcodes `Typography.Title level={4}`, so this renders an
|
|
21
|
+
* `<h4>`. Hardcoding a level is a document-structure decision a component should not normally
|
|
22
|
+
* make, but the alternative — inventing a `level` prop Ant does not have — is a second spelling
|
|
23
|
+
* of an axis the issue asked to port verbatim. Wrap it in your own heading hierarchy if the page
|
|
24
|
+
* needs a different rung.
|
|
25
|
+
*/
|
|
26
|
+
export declare const Welcome: React.ForwardRefExoticComponent<WelcomeProp & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { Heading, Text } from "../general/typography.js";
|
|
6
|
+
function isImageUrl(icon) {
|
|
7
|
+
return typeof icon === "string" && icon.startsWith("http");
|
|
8
|
+
}
|
|
9
|
+
const Welcome = React.forwardRef(
|
|
10
|
+
({ icon, title, description, extra, variant = "filled", id, className, ...rest }, ref) => {
|
|
11
|
+
return /* @__PURE__ */ jsxs(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
id,
|
|
16
|
+
"data-slot": "welcome",
|
|
17
|
+
"data-variant": variant,
|
|
18
|
+
className: cn("ui-welcome", className),
|
|
19
|
+
...rest,
|
|
20
|
+
children: [
|
|
21
|
+
icon ? /* @__PURE__ */ jsx("div", { "data-slot": "welcome-icon", className: "ui-welcome-icon", "aria-hidden": "true", children: isImageUrl(icon) ? /* @__PURE__ */ jsx("img", { src: icon, alt: "" }) : icon }) : null,
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { "data-slot": "welcome-content", className: "ui-welcome-content", children: [
|
|
23
|
+
title || extra ? /* @__PURE__ */ jsxs("div", { "data-slot": "welcome-title-row", className: "ui-welcome-title-row", children: [
|
|
24
|
+
title ? /* @__PURE__ */ jsx(Heading, { level: 4, className: "ui-welcome-title", children: title }) : null,
|
|
25
|
+
extra ? /* @__PURE__ */ jsx("div", { "data-slot": "welcome-extra", className: "ui-welcome-extra", children: extra }) : null
|
|
26
|
+
] }) : null,
|
|
27
|
+
description ? /* @__PURE__ */ jsx(Text, { size: "sm", tone: "muted", className: "ui-welcome-description", children: description }) : null
|
|
28
|
+
] })
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
Welcome.displayName = "Welcome";
|
|
35
|
+
export {
|
|
36
|
+
Welcome
|
|
37
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { AttachmentsItemProp, AttachmentsPlaceholderProp, AttachmentsRefProp } from "../../props/components/data-entry.prop.js";
|
|
3
|
+
export type { AttachmentsProp, AttachmentsProp as AttachmentsProps, AttachmentsItemProp, AttachmentsPlaceholderProp, AttachmentsOverflowProp, AttachmentsRefProp, } from "../../props/components/data-entry.prop.js";
|
|
4
|
+
export declare const Attachments: React.ForwardRefExoticComponent<Omit<import("./upload.js").UploadProp, "children" | "defaultValue" | "onRemove" | "onValueChange" | "showUploadList" | "value" | "variant"> & {
|
|
5
|
+
items?: readonly AttachmentsItemProp[];
|
|
6
|
+
onChange?: (info: {
|
|
7
|
+
file: AttachmentsItemProp;
|
|
8
|
+
fileList: AttachmentsItemProp[];
|
|
9
|
+
}) => void;
|
|
10
|
+
onRemove?: (item: AttachmentsItemProp) => boolean | void | Promise<boolean | void>;
|
|
11
|
+
overflow?: import("./attachments.js").AttachmentsOverflowProp;
|
|
12
|
+
placeholder?: AttachmentsPlaceholderProp | ((type: "inline" | "drop") => AttachmentsPlaceholderProp);
|
|
13
|
+
getDropContainer?: (() => HTMLElement | null | undefined) | null;
|
|
14
|
+
classNames?: Partial<Record<import("../../props/components/data-entry.prop.js").AttachmentsSemanticProp, string>>;
|
|
15
|
+
styles?: Partial<Record<import("../../props/components/data-entry.prop.js").AttachmentsSemanticProp, React.CSSProperties>>;
|
|
16
|
+
rootClassName?: import("../../props/index.js").ClassNameProp;
|
|
17
|
+
children?: React.ReactElement;
|
|
18
|
+
imageProps?: Record<string, unknown>;
|
|
19
|
+
} & React.RefAttributes<AttachmentsRefProp>>;
|