listpage-next 0.0.145 → 0.0.146
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/demos/demo11.js +44 -4
- package/dist/features/ChatClient/components/Bubble/Bubble.d.ts +16 -0
- package/dist/features/ChatClient/components/Bubble/Bubble.js +88 -0
- package/dist/features/ChatClient/components/Bubble/Markdown.d.ts +4 -0
- package/dist/features/ChatClient/components/Bubble/Markdown.js +42 -0
- package/dist/features/ChatClient/components/{Reasoning/index.d.ts → Bubble/Reasoning.d.ts} +2 -2
- package/dist/features/ChatClient/components/{Reasoning/index.js → Bubble/Reasoning.js} +38 -34
- package/dist/features/ChatClient/components/{SuggestMessageList/index.d.ts → Bubble/SuggestMessageList.d.ts} +1 -0
- package/dist/features/ChatClient/components/Bubble/index.d.ts +4 -2
- package/dist/features/ChatClient/components/Bubble/index.js +4 -57
- package/dist/features/ChatClient/index.d.ts +0 -3
- package/dist/features/ChatClient/index.js +0 -3
- package/package.json +5 -3
- package/dist/features/ChatClient/components/Bubble/types.d.ts +0 -8
- package/dist/features/ChatClient/components/Bubble/types.js +0 -0
- /package/dist/features/ChatClient/components/{ReferenceList/index.d.ts → Bubble/ReferenceList.d.ts} +0 -0
- /package/dist/features/ChatClient/components/{ReferenceList/index.js → Bubble/ReferenceList.js} +0 -0
- /package/dist/features/ChatClient/components/{SuggestMessageList/index.js → Bubble/SuggestMessageList.js} +0 -0
package/dist/demos/demo11.js
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Flex } from "antd";
|
|
3
|
+
import { Bubble, SuggestMessageList } from "../features/ChatClient/index.js";
|
|
4
|
+
import { ApiOutlined } from "@ant-design/icons";
|
|
5
|
+
const Demo11 = ()=>{
|
|
6
|
+
const feedback = /*#__PURE__*/ jsxs(Flex, {
|
|
7
|
+
gap: 8,
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ jsx(Button, {
|
|
10
|
+
size: "small",
|
|
11
|
+
type: "text",
|
|
12
|
+
icon: /*#__PURE__*/ jsx(ApiOutlined, {})
|
|
13
|
+
}),
|
|
14
|
+
/*#__PURE__*/ jsx(Button, {
|
|
15
|
+
size: "small",
|
|
16
|
+
type: "text",
|
|
17
|
+
icon: /*#__PURE__*/ jsx(ApiOutlined, {})
|
|
18
|
+
}),
|
|
19
|
+
/*#__PURE__*/ jsx(Button, {
|
|
20
|
+
size: "small",
|
|
21
|
+
type: "text",
|
|
22
|
+
icon: /*#__PURE__*/ jsx(ApiOutlined, {})
|
|
23
|
+
})
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
const suggests = /*#__PURE__*/ jsx(SuggestMessageList, {
|
|
27
|
+
suggests: [
|
|
28
|
+
{
|
|
29
|
+
title: '推荐问题1'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: '推荐问题2'
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
return /*#__PURE__*/ jsx(Bubble, {
|
|
37
|
+
reasoning_content: content,
|
|
38
|
+
content: content,
|
|
39
|
+
role: "assistant",
|
|
40
|
+
feedback: feedback,
|
|
4
41
|
references: [
|
|
5
42
|
{
|
|
6
43
|
title: '从通用到专业:大模型在医疗领域的四阶段训练方法与落地实践-CSDN博客',
|
|
@@ -11,8 +48,11 @@ const Demo11 = ()=>/*#__PURE__*/ jsx(ReferenceList, {
|
|
|
11
48
|
title: '测试2',
|
|
12
49
|
url: 'https://www.baidu.com'
|
|
13
50
|
}
|
|
14
|
-
]
|
|
51
|
+
],
|
|
52
|
+
suggests: suggests,
|
|
53
|
+
showFeedback: ()=>true
|
|
15
54
|
});
|
|
55
|
+
};
|
|
16
56
|
const content = `传统RAG 的检索环节多依赖单一语义检索(如向量相似度),但这种方式存在语义偏差(无法处理精确关键词)、长尾覆盖不足(罕见查询匹配差)等问题。检索增强的核心是混合检索(Hybrid Retrieval),即结合语义检索与关键词检索的优势,实现“精准匹配+广泛覆盖”的平衡。
|
|
17
57
|
混合检索的本质是两种检索结果的加权融合 ,通过线性加权公式计算综合得分:
|
|
18
58
|
BM25_score:基于关键词匹配的得分(由TF-IDF改进而来,考虑词频、文档长度归一化),擅长处理精确关键词(如产品型号、法律条款编号);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ReferenceListProps } from './ReferenceList';
|
|
3
|
+
export type BubbleProps = {
|
|
4
|
+
feedback?: ReactNode;
|
|
5
|
+
showFeedback?: (hovered: boolean) => boolean;
|
|
6
|
+
suggests?: ReactNode;
|
|
7
|
+
extra?: ReactNode;
|
|
8
|
+
content?: string;
|
|
9
|
+
reasoning_content?: string;
|
|
10
|
+
references?: ReferenceListProps['references'];
|
|
11
|
+
placement?: 'start' | 'end';
|
|
12
|
+
role?: 'user' | 'assistant';
|
|
13
|
+
markdownRender?: (text: string) => ReactNode;
|
|
14
|
+
reasoningMarkdownRender?: (text: string) => ReactNode;
|
|
15
|
+
};
|
|
16
|
+
export declare const Bubble: (props: BubbleProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { useHover } from "ahooks";
|
|
4
|
+
import styled_components from "styled-components";
|
|
5
|
+
import { Markdown } from "./Markdown.js";
|
|
6
|
+
import { Reasoning } from "./Reasoning.js";
|
|
7
|
+
import { ReferenceList } from "./ReferenceList.js";
|
|
8
|
+
const Bubble = (props)=>{
|
|
9
|
+
const { content, reasoning_content, extra, feedback, markdownRender, reasoningMarkdownRender = markdownRender, references, suggests, role = 'user', placement = 'user' === role ? 'end' : 'start', showFeedback = (hovered)=>hovered } = props;
|
|
10
|
+
const ref = useRef(null);
|
|
11
|
+
const hovered = useHover(ref);
|
|
12
|
+
const messageMarkdownEle = markdownRender ? markdownRender(content || '') : /*#__PURE__*/ jsx(Markdown, {
|
|
13
|
+
content: content || ''
|
|
14
|
+
});
|
|
15
|
+
const reasoningMarkdownEle = reasoningMarkdownRender ? reasoningMarkdownRender(reasoning_content || '') : /*#__PURE__*/ jsx(Markdown, {
|
|
16
|
+
content: reasoning_content || ''
|
|
17
|
+
});
|
|
18
|
+
const message = 'user' === role ? /*#__PURE__*/ jsx(UserContentWrapper, {
|
|
19
|
+
children: messageMarkdownEle
|
|
20
|
+
}) : /*#__PURE__*/ jsx(AssistantContentWrapper, {
|
|
21
|
+
children: messageMarkdownEle
|
|
22
|
+
});
|
|
23
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
24
|
+
children: [
|
|
25
|
+
/*#__PURE__*/ jsxs(BubbleContainer, {
|
|
26
|
+
placement: placement,
|
|
27
|
+
ref: ref,
|
|
28
|
+
children: [
|
|
29
|
+
Boolean(reasoning_content) && /*#__PURE__*/ jsx(Reasoning, {
|
|
30
|
+
thinking: Boolean(!content),
|
|
31
|
+
children: reasoningMarkdownEle
|
|
32
|
+
}),
|
|
33
|
+
message,
|
|
34
|
+
Boolean(references?.length) && /*#__PURE__*/ jsx(ReferenceList, {
|
|
35
|
+
references: references ?? []
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
}),
|
|
39
|
+
extra,
|
|
40
|
+
feedback && /*#__PURE__*/ jsx(ToolContainer, {
|
|
41
|
+
children: showFeedback(hovered) && feedback
|
|
42
|
+
}),
|
|
43
|
+
suggests && /*#__PURE__*/ jsx(SuggestContainer, {
|
|
44
|
+
children: suggests
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const BubbleContainer = styled_components.div`
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
gap: 20px;
|
|
53
|
+
margin-top: 12px;
|
|
54
|
+
align-items: ${(props)=>'start' === props.placement ? 'flex-start' : 'flex-end'};
|
|
55
|
+
`;
|
|
56
|
+
const UserContentWrapper = styled_components.div`
|
|
57
|
+
color: #000000d9;
|
|
58
|
+
padding: 9px 16px;
|
|
59
|
+
font-size: 16px;
|
|
60
|
+
line-height: 24px;
|
|
61
|
+
font-weight: 400;
|
|
62
|
+
min-width: 0px;
|
|
63
|
+
font-family: sans-serif;
|
|
64
|
+
|
|
65
|
+
width: fit-content;
|
|
66
|
+
background-color: #0000000a;
|
|
67
|
+
border-radius: 12px;
|
|
68
|
+
max-width: 450px;
|
|
69
|
+
`;
|
|
70
|
+
const AssistantContentWrapper = styled_components.div`
|
|
71
|
+
color: #000000d9;
|
|
72
|
+
padding: 0px;
|
|
73
|
+
font-size: 16px;
|
|
74
|
+
line-height: 24px;
|
|
75
|
+
font-weight: 400;
|
|
76
|
+
min-width: 0px;
|
|
77
|
+
font-family: sans-serif;
|
|
78
|
+
`;
|
|
79
|
+
const ToolContainer = styled_components.div`
|
|
80
|
+
height: 40px;
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: row;
|
|
83
|
+
align-items: flex-end;
|
|
84
|
+
`;
|
|
85
|
+
const SuggestContainer = styled_components.div`
|
|
86
|
+
margin-top: 24px;
|
|
87
|
+
`;
|
|
88
|
+
export { Bubble };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import markdown_it from "markdown-it";
|
|
3
|
+
import styled_components from "styled-components";
|
|
4
|
+
const md = markdown_it({
|
|
5
|
+
html: true,
|
|
6
|
+
breaks: true
|
|
7
|
+
});
|
|
8
|
+
const defaultLinkOpen = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
|
|
9
|
+
return self.renderToken(tokens, idx, options);
|
|
10
|
+
};
|
|
11
|
+
md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
|
|
12
|
+
const targetIndex = tokens[idx].attrIndex('target');
|
|
13
|
+
if (targetIndex < 0) tokens[idx].attrPush([
|
|
14
|
+
'target',
|
|
15
|
+
'_blank'
|
|
16
|
+
]);
|
|
17
|
+
else tokens[idx].attrs[targetIndex][1] = '_blank';
|
|
18
|
+
const relIndex = tokens[idx].attrIndex('rel');
|
|
19
|
+
if (relIndex < 0) tokens[idx].attrPush([
|
|
20
|
+
'rel',
|
|
21
|
+
'noopener noreferrer'
|
|
22
|
+
]);
|
|
23
|
+
else tokens[idx].attrs[relIndex][1] = 'noopener noreferrer';
|
|
24
|
+
return defaultLinkOpen(tokens, idx, options, env, self);
|
|
25
|
+
};
|
|
26
|
+
const Markdown = (props)=>/*#__PURE__*/ jsx(MarkdownBody, {
|
|
27
|
+
dangerouslySetInnerHTML: {
|
|
28
|
+
__html: md.render(props.content)
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const MarkdownBody = styled_components.div`
|
|
32
|
+
h1 {
|
|
33
|
+
font-size: 18px;
|
|
34
|
+
}
|
|
35
|
+
h2 {
|
|
36
|
+
font-size: 16px;
|
|
37
|
+
}
|
|
38
|
+
p {
|
|
39
|
+
margin: 3px !important;
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
export { Markdown };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from
|
|
2
|
-
export declare const Reasoning: ({ thinking, children }: {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export declare const Reasoning: ({ thinking, children, }: {
|
|
3
3
|
thinking?: boolean;
|
|
4
4
|
children?: ReactNode;
|
|
5
5
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -43,61 +43,65 @@ const ReasoningContainer = styled.div`
|
|
|
43
43
|
cursor: pointer;
|
|
44
44
|
border: 1px solid #ebebeb;
|
|
45
45
|
border-radius: 12px;
|
|
46
|
-
margin-bottom: 20px;
|
|
47
46
|
transition: height 0.3s ease-in-out;
|
|
48
47
|
&:hover {
|
|
49
48
|
background-color: #0000000a;
|
|
50
49
|
}
|
|
50
|
+
min-width: 240px;
|
|
51
|
+
|
|
52
|
+
& > * {
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
}
|
|
51
55
|
`;
|
|
52
56
|
const ReasoningHeader = styled.div`
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: space-between;
|
|
56
60
|
`;
|
|
57
61
|
const ReasoningContent = styled.div`
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
color: #00000080 !important;
|
|
63
|
+
overflow: hidden;
|
|
60
64
|
`;
|
|
61
65
|
const ReasoningTitle = styled.div`
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
color: #000c;
|
|
67
|
+
font-size: 14px;
|
|
68
|
+
font-weight: 500;
|
|
65
69
|
`;
|
|
66
70
|
const ReasoningIcon = styled.div`
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
align-items: center;
|
|
72
|
+
border: 1px solid #00000014;
|
|
73
|
+
border-radius: 8px;
|
|
74
|
+
display: flex;
|
|
75
|
+
height: 28px;
|
|
76
|
+
justify-content: center;
|
|
77
|
+
padding: 5px 8px;
|
|
78
|
+
width: 28px;
|
|
79
|
+
box-sizing: border-box;
|
|
80
|
+
&:hover {
|
|
77
81
|
background-color: #0000000a;
|
|
78
|
-
|
|
82
|
+
}
|
|
79
83
|
`;
|
|
80
84
|
const ReasoningTitleAnimation = styled.span`
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
85
|
+
/* 文字流光动画 */
|
|
86
|
+
@keyframes textShine {
|
|
87
|
+
to {
|
|
88
|
+
background-position: 200% center;
|
|
86
89
|
}
|
|
90
|
+
}
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
background: linear-gradient(
|
|
93
|
+
90deg,
|
|
90
94
|
#3b82f6,
|
|
91
95
|
#93c5fd,
|
|
92
96
|
#3b82f6,
|
|
93
97
|
#93c5fd,
|
|
94
98
|
#3b82f6
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
);
|
|
100
|
+
background-size: 200% auto;
|
|
101
|
+
color: #000;
|
|
102
|
+
background-clip: text;
|
|
103
|
+
-webkit-background-clip: text;
|
|
104
|
+
-webkit-text-fill-color: transparent;
|
|
105
|
+
animation: textShine 3s linear infinite;
|
|
102
106
|
`;
|
|
103
107
|
export { Reasoning };
|
|
@@ -1,57 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const Bubble = (props)=>{
|
|
6
|
-
const { children, feedback, role = "user", placement = 'user' === role ? 'end' : 'start', showFeedback = (hovered)=>hovered } = props;
|
|
7
|
-
const ref = useRef(null);
|
|
8
|
-
const hovered = useHover(ref);
|
|
9
|
-
const content = "user" === role ? /*#__PURE__*/ jsx(UserContentWrapper, {
|
|
10
|
-
children: children
|
|
11
|
-
}) : /*#__PURE__*/ jsx(AssistantContentWrapper, {
|
|
12
|
-
children: children
|
|
13
|
-
});
|
|
14
|
-
return /*#__PURE__*/ jsxs(BubbleContainer, {
|
|
15
|
-
placement: placement,
|
|
16
|
-
ref: ref,
|
|
17
|
-
children: [
|
|
18
|
-
content,
|
|
19
|
-
feedback && /*#__PURE__*/ jsx(ToolContainer, {
|
|
20
|
-
children: showFeedback(hovered) && feedback
|
|
21
|
-
})
|
|
22
|
-
]
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
const BubbleContainer = styled_components.div`
|
|
26
|
-
display: flex;
|
|
27
|
-
flex-direction: column;
|
|
28
|
-
align-items: ${(props)=>"start" === props.placement ? "flex-start" : "flex-end"};
|
|
29
|
-
margin-top: 16px;
|
|
30
|
-
`;
|
|
31
|
-
const UserContentWrapper = styled_components.div`
|
|
32
|
-
color: #000000d9;
|
|
33
|
-
padding: 9px 16px;
|
|
34
|
-
font-size: 16px;
|
|
35
|
-
line-height: 24px;
|
|
36
|
-
font-weight: 400;
|
|
37
|
-
min-width: 0px;
|
|
38
|
-
font-family: sans-serif;
|
|
39
|
-
|
|
40
|
-
width: fit-content;
|
|
41
|
-
background-color: #0000000a;
|
|
42
|
-
border-radius: 12px;
|
|
43
|
-
max-width: 450px;
|
|
44
|
-
`;
|
|
45
|
-
const AssistantContentWrapper = styled_components.div`
|
|
46
|
-
color: #000000d9;
|
|
47
|
-
padding: 9px 16px;
|
|
48
|
-
font-size: 16px;
|
|
49
|
-
line-height: 24px;
|
|
50
|
-
font-weight: 400;
|
|
51
|
-
min-width: 0px;
|
|
52
|
-
font-family: sans-serif;
|
|
53
|
-
`;
|
|
54
|
-
const ToolContainer = styled_components.div`
|
|
55
|
-
height: 40px;
|
|
56
|
-
`;
|
|
57
|
-
export { Bubble };
|
|
1
|
+
export * from "./Bubble.js";
|
|
2
|
+
export * from "./Reasoning.js";
|
|
3
|
+
export * from "./ReferenceList.js";
|
|
4
|
+
export * from "./SuggestMessageList.js";
|
|
@@ -2,11 +2,8 @@ export * from './components/ChatPage';
|
|
|
2
2
|
export * from './components/ChatGuidance';
|
|
3
3
|
export * from './components/ChatContent';
|
|
4
4
|
export * from './components/Bubble';
|
|
5
|
-
export * from './components/Reasoning';
|
|
6
5
|
export { SimplifyChatPage, type SimplifyChatPageProps, } from './components/ChatPage/SimplifyChatPage';
|
|
7
6
|
export * from './components/ChatDialog';
|
|
8
|
-
export * from './components/SuggestMessageList';
|
|
9
|
-
export * from './components/ReferenceList';
|
|
10
7
|
export { useChatContext } from './context/useChatContext';
|
|
11
8
|
export * from './context/types';
|
|
12
9
|
export * from './utils/parseSse';
|
|
@@ -4,10 +4,7 @@ export * from "./components/ChatPage/index.js";
|
|
|
4
4
|
export * from "./components/ChatGuidance/index.js";
|
|
5
5
|
export * from "./components/ChatContent/index.js";
|
|
6
6
|
export * from "./components/Bubble/index.js";
|
|
7
|
-
export * from "./components/Reasoning/index.js";
|
|
8
7
|
export * from "./components/ChatDialog/index.js";
|
|
9
|
-
export * from "./components/SuggestMessageList/index.js";
|
|
10
|
-
export * from "./components/ReferenceList/index.js";
|
|
11
8
|
export * from "./context/types.js";
|
|
12
9
|
export * from "./utils/parseSse.js";
|
|
13
10
|
export { SimplifyChatPage, useChatContext };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "listpage-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.146",
|
|
4
4
|
"description": "A React component library for creating filter forms with Ant Design",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"storybook-addon-rslib": "^1.0.3",
|
|
47
47
|
"storybook-react-rsbuild": "^1.0.3",
|
|
48
48
|
"typescript": "^5.9.2",
|
|
49
|
-
"react-router-dom": ">=6.0.0"
|
|
49
|
+
"react-router-dom": ">=6.0.0",
|
|
50
|
+
"@types/markdown-it": "~14.1.2"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"react": ">=16.9.0",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"@ant-design/icons": "~6.0.2",
|
|
66
67
|
"mobx-react-lite": "~4.1.1",
|
|
67
68
|
"rc-virtual-list": "~3.19.2",
|
|
68
|
-
"react-draggable": "~4.5.0"
|
|
69
|
+
"react-draggable": "~4.5.0",
|
|
70
|
+
"markdown-it": "~14.1.0"
|
|
69
71
|
}
|
|
70
72
|
}
|
|
File without changes
|
/package/dist/features/ChatClient/components/{ReferenceList/index.d.ts → Bubble/ReferenceList.d.ts}
RENAMED
|
File without changes
|
/package/dist/features/ChatClient/components/{ReferenceList/index.js → Bubble/ReferenceList.js}
RENAMED
|
File without changes
|
|
File without changes
|