@octohirono/stitch-design-system 0.1.0 → 0.3.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/components/BarChart/BarChart.d.ts +42 -0
- package/dist/components/BarChart/BarChart.js +71 -0
- package/dist/components/BarChart/bar-chart.module.js +4 -0
- package/dist/components/BarChart/index.d.ts +2 -0
- package/dist/components/Calendar/Calendar.d.ts +57 -0
- package/dist/components/Calendar/Calendar.js +83 -0
- package/dist/components/Calendar/calendar.module.js +26 -0
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/ChatFile/ChatFile.d.ts +34 -0
- package/dist/components/ChatFile/ChatFile.js +71 -0
- package/dist/components/ChatFile/chat-file.module.js +12 -0
- package/dist/components/ChatFile/index.d.ts +2 -0
- package/dist/components/ChatImage/ChatImage.d.ts +31 -0
- package/dist/components/ChatImage/ChatImage.js +88 -0
- package/dist/components/ChatImage/chat-image.module.js +12 -0
- package/dist/components/ChatImage/index.d.ts +2 -0
- package/dist/components/ChatInput/ChatInput.d.ts +77 -0
- package/dist/components/ChatInput/ChatInput.js +88 -0
- package/dist/components/ChatInput/chat-input.module.js +11 -0
- package/dist/components/ChatInput/index.d.ts +2 -0
- package/dist/components/ChatList/ChatList.d.ts +58 -0
- package/dist/components/ChatList/ChatList.js +49 -0
- package/dist/components/ChatList/chat-list.module.js +7 -0
- package/dist/components/ChatList/index.d.ts +2 -0
- package/dist/components/ChatMessage/ChatMessage.d.ts +52 -0
- package/dist/components/ChatMessage/ChatMessage.js +71 -0
- package/dist/components/ChatMessage/chat-message.module.js +21 -0
- package/dist/components/ChatMessage/index.d.ts +2 -0
- package/dist/components/ChatMessageActions/ChatMessageActions.d.ts +40 -0
- package/dist/components/ChatMessageActions/ChatMessageActions.js +34 -0
- package/dist/components/ChatMessageActions/chat-message-actions.module.js +7 -0
- package/dist/components/ChatMessageActions/index.d.ts +2 -0
- package/dist/components/ChatVoice/ChatVoice.d.ts +39 -0
- package/dist/components/ChatVoice/ChatVoice.js +44 -0
- package/dist/components/ChatVoice/chat-voice.module.js +12 -0
- package/dist/components/ChatVoice/index.d.ts +2 -0
- package/dist/components/ContextMenu/ContextMenu.js +41 -34
- package/dist/components/ContextMenu/context-menu.module.js +10 -9
- package/dist/components/DatePicker/DatePicker.d.ts +60 -0
- package/dist/components/DatePicker/DatePicker.js +75 -0
- package/dist/components/DatePicker/datepicker.module.js +17 -0
- package/dist/components/DatePicker/index.d.ts +2 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +45 -38
- package/dist/components/DropdownMenu/dropdown-menu.module.js +10 -9
- package/dist/components/Icon/Icon.d.ts +36 -0
- package/dist/components/Icon/Icon.js +59 -1
- package/dist/components/Image/Image.js +1 -1
- package/dist/components/Image/image.module.js +14 -14
- package/dist/components/LineChart/LineChart.d.ts +48 -0
- package/dist/components/LineChart/LineChart.js +110 -0
- package/dist/components/LineChart/index.d.ts +2 -0
- package/dist/components/LineChart/line-chart.module.js +7 -0
- package/dist/components/PieChart/PieChart.d.ts +43 -0
- package/dist/components/PieChart/PieChart.js +56 -0
- package/dist/components/PieChart/index.d.ts +2 -0
- package/dist/components/PieChart/pie-chart.module.js +7 -0
- package/dist/components/Select/Select.js +87 -83
- package/dist/components/Select/select.module.js +10 -9
- package/dist/components/Stat/Stat.d.ts +71 -0
- package/dist/components/Stat/Stat.js +66 -0
- package/dist/components/Stat/StatGroup.d.ts +14 -0
- package/dist/components/Stat/StatGroup.js +16 -0
- package/dist/components/Stat/index.d.ts +4 -0
- package/dist/components/Stat/stat.module.js +23 -0
- package/dist/components/TypingIndicator/TypingIndicator.d.ts +24 -0
- package/dist/components/TypingIndicator/TypingIndicator.js +29 -0
- package/dist/components/TypingIndicator/index.d.ts +2 -0
- package/dist/components/TypingIndicator/typing-indicator.module.js +8 -0
- package/dist/components/_internal/dataviz/ChartFrame.d.ts +20 -0
- package/dist/components/_internal/dataviz/ChartFrame.js +18 -0
- package/dist/components/_internal/dataviz/ChartTooltip.d.ts +23 -0
- package/dist/components/_internal/dataviz/ChartTooltip.js +33 -0
- package/dist/components/_internal/dataviz/chart-frame.module.js +4 -0
- package/dist/components/_internal/dataviz/chart-tooltip.module.js +11 -0
- package/dist/components/_internal/dataviz/chartColors.d.ts +12 -0
- package/dist/components/_internal/dataviz/chartColors.js +3 -0
- package/dist/components/_internal/dataviz/index.d.ts +5 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +37 -22
- package/dist/style.css +1305 -448
- package/dist/themes/seline.css +39 -0
- package/dist/themes/steep.css +37 -0
- package/package.json +9 -4
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/** 单条系列:从每行数据里取哪个字段、显示成什么名。 */
|
|
3
|
+
export interface BarChartSeries {
|
|
4
|
+
/** 该系列在数据项里取值的字段名 */
|
|
5
|
+
dataKey: string;
|
|
6
|
+
/** 系列显示名(tooltip / 图例);缺省用 `dataKey` */
|
|
7
|
+
name?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 柱状图。系列色只从契约分类色槽 `var(--stitch-cat-*)` 取、按序号循环,随站换肤整图跟随;
|
|
11
|
+
* 组件内零硬编码主题值、零手写内联 svg(svg 全由 recharts 出),无 emoji。多系列默认分组并排,
|
|
12
|
+
* `stack` 开启则堆叠成一柱;多系列另出图例(`Legend`)把系列名列出,不只靠颜色区分(守 a11y)。
|
|
13
|
+
* 整图作一张图对外——`role="img"` + `aria-label`(缺省兜底非空名)。
|
|
14
|
+
*/
|
|
15
|
+
export interface BarChartProps {
|
|
16
|
+
/** 数据源,每项一行记录(Ant charts `data` 语义) */
|
|
17
|
+
data: Record<string, unknown>[];
|
|
18
|
+
/** x 轴取值字段名(Ant charts `xField` 语义) */
|
|
19
|
+
xField: string;
|
|
20
|
+
/** 一条或多条系列(各取一个 y 字段) */
|
|
21
|
+
series: BarChartSeries[];
|
|
22
|
+
/**
|
|
23
|
+
* 多系列堆叠成一柱(Ant charts `isStack` 语义);关闭时多系列分组并排
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
stack?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 图表高度(px);宽度恒铺满容器
|
|
29
|
+
* @default 300
|
|
30
|
+
*/
|
|
31
|
+
height?: number;
|
|
32
|
+
/** y 值格式化(如货币);作用于坐标轴刻度与 tooltip 值 */
|
|
33
|
+
valueFormatter?: (value: number) => string;
|
|
34
|
+
/** 图表整体可访问名(`role="img"` 的文本替代);缺省兜底非空名 */
|
|
35
|
+
ariaLabel?: string;
|
|
36
|
+
/** 透传外层容器类名 */
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 把数据画成柱状(单 / 多系列,可堆叠),系列色走契约分类色槽、随站换肤。
|
|
41
|
+
*/
|
|
42
|
+
export declare const BarChart: React.FC<BarChartProps>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { catColor as e } from "../_internal/dataviz/chartColors.js";
|
|
2
|
+
import { ChartFrame as t } from "../_internal/dataviz/ChartFrame.js";
|
|
3
|
+
import { ChartTooltip as n } from "../_internal/dataviz/ChartTooltip.js";
|
|
4
|
+
import r from "./bar-chart.module.js";
|
|
5
|
+
import "react";
|
|
6
|
+
import i from "clsx";
|
|
7
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
8
|
+
import { Bar as s, BarChart as c, CartesianGrid as l, Legend as u, Tooltip as d, XAxis as f, YAxis as p } from "recharts";
|
|
9
|
+
//#region packages/react/src/components/BarChart/BarChart.tsx
|
|
10
|
+
var m = ({ data: m, xField: h, series: g, stack: _ = !1, height: v = 300, valueFormatter: y, ariaLabel: b, className: x }) => {
|
|
11
|
+
let S = { fill: "var(--stitch-text-secondary)" }, C = y ? (e) => y(e) : void 0, w = (e) => {
|
|
12
|
+
let { active: t, label: r, payload: i } = e, o = i?.map((e) => ({
|
|
13
|
+
name: e.name,
|
|
14
|
+
value: y && typeof e.value == "number" ? y(e.value) : e.value,
|
|
15
|
+
color: e.color
|
|
16
|
+
}));
|
|
17
|
+
return /* @__PURE__ */ a(n, {
|
|
18
|
+
active: t,
|
|
19
|
+
label: r,
|
|
20
|
+
payload: o
|
|
21
|
+
});
|
|
22
|
+
}, T = _ ? "stack" : void 0, E = g.length > 1;
|
|
23
|
+
return /* @__PURE__ */ a(t, {
|
|
24
|
+
ariaLabel: b,
|
|
25
|
+
height: v,
|
|
26
|
+
className: i(r.chart, x),
|
|
27
|
+
children: /* @__PURE__ */ o(c, {
|
|
28
|
+
data: m,
|
|
29
|
+
margin: {
|
|
30
|
+
top: 8,
|
|
31
|
+
right: 8,
|
|
32
|
+
bottom: 4,
|
|
33
|
+
left: 4
|
|
34
|
+
},
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ a(l, {
|
|
37
|
+
stroke: "var(--stitch-border)",
|
|
38
|
+
vertical: !1
|
|
39
|
+
}),
|
|
40
|
+
/* @__PURE__ */ a(f, {
|
|
41
|
+
dataKey: h,
|
|
42
|
+
stroke: "var(--stitch-border)",
|
|
43
|
+
tick: S,
|
|
44
|
+
tickLine: !1
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ a(p, {
|
|
47
|
+
stroke: "var(--stitch-border)",
|
|
48
|
+
tick: S,
|
|
49
|
+
tickLine: !1,
|
|
50
|
+
tickFormatter: C
|
|
51
|
+
}),
|
|
52
|
+
/* @__PURE__ */ a(d, {
|
|
53
|
+
content: w,
|
|
54
|
+
cursor: { fill: "color-mix(in srgb, var(--stitch-text-primary), transparent 92%)" }
|
|
55
|
+
}),
|
|
56
|
+
E && /* @__PURE__ */ a(u, { wrapperStyle: { color: "var(--stitch-text-primary)" } }),
|
|
57
|
+
g.map((t, n) => /* @__PURE__ */ a(s, {
|
|
58
|
+
dataKey: t.dataKey,
|
|
59
|
+
name: t.name ?? t.dataKey,
|
|
60
|
+
fill: e(n),
|
|
61
|
+
stackId: T,
|
|
62
|
+
radius: 0,
|
|
63
|
+
isAnimationActive: !1
|
|
64
|
+
}, t.dataKey))
|
|
65
|
+
]
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
m.displayName = "BarChart";
|
|
70
|
+
//#endregion
|
|
71
|
+
export { m as BarChart };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type CalendarMode = 'single' | 'range';
|
|
3
|
+
/** 顶部年月区形态:`'label'` 静态标题;`'dropdown'` 月/年可点下拉(快速跳月跳年) */
|
|
4
|
+
export type CalendarCaptionLayout = 'label' | 'dropdown';
|
|
5
|
+
/** 日期范围:`from` 起点、`to` 终点(range 模式的取值形态) */
|
|
6
|
+
export interface DateRange {
|
|
7
|
+
from?: Date;
|
|
8
|
+
to?: Date;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 内联日历网格(react-day-picker 引擎):一次支持 `mode="single"`(单选)与 `mode="range"`
|
|
12
|
+
* (范围);月份网格、方向键导航、ARIA grid(`role="grid"`、日按钮可及名、翻月按钮可及名)
|
|
13
|
+
* 全由引擎兜底,上皮只读角色变量随换肤变化。
|
|
14
|
+
*
|
|
15
|
+
* 跨-prop 注意事项:
|
|
16
|
+
* - **取值随 `mode` 变形**:`single` 下 `value`/`defaultValue` 是 `Date`、`onChange` 收
|
|
17
|
+
* `Date | undefined`;`range` 下它们是 {@link DateRange}(`{from,to}`)、`onChange` 收
|
|
18
|
+
* `DateRange | undefined`。切 mode 时同步换掉取值形态。
|
|
19
|
+
* - **受控/非受控双模式**:给 `value` 由父管(配 `onChange` 回写),只给 `defaultValue`
|
|
20
|
+
* 组件自管;两者互斥优先取 `value`。
|
|
21
|
+
* - **禁用某些日期**用 `disabledDate(date) => boolean`(Ant 语义),命中的日按钮 `disabled`、
|
|
22
|
+
* 键盘与点击都跳过;整块只读用 `disabled`(把所有日期禁掉)。
|
|
23
|
+
* - **面 = 角色变量**:选中日 `--stitch-accent` + `--stitch-accent-text`,范围中段
|
|
24
|
+
* `--stitch-bg-accent`(日按钮铺满整格,底色与端点框边到边对齐、不出头),今天描
|
|
25
|
+
* `--stitch-border-strong`、hover 落 `--stitch-bg-card`、禁用走 `--stitch-text-disabled`;
|
|
26
|
+
* 翻月箭头一律经 `<Icon>`(`chevron-left`/`chevron-right`),无裸 svg / Unicode 符号。
|
|
27
|
+
* - **`captionLayout="dropdown"`(默认)** 顶部月/年为可点下拉,快速跳月跳年(原生 `<select>`
|
|
28
|
+
* 兜键盘与可及名);传 `'label'` 退回静态标题。年份范围默认「今年往前 100 年」,用
|
|
29
|
+
* `startMonth`/`endMonth` 收窄。
|
|
30
|
+
*/
|
|
31
|
+
export interface CalendarProps {
|
|
32
|
+
/** 选择模式:单日或范围 @default 'single' */
|
|
33
|
+
mode?: CalendarMode;
|
|
34
|
+
/** 受控选中值(`single`→`Date`,`range`→`DateRange`) */
|
|
35
|
+
value?: Date | DateRange;
|
|
36
|
+
/** 非受控初始选中值(`single`→`Date`,`range`→`DateRange`) */
|
|
37
|
+
defaultValue?: Date | DateRange;
|
|
38
|
+
/** 选中变化回调(`single`→`Date | undefined`,`range`→`DateRange | undefined`) */
|
|
39
|
+
onChange?: (value: Date | DateRange | undefined) => void;
|
|
40
|
+
/** 逐日禁用判定:返回 `true` 的日期不可选 */
|
|
41
|
+
disabledDate?: (date: Date) => boolean;
|
|
42
|
+
/** 整块禁用(所有日期不可选) @default false */
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
/** 首屏展示的月份(不给则据选中值 / 当月) */
|
|
45
|
+
defaultMonth?: Date;
|
|
46
|
+
/** 顶部年月区形态:`'dropdown'` 可点选月 / 年,`'label'` 静态标题 @default 'dropdown' */
|
|
47
|
+
captionLayout?: CalendarCaptionLayout;
|
|
48
|
+
/** dropdown 年份下限(不给默认今年往前 100 年) */
|
|
49
|
+
startMonth?: Date;
|
|
50
|
+
/** dropdown 年份上限(不给默认今年年底) */
|
|
51
|
+
endMonth?: Date;
|
|
52
|
+
/** 日历网格的可访问名 */
|
|
53
|
+
'aria-label'?: string;
|
|
54
|
+
/** 自定义类名(挂到日历根节点) */
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
export declare const Calendar: React.FC<CalendarProps>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Icon as e } from "../Icon/Icon.js";
|
|
2
|
+
import { Select as t } from "../Select/Select.js";
|
|
3
|
+
import n from "./calendar.module.js";
|
|
4
|
+
import { useCallback as r, useState as i } from "react";
|
|
5
|
+
import a from "clsx";
|
|
6
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
7
|
+
import { DayPicker as s } from "react-day-picker";
|
|
8
|
+
//#region packages/react/src/components/Calendar/Calendar.tsx
|
|
9
|
+
var c = ({ orientation: t }) => /* @__PURE__ */ o(e, {
|
|
10
|
+
name: t === "left" ? "chevron-left" : t === "right" ? "chevron-right" : "chevron-down",
|
|
11
|
+
size: 18
|
|
12
|
+
}), l = ({ options: e, value: r, onChange: i, disabled: s, "aria-label": c }) => {
|
|
13
|
+
let l = typeof c == "string" && /year/i.test(c);
|
|
14
|
+
return /* @__PURE__ */ o(t, {
|
|
15
|
+
size: "small",
|
|
16
|
+
className: a(n.captionSelect, l && n.captionYear),
|
|
17
|
+
options: (e ?? []).map((e) => ({
|
|
18
|
+
label: e.label,
|
|
19
|
+
value: e.value,
|
|
20
|
+
disabled: e.disabled
|
|
21
|
+
})),
|
|
22
|
+
value: r == null ? void 0 : Number(r),
|
|
23
|
+
onChange: (e) => i?.({ target: { value: String(e) } }),
|
|
24
|
+
disabled: s,
|
|
25
|
+
"aria-label": typeof c == "string" ? c : void 0
|
|
26
|
+
});
|
|
27
|
+
}, u = {
|
|
28
|
+
root: n.root,
|
|
29
|
+
months: n.months,
|
|
30
|
+
month: n.month,
|
|
31
|
+
month_caption: n.caption,
|
|
32
|
+
caption_label: n.captionLabel,
|
|
33
|
+
nav: n.nav,
|
|
34
|
+
button_previous: n.navButton,
|
|
35
|
+
button_next: n.navButton,
|
|
36
|
+
dropdowns: n.dropdowns,
|
|
37
|
+
month_grid: n.grid,
|
|
38
|
+
weekdays: n.weekdays,
|
|
39
|
+
weekday: n.weekday,
|
|
40
|
+
week: n.week,
|
|
41
|
+
day: n.day,
|
|
42
|
+
day_button: n.dayButton,
|
|
43
|
+
today: n.today,
|
|
44
|
+
selected: n.selected,
|
|
45
|
+
range_start: n.rangeStart,
|
|
46
|
+
range_middle: n.rangeMiddle,
|
|
47
|
+
range_end: n.rangeEnd,
|
|
48
|
+
outside: n.outside,
|
|
49
|
+
disabled: n.disabled,
|
|
50
|
+
hidden: n.hidden,
|
|
51
|
+
focused: n.focused
|
|
52
|
+
}, d = ({ mode: e = "single", value: t, defaultValue: n, onChange: d, disabledDate: f, disabled: p = !1, defaultMonth: m, captionLayout: h = "dropdown", startMonth: g, endMonth: _, className: v, "aria-label": y }) => {
|
|
53
|
+
let b = t !== void 0, [x, S] = i(n), C = b ? t : x, w = r((e) => {
|
|
54
|
+
b || S(e), d?.(e);
|
|
55
|
+
}, [b, d]), T = (/* @__PURE__ */ new Date()).getFullYear(), E = h === "dropdown" ? g ?? new Date(T - 100, 0, 1) : g, D = h === "dropdown" ? _ ?? new Date(T + 10, 11, 31) : _, O = {
|
|
56
|
+
classNames: u,
|
|
57
|
+
components: {
|
|
58
|
+
Chevron: c,
|
|
59
|
+
Dropdown: l
|
|
60
|
+
},
|
|
61
|
+
disabled: p ? !0 : f,
|
|
62
|
+
defaultMonth: m,
|
|
63
|
+
captionLayout: h,
|
|
64
|
+
startMonth: E,
|
|
65
|
+
endMonth: D,
|
|
66
|
+
"aria-label": y,
|
|
67
|
+
className: a(v)
|
|
68
|
+
};
|
|
69
|
+
return e === "range" ? /* @__PURE__ */ o(s, {
|
|
70
|
+
mode: "range",
|
|
71
|
+
selected: C,
|
|
72
|
+
onSelect: (e) => w(e ?? void 0),
|
|
73
|
+
...O
|
|
74
|
+
}) : /* @__PURE__ */ o(s, {
|
|
75
|
+
mode: "single",
|
|
76
|
+
selected: C,
|
|
77
|
+
onSelect: (e) => w(e ?? void 0),
|
|
78
|
+
...O
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
d.displayName = "Calendar";
|
|
82
|
+
//#endregion
|
|
83
|
+
export { d as Calendar };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region packages/react/src/components/Calendar/calendar.module.less
|
|
2
|
+
var e = "_root_de6fy_1", t = "_months_de6fy_11", n = "_caption_de6fy_14", r = "_captionLabel_de6fy_21", i = "_nav_de6fy_25", a = "_navButton_de6fy_34", o = "_dropdowns_de6fy_60", s = "_captionSelect_de6fy_66", c = "_captionYear_de6fy_69", l = "_grid_de6fy_72", u = "_weekday_de6fy_75", d = "_day_de6fy_83", f = "_dayButton_de6fy_90", p = "_today_de6fy_116", m = "_selected_de6fy_116", h = "_rangeStart_de6fy_116", g = "_rangeEnd_de6fy_116", _ = "_outside_de6fy_120", v = "_disabled_de6fy_123", y = "_hidden_de6fy_130", b = "_rangeMiddle_de6fy_140", x = {
|
|
3
|
+
root: e,
|
|
4
|
+
months: t,
|
|
5
|
+
caption: n,
|
|
6
|
+
captionLabel: r,
|
|
7
|
+
nav: i,
|
|
8
|
+
navButton: a,
|
|
9
|
+
dropdowns: o,
|
|
10
|
+
captionSelect: s,
|
|
11
|
+
captionYear: c,
|
|
12
|
+
grid: l,
|
|
13
|
+
weekday: u,
|
|
14
|
+
day: d,
|
|
15
|
+
dayButton: f,
|
|
16
|
+
today: p,
|
|
17
|
+
selected: m,
|
|
18
|
+
rangeStart: h,
|
|
19
|
+
rangeEnd: g,
|
|
20
|
+
outside: _,
|
|
21
|
+
disabled: v,
|
|
22
|
+
hidden: y,
|
|
23
|
+
rangeMiddle: b
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { n as caption, r as captionLabel, s as captionSelect, c as captionYear, d as day, f as dayButton, x as default, v as disabled, o as dropdowns, l as grid, y as hidden, t as months, i as nav, a as navButton, _ as outside, g as rangeEnd, b as rangeMiddle, h as rangeStart, e as root, m as selected, p as today, u as weekday };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 文件附件卡:复用 `<Card>` 承载——类型图标(`<Icon name="file">`)+ 文件名 + 大小 /
|
|
4
|
+
* 副文本;作为 `<ChatMessage>` 的 `content` 塞入(sent / received 两侧皆可)。点击 / 下载
|
|
5
|
+
* 均为**回调交 app**(组件不导航、不发起下载)。对外 props 取 Ant Design X `Attachments`
|
|
6
|
+
* 附件项最近惯例(`name` / `size` / `description`)+ Ant v5 回调命名。
|
|
7
|
+
*
|
|
8
|
+
* 跨-prop 注意事项:
|
|
9
|
+
* - **下载键是文件卡固有部件、常驻**(文件默认可下载):右侧复用 `<Button type="text">`,点击走
|
|
10
|
+
* `onDownload` 回调、由 app 落地下载。
|
|
11
|
+
* - **两个独立可聚焦控件、互不嵌套**:给 `onClick` 时文件名区升格为整行透明按钮(打开),与下载
|
|
12
|
+
* 键平级,无按钮套按钮。
|
|
13
|
+
* - **`size` 是字节数**,组件内格式化为人类可读(`1.2 MB`);`description` 为副文本(如类型),
|
|
14
|
+
* 与已格式化的大小同排、`·` 分隔。
|
|
15
|
+
* - **图标走 `<Icon>`**:类型图标 `<Icon name="file">`(装饰性)、下载 `<Icon name="download">`
|
|
16
|
+
* (其按钮带可访问名 `下载 {name}`),非 emoji / 裸 `<svg>`。
|
|
17
|
+
*/
|
|
18
|
+
export interface ChatFileProps {
|
|
19
|
+
/** 文件名(必填) */
|
|
20
|
+
name: string;
|
|
21
|
+
/** 文件大小(字节数);组件内格式化为人类可读 */
|
|
22
|
+
size?: number;
|
|
23
|
+
/** 副文本(如文件类型说明),与大小同排 `·` 分隔 */
|
|
24
|
+
description?: React.ReactNode;
|
|
25
|
+
/** 点击文件卡的回调(打开 / 预览交 app);给出时文件名区可聚焦、可键盘触发 */
|
|
26
|
+
onClick?: () => void;
|
|
27
|
+
/** 点击下载键的回调(下载交 app);下载键常驻,点击走此回调 */
|
|
28
|
+
onDownload?: () => void;
|
|
29
|
+
/** 自定义类名(挂到根 Card) */
|
|
30
|
+
className?: string;
|
|
31
|
+
/** 行内样式(挂到根 Card) */
|
|
32
|
+
style?: React.CSSProperties;
|
|
33
|
+
}
|
|
34
|
+
export declare const ChatFile: React.FC<ChatFileProps>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Button as e } from "../Button/Button.js";
|
|
2
|
+
import { Icon as t } from "../Icon/Icon.js";
|
|
3
|
+
import { Card as n } from "../Card/Card.js";
|
|
4
|
+
import r from "./chat-file.module.js";
|
|
5
|
+
import "react";
|
|
6
|
+
import i from "clsx";
|
|
7
|
+
import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
|
+
//#region packages/react/src/components/ChatFile/ChatFile.tsx
|
|
9
|
+
var c = [
|
|
10
|
+
"B",
|
|
11
|
+
"KB",
|
|
12
|
+
"MB",
|
|
13
|
+
"GB",
|
|
14
|
+
"TB"
|
|
15
|
+
];
|
|
16
|
+
function l(e) {
|
|
17
|
+
if (!Number.isFinite(e) || e < 0) return "";
|
|
18
|
+
if (e < 1) return "0 B";
|
|
19
|
+
let t = Math.min(c.length - 1, Math.floor(Math.log(e) / Math.log(1024))), n = e / 1024 ** t;
|
|
20
|
+
return `${t === 0 ? String(Math.round(n)) : n.toFixed(1)} ${c[t]}`;
|
|
21
|
+
}
|
|
22
|
+
var u = ({ name: c, size: u, description: d, onClick: f, onDownload: p, className: m, style: h }) => {
|
|
23
|
+
let g = typeof u == "number" ? l(u) : "", _ = /* @__PURE__ */ s("span", {
|
|
24
|
+
className: r.meta,
|
|
25
|
+
children: [
|
|
26
|
+
g && /* @__PURE__ */ o("span", { children: g }),
|
|
27
|
+
g && d != null && /* @__PURE__ */ o("span", {
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
children: " · "
|
|
30
|
+
}),
|
|
31
|
+
d != null && /* @__PURE__ */ o("span", { children: d })
|
|
32
|
+
]
|
|
33
|
+
}), v = /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o(t, {
|
|
34
|
+
name: "file",
|
|
35
|
+
className: r.type,
|
|
36
|
+
size: "1.5em"
|
|
37
|
+
}), /* @__PURE__ */ s("span", {
|
|
38
|
+
className: r.text,
|
|
39
|
+
children: [/* @__PURE__ */ o("span", {
|
|
40
|
+
className: r.name,
|
|
41
|
+
children: c
|
|
42
|
+
}), (g || d != null) && _]
|
|
43
|
+
})] });
|
|
44
|
+
return /* @__PURE__ */ s(n, {
|
|
45
|
+
variant: "outlined",
|
|
46
|
+
className: i(r.file, m),
|
|
47
|
+
style: h,
|
|
48
|
+
children: [f ? /* @__PURE__ */ o("button", {
|
|
49
|
+
type: "button",
|
|
50
|
+
className: r.trigger,
|
|
51
|
+
onClick: f,
|
|
52
|
+
"aria-label": `打开文件 ${c}`,
|
|
53
|
+
children: v
|
|
54
|
+
}) : /* @__PURE__ */ o("div", {
|
|
55
|
+
className: r.trigger,
|
|
56
|
+
children: v
|
|
57
|
+
}), /* @__PURE__ */ o(e, {
|
|
58
|
+
type: "text",
|
|
59
|
+
className: r.download,
|
|
60
|
+
onClick: p,
|
|
61
|
+
"aria-label": `下载 ${c}`,
|
|
62
|
+
children: /* @__PURE__ */ o(t, {
|
|
63
|
+
name: "download",
|
|
64
|
+
size: "1.25em"
|
|
65
|
+
})
|
|
66
|
+
})]
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
u.displayName = "ChatFile";
|
|
70
|
+
//#endregion
|
|
71
|
+
export { u as ChatFile };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region packages/react/src/components/ChatFile/chat-file.module.less
|
|
2
|
+
var e = "_file_1tjaq_1", t = "_trigger_1tjaq_8", n = "_type_1tjaq_29", r = "_text_1tjaq_33", i = "_name_1tjaq_39", a = "_meta_1tjaq_47", o = "_download_1tjaq_51", s = {
|
|
3
|
+
file: e,
|
|
4
|
+
trigger: t,
|
|
5
|
+
type: n,
|
|
6
|
+
text: r,
|
|
7
|
+
name: i,
|
|
8
|
+
meta: a,
|
|
9
|
+
download: o
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { s as default, o as download, e as file, a as meta, i as name, r as text, t as trigger, n as type };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 图片消息(气泡内缩略图 + 大图查看器):气泡里显缩略图(复用通用 `<Image>`、`preview` 关闭),
|
|
4
|
+
* 点击开大图——**大图仍复用通用 `<Image>`(它自带的相框即「框」)**,本组件只做一层遮罩 + 把下载 /
|
|
5
|
+
* 关闭工具键**叠在这个框上**。作为 `<ChatMessage>` 的 `content` 塞入(sent / received 两侧皆可)。
|
|
6
|
+
* `src` / `alt` / `width` / `height` 照搬 antd `Image`;`width` 即缩略图宽。
|
|
7
|
+
*
|
|
8
|
+
* 跨-prop 注意事项:
|
|
9
|
+
* - **缩略图与大图都复用 `<Image preview={false}>`**(不手写裸 `<img>`、不重造 Image 的相框 / 圆角 /
|
|
10
|
+
* 加载淡入 / 错误占位);本组件只加聊天专属的遮罩 + 框上工具键(下载 / 关闭),`<Image>` 一行未改。
|
|
11
|
+
* - **块级排布**:根为块级元素,故 `<ChatMessage>` 的时间 / 回执落在缩略图**下方**(同文件卡)。
|
|
12
|
+
* - **大图查看器 a11y**:Portal 遮罩 + `role="dialog"`;打开焦点落关闭键、Tab 在下载 / 关闭间循环、
|
|
13
|
+
* ESC 关闭、关闭后焦点归还缩略图。下载走原生 `<a download href={src}>`(存下当前图,不解码不发
|
|
14
|
+
* 请求),工具键图标走 `<Icon>`,均带可访问名。
|
|
15
|
+
* - `width` 控缩略图尺寸;点击后大图按视口放大(原始尺寸)。
|
|
16
|
+
*/
|
|
17
|
+
export interface ChatImageProps {
|
|
18
|
+
/** 图片地址(必填,照搬 antd Image) */
|
|
19
|
+
src: string;
|
|
20
|
+
/** 图片替代文本(无障碍);留空表示装饰性图片 */
|
|
21
|
+
alt?: string;
|
|
22
|
+
/** 缩略图宽度(数字按 px,字符串原样) */
|
|
23
|
+
width?: number | string;
|
|
24
|
+
/** 缩略图高度(数字按 px,字符串原样) */
|
|
25
|
+
height?: number | string;
|
|
26
|
+
/** 自定义类名(挂到根) */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** 行内样式(挂到根) */
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
}
|
|
31
|
+
export declare const ChatImage: React.FC<ChatImageProps>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Icon as e } from "../Icon/Icon.js";
|
|
2
|
+
import { Image as t } from "../Image/Image.js";
|
|
3
|
+
import n from "./chat-image.module.js";
|
|
4
|
+
import { useEffect as r, useRef as i, useState as a } from "react";
|
|
5
|
+
import o from "clsx";
|
|
6
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
7
|
+
import { createPortal as l } from "react-dom";
|
|
8
|
+
//#region packages/react/src/components/ChatImage/ChatImage.tsx
|
|
9
|
+
var u = ({ src: u, alt: d = "", width: f, height: p, className: m, style: h }) => {
|
|
10
|
+
let [g, _] = a(!1), v = i(null), y = i(null), b = i(null);
|
|
11
|
+
return r(() => {
|
|
12
|
+
if (!g) return;
|
|
13
|
+
v.current?.focus();
|
|
14
|
+
let e = (e) => {
|
|
15
|
+
if (e.key === "Escape") _(!1);
|
|
16
|
+
else if (e.key === "Tab") {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
let t = [y.current, v.current].filter((e) => e != null);
|
|
19
|
+
if (t.length === 0) return;
|
|
20
|
+
let n = t.indexOf(document.activeElement);
|
|
21
|
+
t[e.shiftKey ? n <= 0 ? t.length - 1 : n - 1 : n >= t.length - 1 ? 0 : n + 1]?.focus();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
|
|
25
|
+
}, [g]), r(() => {
|
|
26
|
+
g || (b.current?.focus(), b.current = null);
|
|
27
|
+
}, [g]), /* @__PURE__ */ c("span", {
|
|
28
|
+
className: o(n.frame, m),
|
|
29
|
+
style: h,
|
|
30
|
+
children: [/* @__PURE__ */ s("button", {
|
|
31
|
+
type: "button",
|
|
32
|
+
className: n.thumb,
|
|
33
|
+
onClick: () => {
|
|
34
|
+
b.current = document.activeElement, _(!0);
|
|
35
|
+
},
|
|
36
|
+
"aria-label": d ? `查看大图 ${d}` : "查看大图",
|
|
37
|
+
children: /* @__PURE__ */ s(t, {
|
|
38
|
+
src: u,
|
|
39
|
+
alt: d,
|
|
40
|
+
width: f,
|
|
41
|
+
height: p,
|
|
42
|
+
preview: !1
|
|
43
|
+
})
|
|
44
|
+
}), l(g ? /* @__PURE__ */ s("div", {
|
|
45
|
+
className: n.mask,
|
|
46
|
+
onClick: () => _(!1),
|
|
47
|
+
children: /* @__PURE__ */ c("div", {
|
|
48
|
+
className: n.dialog,
|
|
49
|
+
role: "dialog",
|
|
50
|
+
"aria-modal": "true",
|
|
51
|
+
"aria-label": d ? `查看图片:${d}` : "图片预览",
|
|
52
|
+
onClick: (e) => e.stopPropagation(),
|
|
53
|
+
children: [/* @__PURE__ */ s(t, {
|
|
54
|
+
src: u,
|
|
55
|
+
alt: d,
|
|
56
|
+
preview: !1,
|
|
57
|
+
className: n.full
|
|
58
|
+
}), /* @__PURE__ */ c("div", {
|
|
59
|
+
className: n.tools,
|
|
60
|
+
children: [/* @__PURE__ */ s("a", {
|
|
61
|
+
ref: y,
|
|
62
|
+
className: n.toolBtn,
|
|
63
|
+
href: u,
|
|
64
|
+
download: !0,
|
|
65
|
+
"aria-label": d ? `下载图片 ${d}` : "下载图片",
|
|
66
|
+
children: /* @__PURE__ */ s(e, {
|
|
67
|
+
name: "download",
|
|
68
|
+
size: 14
|
|
69
|
+
})
|
|
70
|
+
}), /* @__PURE__ */ s("button", {
|
|
71
|
+
type: "button",
|
|
72
|
+
ref: v,
|
|
73
|
+
className: n.toolBtn,
|
|
74
|
+
"aria-label": "关闭大图",
|
|
75
|
+
onClick: () => _(!1),
|
|
76
|
+
children: /* @__PURE__ */ s(e, {
|
|
77
|
+
name: "close",
|
|
78
|
+
size: 14
|
|
79
|
+
})
|
|
80
|
+
})]
|
|
81
|
+
})]
|
|
82
|
+
})
|
|
83
|
+
}) : null, document.body)]
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
u.displayName = "ChatImage";
|
|
87
|
+
//#endregion
|
|
88
|
+
export { u as ChatImage };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region packages/react/src/components/ChatImage/chat-image.module.less
|
|
2
|
+
var e = "_frame_1b4n8_1", t = "_thumb_1b4n8_6", n = "_mask_1b4n8_18", r = "_dialog_1b4n8_27", i = "_full_1b4n8_32", a = "_tools_1b4n8_36", o = "_toolBtn_1b4n8_44", s = {
|
|
3
|
+
frame: e,
|
|
4
|
+
thumb: t,
|
|
5
|
+
mask: n,
|
|
6
|
+
dialog: r,
|
|
7
|
+
full: i,
|
|
8
|
+
tools: a,
|
|
9
|
+
toolBtn: o
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { s as default, r as dialog, e as frame, i as full, n as mask, t as thumb, o as toolBtn, a as tools };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ChatInputSubmitType = 'enter' | 'shiftEnter';
|
|
3
|
+
/** autoSize 精细档:限制自增高的最小 / 最大行数(照搬 antd Input.TextArea / Sender) */
|
|
4
|
+
export interface ChatInputAutoSize {
|
|
5
|
+
/** 最小行数(低于此仍占此高) */
|
|
6
|
+
minRows?: number;
|
|
7
|
+
/** 最大行数(超过后内部滚动、不再增高) */
|
|
8
|
+
maxRows?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 聊天输入器:多行 textarea **自增高**(`autoSize`)+ 受控/非受控 `value` + `submitType`
|
|
12
|
+
* 决定发送键位(Enter 发送 / Shift+Enter 换行)+ `onSubmit` 发送回调 + `prefix` / `actions`
|
|
13
|
+
* 插槽(附件按钮等钩子由 app 填)。对外 props 照搬 antd `Input`(`value` / `onChange` /
|
|
14
|
+
* `disabled` / `placeholder` / `autoSize`)+ 聊天专属补 Ant Design X `Sender`
|
|
15
|
+
* (`onSubmit` / `loading` / `submitType` / `prefix` / `actions`)。
|
|
16
|
+
*
|
|
17
|
+
* 跨-prop 注意事项:
|
|
18
|
+
* - **受控/非受控双模式**:给 `value` 由父管,只给 `defaultValue` 组件自管;非受控时发送后
|
|
19
|
+
* 自动清空,受控时清空由父在 `onSubmit` 里做(组件不擅自改父的值)。
|
|
20
|
+
* - **`autoSize` 自增高**:`true`(默认)随内容行数增高;传 `{ minRows, maxRows }` 卡上下界,
|
|
21
|
+
* 超 `maxRows` 内部滚动。`false` 关自增(固定单行高、可手动拉伸由浏览器定)。
|
|
22
|
+
* - **`submitType` 定发送键位**:`enter`(默认)→ Enter 发送、Shift+Enter 换行;`shiftEnter`
|
|
23
|
+
* → Shift+Enter 发送、Enter 换行。输入法组词中(IME composing)的 Enter 一律只上屏、不发送。
|
|
24
|
+
* - **`onSubmit` 只在有内容时触发**:纯空白不发送;`disabled` / `loading` 时不发送。发送键是
|
|
25
|
+
* 原生 `<button>`,图标走 `<Icon name="send">`(禁 emoji / Unicode / 裸 svg),`sendAriaLabel`
|
|
26
|
+
* 定其可访问名。
|
|
27
|
+
* - **IM 无停止态**:`loading` 只置发送键忙 / 禁发,**不**把发送键换成「停止」键(那是 AI 生成
|
|
28
|
+
* 语境;IM 是人对人、无生成可停)。
|
|
29
|
+
* - **`prefix` / `actions` 传你自己的元素**(附件按钮走 `<Icon>` 或 `<Button>`)——**Do NOT** 传
|
|
30
|
+
* emoji / Unicode 符号 / 裸 `<svg>`。附件的选择 / 上传逻辑由 app 实现,组件只留插槽。
|
|
31
|
+
* - **可及名**:其余原生 textarea 属性(`aria-label` / `id` / `name` / `maxLength` …)经 `...rest`
|
|
32
|
+
* 透传到内部 `<textarea>`——给它可访问名(配 `<label htmlFor>` 或 `aria-label`)。
|
|
33
|
+
*/
|
|
34
|
+
export interface ChatInputProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue' | 'onChange' | 'onSubmit' | 'onKeyDown' | 'rows' | 'prefix'> {
|
|
35
|
+
/** 输入值(受控);不传由组件自管(非受控,配 `defaultValue`) */
|
|
36
|
+
value?: string;
|
|
37
|
+
/** 默认值(非受控初始值) */
|
|
38
|
+
defaultValue?: string;
|
|
39
|
+
/** 值变化回调(照搬 antd Input) */
|
|
40
|
+
onChange?: React.ChangeEventHandler<HTMLTextAreaElement>;
|
|
41
|
+
/** 发送回调(照搬 Ant Design X Sender):参数为当前消息文本 */
|
|
42
|
+
onSubmit?: (message: string) => void;
|
|
43
|
+
/** 占位符(照搬 antd Input) */
|
|
44
|
+
placeholder?: string;
|
|
45
|
+
/** 禁用(照搬 antd Input) */
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 发送中(照搬 Sender):置发送键忙 / 禁发;**IM 无停止态**,不换成「停止」键
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
loading?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 多行自增高(照搬 antd Input.TextArea / Sender):`true` 随内容增高,`{ minRows, maxRows }`
|
|
54
|
+
* 卡上下界,`false` 关自增
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
57
|
+
autoSize?: boolean | ChatInputAutoSize;
|
|
58
|
+
/**
|
|
59
|
+
* 发送键位(照搬 Sender):`enter` = Enter 发送 / Shift+Enter 换行;`shiftEnter` 反之
|
|
60
|
+
* @default 'enter'
|
|
61
|
+
*/
|
|
62
|
+
submitType?: ChatInputSubmitType;
|
|
63
|
+
/** 前缀插槽(附件按钮等钩子,照搬 Sender);附件逻辑由 app */
|
|
64
|
+
prefix?: React.ReactNode;
|
|
65
|
+
/** 动作区插槽(照搬 Sender):覆盖默认发送键旁的自定义动作 */
|
|
66
|
+
actions?: React.ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* 发送键的无障碍标签(纯图标按钮必备可访问名)
|
|
69
|
+
* @default '发送'
|
|
70
|
+
*/
|
|
71
|
+
sendAriaLabel?: string;
|
|
72
|
+
/** 自定义类名(挂到根容器) */
|
|
73
|
+
className?: string;
|
|
74
|
+
/** 行内样式(挂到根容器) */
|
|
75
|
+
style?: React.CSSProperties;
|
|
76
|
+
}
|
|
77
|
+
export declare const ChatInput: React.FC<ChatInputProps>;
|