@aura-react-comp/x 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -2
  3. package/esm/actions/index.d.ts +28 -0
  4. package/esm/actions/index.js +37 -0
  5. package/esm/actions/index.less +59 -0
  6. package/esm/attachments/index.d.ts +41 -0
  7. package/esm/attachments/index.js +48 -0
  8. package/esm/attachments/index.less +22 -0
  9. package/esm/bubble/index.d.ts +42 -0
  10. package/esm/bubble/index.js +80 -0
  11. package/esm/bubble/index.less +164 -0
  12. package/esm/code-highlighter/index.d.ts +39 -0
  13. package/esm/code-highlighter/index.js +165 -0
  14. package/esm/code-highlighter/index.less +76 -0
  15. package/esm/code-highlighter/prism-theme.d.ts +13 -0
  16. package/esm/code-highlighter/prism-theme.js +75 -0
  17. package/esm/conversations/index.d.ts +35 -0
  18. package/esm/conversations/index.js +89 -0
  19. package/esm/conversations/index.less +138 -0
  20. package/esm/file-card/index.d.ts +40 -0
  21. package/esm/file-card/index.js +126 -0
  22. package/esm/file-card/index.less +161 -0
  23. package/esm/folder/index.d.ts +66 -0
  24. package/esm/folder/index.js +345 -0
  25. package/esm/folder/index.less +158 -0
  26. package/esm/folder/tree-utils.d.ts +30 -0
  27. package/esm/folder/tree-utils.js +147 -0
  28. package/esm/folder/types.d.ts +51 -0
  29. package/esm/folder/types.js +1 -0
  30. package/esm/index.d.ts +40 -0
  31. package/esm/index.js +20 -0
  32. package/esm/markdown-content/index.d.ts +34 -0
  33. package/esm/markdown-content/index.js +117 -0
  34. package/esm/markdown-content/index.less +124 -0
  35. package/esm/mermaid/index.d.ts +47 -0
  36. package/esm/mermaid/index.js +235 -0
  37. package/esm/mermaid/index.less +155 -0
  38. package/esm/notification/index.d.ts +59 -0
  39. package/esm/notification/index.js +148 -0
  40. package/esm/prompts/index.d.ts +27 -0
  41. package/esm/prompts/index.js +50 -0
  42. package/esm/prompts/index.less +95 -0
  43. package/esm/sender/index.d.ts +48 -0
  44. package/esm/sender/index.js +88 -0
  45. package/esm/sender/index.less +75 -0
  46. package/esm/sources/index.d.ts +40 -0
  47. package/esm/sources/index.js +154 -0
  48. package/esm/sources/index.less +219 -0
  49. package/esm/style.css +1565 -0
  50. package/esm/suggestion/index.d.ts +21 -0
  51. package/esm/suggestion/index.js +36 -0
  52. package/esm/suggestion/index.less +44 -0
  53. package/esm/think/index.d.ts +20 -0
  54. package/esm/think/index.js +48 -0
  55. package/esm/think/index.less +92 -0
  56. package/esm/thought-chain/index.d.ts +34 -0
  57. package/esm/thought-chain/index.js +105 -0
  58. package/esm/thought-chain/index.less +174 -0
  59. package/esm/use-x-chat/index.d.ts +85 -0
  60. package/esm/use-x-chat/index.js +178 -0
  61. package/esm/use-x-stream/index.d.ts +43 -0
  62. package/esm/use-x-stream/index.js +112 -0
  63. package/esm/use-x-stream/parse-sse.d.ts +19 -0
  64. package/esm/use-x-stream/parse-sse.js +91 -0
  65. package/esm/utils/color.d.ts +9 -0
  66. package/esm/utils/color.js +45 -0
  67. package/esm/welcome/index.d.ts +22 -0
  68. package/esm/welcome/index.js +36 -0
  69. package/esm/welcome/index.less +57 -0
  70. package/esm/x-provider/index.d.ts +48 -0
  71. package/esm/x-provider/index.js +66 -0
  72. package/package.json +69 -3
@@ -0,0 +1,124 @@
1
+ /* MarkdownContent — AI 消息的 Markdown 排版(科技感微调) */
2
+
3
+ .aura-x-markdown {
4
+ font-size: var(--aura-font-size-md);
5
+ line-height: 1.7;
6
+ word-break: break-word;
7
+
8
+ > :first-child {
9
+ margin-top: 0;
10
+ }
11
+
12
+ > :last-child {
13
+ margin-bottom: 0;
14
+ }
15
+
16
+ h1,
17
+ h2,
18
+ h3,
19
+ h4,
20
+ h5,
21
+ h6 {
22
+ margin: var(--aura-spacing-4) 0 var(--aura-spacing-2);
23
+ font-weight: 600;
24
+ line-height: 1.4;
25
+ }
26
+
27
+ p {
28
+ margin: var(--aura-spacing-2) 0;
29
+ }
30
+
31
+ ul,
32
+ ol {
33
+ margin: var(--aura-spacing-2) 0;
34
+ padding-left: var(--aura-spacing-5);
35
+ }
36
+
37
+ li {
38
+ margin: 4px 0;
39
+ }
40
+
41
+ /* 行内代码:品牌色点染 */
42
+ code {
43
+ padding: 2px 6px;
44
+ border-radius: var(--aura-radius-sm);
45
+ background: var(--aura-x-accent-soft);
46
+ color: var(--aura-x-accent);
47
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
48
+ font-size: 0.92em;
49
+ }
50
+
51
+ /* 代码块(highlightCode={false} 时的朴素形态):暗色科技底 + 细边框 */
52
+ pre {
53
+ margin: var(--aura-spacing-3) 0;
54
+ padding: var(--aura-spacing-3) var(--aura-spacing-4);
55
+ border-radius: var(--aura-radius-md);
56
+ border: 1px solid var(--aura-x-bubble-border);
57
+ background: var(--aura-x-code-bg);
58
+ overflow-x: auto;
59
+ }
60
+
61
+ pre code {
62
+ padding: 0;
63
+ border: none;
64
+ background: transparent;
65
+ color: var(--aura-text);
66
+ }
67
+
68
+ /* 围栏代码块默认交给 CodeHighlighter 渲染,这里只统一它的外边距,
69
+ 内层留白与底色由 CodeHighlighter 自己负责,避免与上面的 pre 规则打架 */
70
+ .aura-x-code-highlighter {
71
+ margin: var(--aura-spacing-3) 0;
72
+ }
73
+
74
+ a {
75
+ color: var(--aura-x-accent);
76
+ text-decoration: none;
77
+
78
+ &:hover {
79
+ text-decoration: underline;
80
+ }
81
+ }
82
+
83
+ /* 引用块:渐变左边线 + 品牌浅底 */
84
+ blockquote {
85
+ margin: var(--aura-spacing-3) 0;
86
+ padding: var(--aura-spacing-2) var(--aura-spacing-4);
87
+ border-left: 3px solid var(--aura-x-accent);
88
+ border-radius: 0 var(--aura-radius-sm) var(--aura-radius-sm) 0;
89
+ background: var(--aura-x-accent-soft);
90
+ color: var(--aura-text-secondary);
91
+ }
92
+
93
+ table {
94
+ margin: var(--aura-spacing-3) 0;
95
+ border-collapse: collapse;
96
+ width: 100%;
97
+ }
98
+
99
+ th,
100
+ td {
101
+ padding: var(--aura-spacing-2) var(--aura-spacing-3);
102
+ border: 1px solid var(--aura-x-bubble-border);
103
+ text-align: left;
104
+ }
105
+
106
+ th {
107
+ font-weight: 600;
108
+ background: var(--aura-x-accent-soft);
109
+ }
110
+
111
+ hr {
112
+ margin: var(--aura-spacing-4) 0;
113
+ border: none;
114
+ border-top: 1px solid var(--aura-x-bubble-border);
115
+ }
116
+ }
117
+
118
+ /* 暗色下的局部微调 */
119
+ [data-theme='dark'] .aura-x-markdown {
120
+ blockquote,
121
+ th {
122
+ background: rgba(139, 92, 246, 0.08);
123
+ }
124
+ }
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ /**
3
+ * mermaid 的配置项。
4
+ *
5
+ * 刻意不 `import type { MermaidConfig } from 'mermaid'`:mermaid 是**可选** peer
6
+ * 依赖,若在类型层硬依赖它,未安装 mermaid 的消费方连 `import { Mermaid }`
7
+ * 都会因找不到类型而编译失败——可选依赖必须做到类型层面也可选。
8
+ */
9
+ export type MermaidConfig = Record<string, unknown>;
10
+ export interface MermaidActions {
11
+ /** 显示放大 / 缩小按钮 @default true */
12
+ enableZoom?: boolean;
13
+ /** 显示下载 SVG 按钮 @default true */
14
+ enableDownload?: boolean;
15
+ /** 显示复制源码按钮 @default true */
16
+ enableCopy?: boolean;
17
+ /** 追加自定义操作节点 */
18
+ customActions?: React.ReactNode;
19
+ }
20
+ export interface MermaidProps {
21
+ /** mermaid 源码 */
22
+ children?: string;
23
+ /**
24
+ * 头部内容:
25
+ * - 不传:默认头部(图片 / 代码切换 + 操作按钮)
26
+ * - `null`:不渲染头部
27
+ * - 其他节点:完全自定义(此时不再渲染内置操作按钮)
28
+ */
29
+ header?: React.ReactNode | null;
30
+ /**
31
+ * mermaid 配置。**必须是引用稳定的对象**(`useMemo` / 模块常量),
32
+ * 否则每次父组件重渲染都会重新初始化并重绘图表。
33
+ */
34
+ config?: MermaidConfig;
35
+ actions?: MermaidActions;
36
+ /** 渲染类型切换回调 */
37
+ onRenderTypeChange?: (value: 'image' | 'code') => void;
38
+ className?: string;
39
+ style?: React.CSSProperties;
40
+ }
41
+ /**
42
+ * Mermaid — 图表。
43
+ *
44
+ * 把 mermaid 源码渲染为 SVG,并提供图片 / 代码双视图、缩放、重置、下载与复制。
45
+ * mermaid 通过动态 `import()` 按需加载,因此不装它也不会拖累主包体积。
46
+ */
47
+ export declare const Mermaid: React.FC<MermaidProps>;
@@ -0,0 +1,235 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { classNames, prefixCls } from '@aura-react-comp/shared';
3
+ import { CodeHighlighter } from "../code-highlighter";
4
+
5
+ /**
6
+ * mermaid 的配置项。
7
+ *
8
+ * 刻意不 `import type { MermaidConfig } from 'mermaid'`:mermaid 是**可选** peer
9
+ * 依赖,若在类型层硬依赖它,未安装 mermaid 的消费方连 `import { Mermaid }`
10
+ * 都会因找不到类型而编译失败——可选依赖必须做到类型层面也可选。
11
+ */
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { Fragment as _Fragment } from "react/jsx-runtime";
14
+ import { jsxs as _jsxs } from "react/jsx-runtime";
15
+ const SCALE_STEP = 0.2;
16
+ const SCALE_MIN = 0.4;
17
+ const SCALE_MAX = 3;
18
+
19
+ /** 默认配置:不自动扫描页面、安全级别 strict(对图表内的 HTML / 链接做净化) */
20
+ const DEFAULT_CONFIG = {
21
+ startOnLoad: false,
22
+ securityLevel: 'strict'
23
+ };
24
+
25
+ /** mermaid 实例 id 需为 CSS 安全字符,故不用 useId(其返回值含冒号) */
26
+ let instanceSeq = 0;
27
+ const nextInstanceId = () => `aura-x-mermaid-${instanceSeq++}`;
28
+ /** 动态加载 mermaid:重依赖不进主包,未安装时才在运行到该组件时报错 */
29
+ async function loadMermaid() {
30
+ try {
31
+ const mod = await import('mermaid');
32
+ return mod.default ?? mod;
33
+ } catch {
34
+ throw new Error('未安装 mermaid:请先 `pnpm add mermaid` 再使用 <Mermaid />');
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Mermaid — 图表。
40
+ *
41
+ * 把 mermaid 源码渲染为 SVG,并提供图片 / 代码双视图、缩放、重置、下载与复制。
42
+ * mermaid 通过动态 `import()` 按需加载,因此不装它也不会拖累主包体积。
43
+ */
44
+ export const Mermaid = ({
45
+ children,
46
+ header,
47
+ config,
48
+ actions,
49
+ onRenderTypeChange,
50
+ className,
51
+ style
52
+ }) => {
53
+ const code = children ?? '';
54
+ const [instanceId] = useState(nextInstanceId);
55
+ const [view, setView] = useState('image');
56
+ const [status, setStatus] = useState('loading');
57
+ const [svg, setSvg] = useState('');
58
+ const [error, setError] = useState('');
59
+ const [scale, setScale] = useState(1);
60
+ const renderSeq = useRef(0);
61
+ const timerRef = useRef(null);
62
+ const [copied, setCopied] = useState(false);
63
+ useEffect(() => {
64
+ let cancelled = false;
65
+ const seq = ++renderSeq.current;
66
+ const isCurrent = () => !cancelled && seq === renderSeq.current;
67
+ setStatus('loading');
68
+ setError('');
69
+ (async () => {
70
+ let runtime;
71
+ try {
72
+ runtime = await loadMermaid();
73
+ } catch (loadError) {
74
+ if (!isCurrent()) return;
75
+ setError(loadError.message);
76
+ setStatus('error');
77
+ return;
78
+ }
79
+ try {
80
+ runtime.initialize({
81
+ ...DEFAULT_CONFIG,
82
+ ...config
83
+ });
84
+ const {
85
+ svg: output
86
+ } = await runtime.render(`${instanceId}-${seq}`, code);
87
+ if (!isCurrent()) return;
88
+ setSvg(output);
89
+ setStatus('ready');
90
+ } catch (renderError) {
91
+ if (!isCurrent()) return;
92
+ // 语法错误等:保留错误信息,同时把代码视图作为兜底呈现
93
+ setError(renderError instanceof Error ? renderError.message : String(renderError));
94
+ setStatus('error');
95
+ }
96
+ })();
97
+ return () => {
98
+ cancelled = true;
99
+ };
100
+ }, [code, config, instanceId]);
101
+ useEffect(() => () => {
102
+ if (timerRef.current !== null) window.clearTimeout(timerRef.current);
103
+ }, []);
104
+ const changeView = useCallback(next => {
105
+ setView(next);
106
+ onRenderTypeChange?.(next);
107
+ }, [onRenderTypeChange]);
108
+ const zoom = useCallback(delta => {
109
+ setScale(prev => Math.min(SCALE_MAX, Math.max(SCALE_MIN, Number((prev + delta).toFixed(2)))));
110
+ }, []);
111
+ const handleDownload = useCallback(() => {
112
+ if (!svg) return;
113
+ const blob = new Blob([svg], {
114
+ type: 'image/svg+xml;charset=utf-8'
115
+ });
116
+ const url = URL.createObjectURL(blob);
117
+ const anchor = document.createElement('a');
118
+ anchor.href = url;
119
+ anchor.download = `${instanceId}.svg`;
120
+ document.body.appendChild(anchor);
121
+ anchor.click();
122
+ anchor.remove();
123
+ URL.revokeObjectURL(url);
124
+ }, [svg, instanceId]);
125
+ const handleCopy = useCallback(async () => {
126
+ try {
127
+ if (typeof navigator === 'undefined' || !navigator.clipboard?.writeText) {
128
+ throw new Error('clipboard unavailable');
129
+ }
130
+ await navigator.clipboard.writeText(code);
131
+ } catch {
132
+ return;
133
+ }
134
+ setCopied(true);
135
+ if (timerRef.current !== null) window.clearTimeout(timerRef.current);
136
+ timerRef.current = window.setTimeout(() => setCopied(false), 1500);
137
+ }, [code]);
138
+ const showZoom = actions?.enableZoom !== false;
139
+ const showDownload = actions?.enableDownload !== false;
140
+ const showCopy = actions?.enableCopy !== false;
141
+ const defaultHeader = /*#__PURE__*/_jsxs("div", {
142
+ className: prefixCls('x-mermaid-header'),
143
+ children: [/*#__PURE__*/_jsx("div", {
144
+ className: prefixCls('x-mermaid-views'),
145
+ role: "group",
146
+ "aria-label": "\u6E32\u67D3\u89C6\u56FE\u5207\u6362",
147
+ children: [['image', '图片'], ['code', '代码']].map(([value, label]) => /*#__PURE__*/_jsx("button", {
148
+ type: "button",
149
+ className: classNames(prefixCls('x-mermaid-view-btn'), view === value && prefixCls('x-mermaid-view-btn--active')),
150
+ "aria-pressed": view === value,
151
+ onClick: () => changeView(value),
152
+ children: label
153
+ }, value))
154
+ }), /*#__PURE__*/_jsxs("div", {
155
+ className: prefixCls('x-mermaid-actions'),
156
+ children: [showZoom ? /*#__PURE__*/_jsxs(_Fragment, {
157
+ children: [/*#__PURE__*/_jsx("button", {
158
+ type: "button",
159
+ className: prefixCls('x-mermaid-action'),
160
+ "aria-label": "\u653E\u5927",
161
+ disabled: scale >= SCALE_MAX,
162
+ onClick: () => zoom(SCALE_STEP),
163
+ children: "\uFF0B"
164
+ }), /*#__PURE__*/_jsx("button", {
165
+ type: "button",
166
+ className: prefixCls('x-mermaid-action'),
167
+ "aria-label": "\u7F29\u5C0F",
168
+ disabled: scale <= SCALE_MIN,
169
+ onClick: () => zoom(-SCALE_STEP),
170
+ children: "\uFF0D"
171
+ }), /*#__PURE__*/_jsx("button", {
172
+ type: "button",
173
+ className: prefixCls('x-mermaid-action'),
174
+ "aria-label": "\u91CD\u7F6E\u7F29\u653E",
175
+ onClick: () => setScale(1),
176
+ children: "\u91CD\u7F6E"
177
+ })]
178
+ }) : null, showCopy ? /*#__PURE__*/_jsx("button", {
179
+ type: "button",
180
+ className: prefixCls('x-mermaid-action'),
181
+ "aria-label": copied ? '已复制' : '复制源码',
182
+ onClick: handleCopy,
183
+ children: copied ? '已复制' : '复制'
184
+ }) : null, showDownload ? /*#__PURE__*/_jsx("button", {
185
+ type: "button",
186
+ className: prefixCls('x-mermaid-action'),
187
+ "aria-label": "\u4E0B\u8F7D SVG",
188
+ disabled: !svg,
189
+ onClick: handleDownload,
190
+ children: "\u4E0B\u8F7D"
191
+ }) : null, actions?.customActions]
192
+ })]
193
+ });
194
+ const resolvedHeader = header === null ? null : header ?? defaultHeader;
195
+ return /*#__PURE__*/_jsxs("div", {
196
+ className: classNames(prefixCls('x-mermaid'), className),
197
+ style: style,
198
+ children: [resolvedHeader, /*#__PURE__*/_jsx("div", {
199
+ className: classNames(prefixCls('x-mermaid-body'), view === 'code' && prefixCls('x-mermaid-body--code')),
200
+ children: view === 'code' ? /*#__PURE__*/_jsx(CodeHighlighter, {
201
+ lang: "mermaid",
202
+ children: code
203
+ }) : status === 'error' ? /*#__PURE__*/_jsxs("div", {
204
+ className: prefixCls('x-mermaid-error'),
205
+ role: "alert",
206
+ children: [/*#__PURE__*/_jsx("p", {
207
+ className: prefixCls('x-mermaid-error-title'),
208
+ children: "\u56FE\u8868\u6E32\u67D3\u5931\u8D25"
209
+ }), /*#__PURE__*/_jsx("pre", {
210
+ className: prefixCls('x-mermaid-error-detail'),
211
+ children: error
212
+ })]
213
+ }) : status === 'loading' ? /*#__PURE__*/_jsx("div", {
214
+ className: prefixCls('x-mermaid-loading'),
215
+ "aria-busy": "true",
216
+ children: "\u6B63\u5728\u6E32\u67D3\u56FE\u8868\u2026"
217
+ }) : /*#__PURE__*/_jsx("div", {
218
+ className: prefixCls('x-mermaid-graph'),
219
+ children: /*#__PURE__*/_jsx("div", {
220
+ className: prefixCls('x-mermaid-canvas'),
221
+ style: {
222
+ transform: `scale(${scale})`
223
+ }
224
+ // mermaid 在本机按源码生成 SVG;安全级别已固定为 strict(净化内联
225
+ // HTML 与链接协议),注入面与直接用 mermaid 渲染一致。
226
+ ,
227
+ dangerouslySetInnerHTML: {
228
+ __html: svg
229
+ }
230
+ })
231
+ })
232
+ })]
233
+ });
234
+ };
235
+ Mermaid.displayName = 'Mermaid';
@@ -0,0 +1,155 @@
1
+ /* Mermaid — 图表(头部操作栏 + 图片 / 代码双视图) */
2
+
3
+ .aura-x-mermaid {
4
+ overflow: hidden;
5
+ border: 1px solid var(--aura-x-bubble-border);
6
+ border-radius: var(--aura-radius-md);
7
+ background: var(--aura-x-bubble-ai-bg);
8
+ }
9
+
10
+ /* ===== 头部 ===== */
11
+
12
+ .aura-x-mermaid-header {
13
+ display: flex;
14
+ gap: var(--aura-spacing-2);
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ padding: var(--aura-spacing-1) var(--aura-spacing-2) var(--aura-spacing-1)
18
+ var(--aura-spacing-3);
19
+ border-bottom: 1px solid var(--aura-border);
20
+ background: var(--aura-x-stage-bg);
21
+ }
22
+
23
+ .aura-x-mermaid-views {
24
+ display: inline-flex;
25
+ gap: var(--aura-spacing-1);
26
+ }
27
+
28
+ .aura-x-mermaid-view-btn {
29
+ padding: var(--aura-spacing-1) var(--aura-spacing-2);
30
+ border: none;
31
+ border-radius: var(--aura-radius-sm);
32
+ background: transparent;
33
+ color: var(--aura-text-secondary);
34
+ font-size: var(--aura-font-size-xs);
35
+ cursor: pointer;
36
+ transition:
37
+ background var(--aura-duration-fast) var(--aura-easing),
38
+ color var(--aura-duration-fast) var(--aura-easing);
39
+ }
40
+
41
+ .aura-x-mermaid-view-btn--active {
42
+ background: var(--aura-x-accent-soft);
43
+ color: var(--aura-x-accent);
44
+ font-weight: 600;
45
+ }
46
+
47
+ .aura-x-mermaid-view-btn:focus-visible,
48
+ .aura-x-mermaid-action:focus-visible {
49
+ outline: none;
50
+ box-shadow: var(--aura-x-focus-ring);
51
+ }
52
+
53
+ .aura-x-mermaid-actions {
54
+ display: inline-flex;
55
+ gap: var(--aura-spacing-1);
56
+ align-items: center;
57
+ }
58
+
59
+ .aura-x-mermaid-action {
60
+ padding: var(--aura-spacing-1) var(--aura-spacing-2);
61
+ border: none;
62
+ border-radius: var(--aura-radius-sm);
63
+ background: transparent;
64
+ color: var(--aura-text-secondary);
65
+ font-size: var(--aura-font-size-xs);
66
+ line-height: 1.5;
67
+ cursor: pointer;
68
+ transition:
69
+ background var(--aura-duration-fast) var(--aura-easing),
70
+ color var(--aura-duration-fast) var(--aura-easing);
71
+ }
72
+
73
+ .aura-x-mermaid-action:hover:not(:disabled) {
74
+ background: var(--aura-x-accent-soft);
75
+ color: var(--aura-x-accent);
76
+ }
77
+
78
+ .aura-x-mermaid-action:disabled {
79
+ color: var(--aura-text-tertiary);
80
+ cursor: default;
81
+ }
82
+
83
+ /* ===== 内容区 ===== */
84
+
85
+ .aura-x-mermaid-body {
86
+ padding: var(--aura-spacing-3);
87
+ }
88
+
89
+ /* 代码视图下把内嵌 CodeHighlighter 的外框抹平,避免双层边框 */
90
+ .aura-x-mermaid-body--code {
91
+ padding: 0;
92
+ }
93
+
94
+ .aura-x-mermaid-body--code .aura-x-code-highlighter {
95
+ border: none;
96
+ border-radius: 0;
97
+ }
98
+
99
+ .aura-x-mermaid-graph {
100
+ overflow: auto;
101
+ max-height: 420px;
102
+ background: var(--aura-x-stage-bg);
103
+ border-radius: var(--aura-radius-sm);
104
+ }
105
+
106
+ .aura-x-mermaid-canvas {
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ padding: var(--aura-spacing-3);
111
+ transform-origin: center center;
112
+ transition: transform var(--aura-duration-normal) var(--aura-easing);
113
+ }
114
+
115
+ .aura-x-mermaid-canvas > svg {
116
+ max-width: 100%;
117
+ height: auto;
118
+ }
119
+
120
+ .aura-x-mermaid-loading {
121
+ padding: var(--aura-spacing-6) 0;
122
+ color: var(--aura-text-secondary);
123
+ font-size: var(--aura-font-size-sm);
124
+ text-align: center;
125
+ }
126
+
127
+ .aura-x-mermaid-error {
128
+ padding: var(--aura-spacing-3);
129
+ border: 1px solid var(--aura-error);
130
+ border-radius: var(--aura-radius-sm);
131
+ background: var(--aura-error-light);
132
+ }
133
+
134
+ .aura-x-mermaid-error-title {
135
+ margin: 0 0 var(--aura-spacing-1);
136
+ color: var(--aura-error);
137
+ font-size: var(--aura-font-size-sm);
138
+ font-weight: 600;
139
+ }
140
+
141
+ .aura-x-mermaid-error-detail {
142
+ margin: 0;
143
+ overflow-x: auto;
144
+ color: var(--aura-text-secondary);
145
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
146
+ font-size: var(--aura-font-size-xs);
147
+ line-height: 1.6;
148
+ white-space: pre-wrap;
149
+ }
150
+
151
+ @media (prefers-reduced-motion: reduce) {
152
+ .aura-x-mermaid-canvas {
153
+ transition: none;
154
+ }
155
+ }
@@ -0,0 +1,59 @@
1
+ /** 当前来源(origin)的浏览器通知授权状态 */
2
+ export type XNotificationPermission = NotificationPermission;
3
+ export interface XNotificationConfig extends NotificationOptions {
4
+ /** 通知标题(浏览器不提供默认值,必填) */
5
+ title: string;
6
+ /** 自动关闭延时(毫秒);不传或非正数则不自动关闭 */
7
+ duration?: number;
8
+ /** 点击通知;第二个参数可直接关闭本条通知 */
9
+ onClick?: (event: Event, close: () => void) => void;
10
+ onClose?: (event: Event) => void;
11
+ onError?: (event: Event) => void;
12
+ onShow?: (event: Event) => void;
13
+ }
14
+ /**
15
+ * `open` 的参数:既接受扁平的 {@link XNotificationConfig},
16
+ * 也接受 antdx 风格的 `{ openConfig, closeConfig }` 包装形态。
17
+ * `closeConfig` 用于在弹出新通知前先关掉指定 `tag` 的旧通知。
18
+ */
19
+ export type XNotificationOpenArgs = XNotificationConfig | {
20
+ openConfig: XNotificationConfig;
21
+ /** 先关闭这些 tag 的通知(`undefined` 项会被忽略) */
22
+ closeConfig?: (string | undefined)[];
23
+ };
24
+ export interface XNotificationApi {
25
+ /** 当前授权状态;每次读取都向浏览器取实时值 */
26
+ readonly permission: XNotificationPermission;
27
+ /** 向用户请求通知权限 */
28
+ requestPermission: () => Promise<XNotificationPermission>;
29
+ /** 推送一条通知;未授权或环境不支持时静默无效果 */
30
+ open: (args: XNotificationOpenArgs) => void;
31
+ /** 关闭通知:传 tag 列表只关指定的,不传则关闭本实例发出的全部 */
32
+ close: (tags?: string[]) => void;
33
+ }
34
+ export type UseNotificationResult = [
35
+ {
36
+ permission: XNotificationPermission;
37
+ },
38
+ {
39
+ open: XNotificationApi['open'];
40
+ close: XNotificationApi['close'];
41
+ requestPermission: XNotificationApi['requestPermission'];
42
+ }
43
+ ];
44
+ /**
45
+ * XNotification — 浏览器**系统通知**的命令式 API(对标 antdx 的 `notification`)。
46
+ *
47
+ * 注意这是「页面外的系统级通知」,走 `window.Notification`,受操作系统与浏览器
48
+ * 通知权限管控——**不是**页面内的消息条。页面内的提示请用 `@aura-react-comp/ui` 的
49
+ * `Notification` / `Message`。
50
+ */
51
+ export declare const XNotification: XNotificationApi;
52
+ /**
53
+ * useNotification — `XNotification` 的 Hook 形态。
54
+ *
55
+ * 返回 `[{ permission }, { open, close, requestPermission }]`。
56
+ * `permission` 首帧固定为 `'denied'`,挂载后(`useEffect` 中)再同步真实值,
57
+ * 以避免服务端渲染与水合结果不一致。
58
+ */
59
+ export declare function useNotification(): UseNotificationResult;