@nethru/kit 1.0.6 → 1.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.
- package/dist/components/charts/Chart.js +379 -0
- package/dist/components/charts/ChartColors.js +11 -0
- package/dist/components/charts/ColumnChart.js +118 -0
- package/dist/components/charts/Number.js +48 -0
- package/dist/components/charts/PieChart.js +168 -0
- package/dist/components/charts/StackedAreaTrendChart.js +52 -0
- package/dist/components/charts/TrendChart.js +30 -0
- package/dist/components/chat/AiChat.js +46 -0
- package/dist/components/chat/ChatInput.js +112 -0
- package/dist/components/chat/ChatMessage.js +76 -0
- package/dist/components/chat/ChatMessages.js +34 -0
- package/dist/components/chat/LoadingIndicator.js +48 -0
- package/dist/components/chat/content/MarkdownContent.css +151 -0
- package/dist/components/chat/content/MarkdownContent.js +14 -0
- package/dist/components/chat/content/ToolContent.js +86 -0
- package/dist/components/chat/content/wisecollector/ColumnChartContent.js +65 -0
- package/dist/components/chat/content/wisecollector/PieChartContent.js +89 -0
- package/dist/components/chat/content/wisecollector/StackedAreaChartContent.js +98 -0
- package/dist/components/chat/contexts/ToolContext.js +31 -0
- package/dist/components/chat/hooks/useChatApi.js +87 -0
- package/dist/components/chat/mock.js +737 -0
- package/dist/index.js +5 -22318
- package/dist/js/config.js +12 -0
- package/dist/js/dateHelper.js +78 -0
- package/package.json +17 -23
- package/dist/index.esm.js +0 -22311
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import Highcharts from 'highcharts';
|
|
3
|
+
import HighchartsReactModule from 'highcharts-react-official';
|
|
4
|
+
import 'highcharts/modules/pattern-fill.js';
|
|
5
|
+
|
|
6
|
+
// Handle both ES module and CommonJS exports
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
const HighchartsReact = HighchartsReactModule.default || HighchartsReactModule;
|
|
9
|
+
const PieChart = ({
|
|
10
|
+
data,
|
|
11
|
+
width = 230,
|
|
12
|
+
height = 180,
|
|
13
|
+
size = '60%',
|
|
14
|
+
colors = ['#2652a8', '#b47813', '#aa1a32']
|
|
15
|
+
}) => {
|
|
16
|
+
const noData = data.metrics.some(m => m.transparent);
|
|
17
|
+
const options = useMemo(() => {
|
|
18
|
+
const chartData = data.metrics.filter(metric => metric.transparent || metric.value > 0).map((metric, index) => ({
|
|
19
|
+
name: metric.label,
|
|
20
|
+
y: metric.value,
|
|
21
|
+
color: metric.transparent ? checkerboardPattern() : colors[index % colors.length]
|
|
22
|
+
}));
|
|
23
|
+
return {
|
|
24
|
+
chart: {
|
|
25
|
+
type: 'pie',
|
|
26
|
+
backgroundColor: 'transparent',
|
|
27
|
+
width: width,
|
|
28
|
+
height: height,
|
|
29
|
+
style: {
|
|
30
|
+
fontFamily: fontFamily
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
title: {
|
|
34
|
+
text: undefined
|
|
35
|
+
},
|
|
36
|
+
tooltip: {
|
|
37
|
+
pointFormat: '<span><b>{point.y}</b> ({point.percentage:.1f}%)</span>',
|
|
38
|
+
style: {
|
|
39
|
+
fontFamily: fontFamily,
|
|
40
|
+
fontSize: '13px'
|
|
41
|
+
},
|
|
42
|
+
useHTML: true
|
|
43
|
+
},
|
|
44
|
+
plotOptions: {
|
|
45
|
+
pie: {
|
|
46
|
+
size: size,
|
|
47
|
+
allowPointSelect: true,
|
|
48
|
+
cursor: 'pointer',
|
|
49
|
+
dataLabels: {
|
|
50
|
+
enabled: true,
|
|
51
|
+
format: '{point.name}<br><b>{point.y}</b> ({point.percentage:.1f}%)',
|
|
52
|
+
distance: 20,
|
|
53
|
+
style: {
|
|
54
|
+
fontSize: '13px',
|
|
55
|
+
fontWeight: '100',
|
|
56
|
+
textOutline: 'none',
|
|
57
|
+
fontFamily: fontFamily
|
|
58
|
+
},
|
|
59
|
+
connectorColor: '#666',
|
|
60
|
+
connectorWidth: 1,
|
|
61
|
+
overflow: 'allow',
|
|
62
|
+
crop: false
|
|
63
|
+
},
|
|
64
|
+
showInLegend: false
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
series: [{
|
|
68
|
+
type: 'pie',
|
|
69
|
+
name: '',
|
|
70
|
+
colorByPoint: true,
|
|
71
|
+
data: chartData
|
|
72
|
+
}],
|
|
73
|
+
credits: {
|
|
74
|
+
enabled: false
|
|
75
|
+
},
|
|
76
|
+
accessibility: {
|
|
77
|
+
enabled: false
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}, [data, width, height, size, colors]);
|
|
81
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
82
|
+
style: styles.chartWrapper,
|
|
83
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
84
|
+
style: {
|
|
85
|
+
...styles.chartContainer,
|
|
86
|
+
width,
|
|
87
|
+
height,
|
|
88
|
+
position: 'relative'
|
|
89
|
+
},
|
|
90
|
+
children: [noData && /*#__PURE__*/_jsx(CheckerboardBackground, {
|
|
91
|
+
width: width,
|
|
92
|
+
height: height
|
|
93
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
94
|
+
style: {
|
|
95
|
+
position: 'relative',
|
|
96
|
+
zIndex: 1
|
|
97
|
+
},
|
|
98
|
+
children: /*#__PURE__*/_jsx(HighchartsReact, {
|
|
99
|
+
highcharts: Highcharts,
|
|
100
|
+
options: options
|
|
101
|
+
})
|
|
102
|
+
})]
|
|
103
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
104
|
+
style: styles.agentName,
|
|
105
|
+
children: data.name
|
|
106
|
+
})]
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
export default PieChart;
|
|
110
|
+
const fontFamily = 'Pretendard, -apple-system, BlinkMacSystemFont, sans-serif';
|
|
111
|
+
const styles = {
|
|
112
|
+
chartWrapper: {
|
|
113
|
+
background: 'transparent',
|
|
114
|
+
textAlign: 'center',
|
|
115
|
+
display: 'flex',
|
|
116
|
+
flexDirection: 'column',
|
|
117
|
+
justifyContent: 'center',
|
|
118
|
+
alignItems: 'center'
|
|
119
|
+
},
|
|
120
|
+
chartContainer: {
|
|
121
|
+
display: 'flex',
|
|
122
|
+
alignItems: 'center',
|
|
123
|
+
justifyContent: 'center'
|
|
124
|
+
},
|
|
125
|
+
agentName: {
|
|
126
|
+
fontSize: '12px',
|
|
127
|
+
fontWeight: '100',
|
|
128
|
+
marginTop: '-30px',
|
|
129
|
+
color: '#333'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const CheckerboardBackground = ({
|
|
133
|
+
width,
|
|
134
|
+
height
|
|
135
|
+
}) => {
|
|
136
|
+
const circleSize = Math.min(width, height) * 0.47;
|
|
137
|
+
return /*#__PURE__*/_jsx("div", {
|
|
138
|
+
style: {
|
|
139
|
+
position: 'absolute',
|
|
140
|
+
width: circleSize,
|
|
141
|
+
height: circleSize,
|
|
142
|
+
borderRadius: '50%',
|
|
143
|
+
backgroundImage: `
|
|
144
|
+
linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
|
|
145
|
+
linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
|
|
146
|
+
linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
|
|
147
|
+
linear-gradient(-45deg, transparent 75%, #e0e0e0 75%)
|
|
148
|
+
`,
|
|
149
|
+
backgroundSize: '10px 10px',
|
|
150
|
+
backgroundPosition: '0 0, 0 5px, 5px -5px, -5px 0px',
|
|
151
|
+
backgroundColor: '#ffffff',
|
|
152
|
+
zIndex: 0
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
const checkerboardPattern = () => ({
|
|
157
|
+
pattern: {
|
|
158
|
+
path: {
|
|
159
|
+
d: 'M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5',
|
|
160
|
+
stroke: '#d0d0d0',
|
|
161
|
+
strokeWidth: 1
|
|
162
|
+
},
|
|
163
|
+
width: 5,
|
|
164
|
+
height: 5,
|
|
165
|
+
backgroundColor: '#ffffff',
|
|
166
|
+
opacity: 1
|
|
167
|
+
}
|
|
168
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import TrendChart from "./TrendChart";
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
export default function StackedAreaTrendChart({
|
|
5
|
+
metrics,
|
|
6
|
+
records,
|
|
7
|
+
isDaily = false,
|
|
8
|
+
xPlotIndex,
|
|
9
|
+
xAxisTickInterval,
|
|
10
|
+
yAxisLabelEnabled = false,
|
|
11
|
+
legendLimit = 3,
|
|
12
|
+
colors = defaultColors,
|
|
13
|
+
...props
|
|
14
|
+
}) {
|
|
15
|
+
const _metrics = useMemo(() => {
|
|
16
|
+
return metrics.map(m => ({
|
|
17
|
+
metric: m.id,
|
|
18
|
+
chartType: 'area'
|
|
19
|
+
}));
|
|
20
|
+
}, [metrics]);
|
|
21
|
+
const metas = useMemo(() => {
|
|
22
|
+
const result = {
|
|
23
|
+
time: {
|
|
24
|
+
name: "일시",
|
|
25
|
+
type: "DATE"
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
metrics.forEach(m => {
|
|
29
|
+
result[m.id] = {
|
|
30
|
+
name: m.name,
|
|
31
|
+
type: "NUMBER"
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
return result;
|
|
35
|
+
}, [metrics]);
|
|
36
|
+
return /*#__PURE__*/_jsx(TrendChart, {
|
|
37
|
+
dimension: "time",
|
|
38
|
+
stacking: "normal",
|
|
39
|
+
metrics: _metrics,
|
|
40
|
+
metas: metas,
|
|
41
|
+
records: records,
|
|
42
|
+
isRealtime: xPlotIndex !== undefined,
|
|
43
|
+
isDaily: isDaily,
|
|
44
|
+
xPlotIndex: xPlotIndex,
|
|
45
|
+
xAxisTickInterval: xAxisTickInterval,
|
|
46
|
+
yAxisLabelEnabled: yAxisLabelEnabled,
|
|
47
|
+
legendLimit: legendLimit,
|
|
48
|
+
colors: colors,
|
|
49
|
+
...props
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const defaultColors = [["rgba(54,115,237,0.8)", "#3673ed"], ["rgba(149,77,241,0.8)", "#954df1"], ["#4dc391", "#20b476"], ["#fbba3d", "#faa90c"], ["#f2426d", "#ef1348"]];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import Chart from "./Chart";
|
|
3
|
+
import * as ChartColors from "./ChartColors";
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
export default function TrendChart({
|
|
6
|
+
colorIndex = 0,
|
|
7
|
+
legendColors,
|
|
8
|
+
isDaily,
|
|
9
|
+
isRealtime,
|
|
10
|
+
...props
|
|
11
|
+
}) {
|
|
12
|
+
const colors = useMemo(() => {
|
|
13
|
+
return ChartColors.all[colorIndex % ChartColors.all.length];
|
|
14
|
+
}, [colorIndex]);
|
|
15
|
+
const tooltip = useMemo(() => ({
|
|
16
|
+
dateFormat: isRealtime ? '%H:%M' : '%Y-%m-%d',
|
|
17
|
+
headerTime: !isDaily && !isRealtime,
|
|
18
|
+
outside: props.tooltipOutSide,
|
|
19
|
+
legendColors
|
|
20
|
+
}), [isRealtime, isDaily, props.tooltipOutSide, legendColors]);
|
|
21
|
+
return /*#__PURE__*/_jsx(Chart, {
|
|
22
|
+
type: "areaspline",
|
|
23
|
+
categorize: true,
|
|
24
|
+
xAxisType: "datetime",
|
|
25
|
+
xAxisLabelFormat: isDaily ? '%m-%d' : '%H:%M',
|
|
26
|
+
colors: colors,
|
|
27
|
+
tooltip: tooltip,
|
|
28
|
+
...props
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Stack } from "@mui/material";
|
|
3
|
+
import ChatMessages from './ChatMessages';
|
|
4
|
+
import ChatInput from './ChatInput';
|
|
5
|
+
import useChatApi from './hooks/useChatApi';
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
function AiChat({
|
|
8
|
+
defaultMessages,
|
|
9
|
+
sx
|
|
10
|
+
}) {
|
|
11
|
+
const {
|
|
12
|
+
messages,
|
|
13
|
+
inputValue,
|
|
14
|
+
setInputValue,
|
|
15
|
+
isLoading,
|
|
16
|
+
chatContainerRef,
|
|
17
|
+
sendMessage
|
|
18
|
+
} = useChatApi(defaultMessages);
|
|
19
|
+
return /*#__PURE__*/_jsxs(Stack, {
|
|
20
|
+
sx: {
|
|
21
|
+
...styles.container,
|
|
22
|
+
...sx
|
|
23
|
+
},
|
|
24
|
+
children: [/*#__PURE__*/_jsx(ChatMessages, {
|
|
25
|
+
messages: messages,
|
|
26
|
+
isLoading: isLoading,
|
|
27
|
+
chatContainerRef: chatContainerRef
|
|
28
|
+
}), /*#__PURE__*/_jsx(ChatInput, {
|
|
29
|
+
inputValue: inputValue,
|
|
30
|
+
setInputValue: setInputValue,
|
|
31
|
+
onSend: sendMessage,
|
|
32
|
+
isLoading: isLoading
|
|
33
|
+
})]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export default AiChat;
|
|
37
|
+
const styles = {
|
|
38
|
+
container: {
|
|
39
|
+
width: '100%',
|
|
40
|
+
height: '90vh',
|
|
41
|
+
background: 'white',
|
|
42
|
+
display: 'flex',
|
|
43
|
+
flexDirection: 'column',
|
|
44
|
+
overflow: 'hidden'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, FormControl, IconButton, MenuItem, Select, Stack, TextField } from '@mui/material';
|
|
3
|
+
import { Send as SendIcon } from '@mui/icons-material';
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
const ChatInput = ({
|
|
6
|
+
inputValue,
|
|
7
|
+
setInputValue,
|
|
8
|
+
onSend,
|
|
9
|
+
isLoading
|
|
10
|
+
}) => {
|
|
11
|
+
const [model, setModel] = React.useState('GPT_4_1_MINI');
|
|
12
|
+
const handleKeyPress = e => {
|
|
13
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
onSend();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
19
|
+
sx: styles.container,
|
|
20
|
+
children: /*#__PURE__*/_jsxs(Stack, {
|
|
21
|
+
sx: styles.textArea,
|
|
22
|
+
children: [/*#__PURE__*/_jsx(TextField, {
|
|
23
|
+
fullWidth: true,
|
|
24
|
+
multiline: true,
|
|
25
|
+
placeholder: "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694...",
|
|
26
|
+
value: inputValue,
|
|
27
|
+
onChange: e => setInputValue(e.target.value),
|
|
28
|
+
onKeyUp: handleKeyPress,
|
|
29
|
+
disabled: isLoading,
|
|
30
|
+
variant: "standard",
|
|
31
|
+
slotProps: {
|
|
32
|
+
input: {
|
|
33
|
+
disableUnderline: true,
|
|
34
|
+
sx: styles.textField
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}), /*#__PURE__*/_jsxs(Stack, {
|
|
38
|
+
direction: "row",
|
|
39
|
+
gap: 2,
|
|
40
|
+
justifyContent: "flex-end",
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
children: [/*#__PURE__*/_jsx(FormControl, {
|
|
43
|
+
variant: "standard",
|
|
44
|
+
children: /*#__PURE__*/_jsxs(Select, {
|
|
45
|
+
variant: "standard",
|
|
46
|
+
value: model,
|
|
47
|
+
onChange: e => setModel(e.target.value),
|
|
48
|
+
disableUnderline: true,
|
|
49
|
+
sx: {
|
|
50
|
+
fontSize: '13px'
|
|
51
|
+
},
|
|
52
|
+
children: [/*#__PURE__*/_jsx(MenuItem, {
|
|
53
|
+
value: "GPT_4_1_MINI",
|
|
54
|
+
children: "GPT-4.1 Mini"
|
|
55
|
+
}), /*#__PURE__*/_jsx(MenuItem, {
|
|
56
|
+
value: "CLAUDE_3",
|
|
57
|
+
children: "Claude 3"
|
|
58
|
+
})]
|
|
59
|
+
})
|
|
60
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
61
|
+
onClick: onSend,
|
|
62
|
+
disabled: isLoading || !inputValue.trim(),
|
|
63
|
+
sx: styles.iconButton,
|
|
64
|
+
children: /*#__PURE__*/_jsx(SendIcon, {
|
|
65
|
+
sx: {
|
|
66
|
+
fontSize: 18
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
})]
|
|
70
|
+
})]
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
export default ChatInput;
|
|
75
|
+
const styles = {
|
|
76
|
+
container: {
|
|
77
|
+
background: '#f5f5f5',
|
|
78
|
+
padding: '20px',
|
|
79
|
+
borderTop: '1px solid #e5e7eb'
|
|
80
|
+
},
|
|
81
|
+
textArea: {
|
|
82
|
+
border: '1px solid #dfdfdf',
|
|
83
|
+
background: '#fff',
|
|
84
|
+
borderRadius: '12px',
|
|
85
|
+
padding: '4px 12px',
|
|
86
|
+
transition: 'all 0.2s ease-in-out'
|
|
87
|
+
},
|
|
88
|
+
textField: {
|
|
89
|
+
fontSize: '14px',
|
|
90
|
+
padding: '8px 4px',
|
|
91
|
+
lineHeight: '1.4',
|
|
92
|
+
transition: 'all 0.2s ease-in-out',
|
|
93
|
+
'& textarea': {
|
|
94
|
+
transition: 'height 0.2s ease-in-out !important'
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
iconButton: {
|
|
98
|
+
background: '#000',
|
|
99
|
+
color: 'white',
|
|
100
|
+
width: 30,
|
|
101
|
+
height: 30,
|
|
102
|
+
paddingLeft: '12px',
|
|
103
|
+
transition: 'background-color 0.3s ease',
|
|
104
|
+
'&:hover': {
|
|
105
|
+
background: '#333'
|
|
106
|
+
},
|
|
107
|
+
'&:disabled': {
|
|
108
|
+
background: '#e0e0e0',
|
|
109
|
+
color: '#9e9e9e'
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Box, keyframes } from '@mui/material';
|
|
3
|
+
import MarkdownContent from "./content/MarkdownContent";
|
|
4
|
+
import ToolContent from "./content/ToolContent";
|
|
5
|
+
import { ToolContextProvider } from "./contexts/ToolContext";
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
const slideIn = keyframes`
|
|
8
|
+
from {
|
|
9
|
+
opacity: 0;
|
|
10
|
+
transform: translateY(10px);
|
|
11
|
+
}
|
|
12
|
+
to {
|
|
13
|
+
opacity: 1;
|
|
14
|
+
transform: translateY(0);
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
const ChatMessage = ({
|
|
18
|
+
message
|
|
19
|
+
}) => {
|
|
20
|
+
const textContent = useMemo(() => message.content.filter(c => c.type === 'text'), [message]);
|
|
21
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
22
|
+
sx: message.role === 'user' ? styles.messageUser : styles.messageAssistant,
|
|
23
|
+
children: [/*#__PURE__*/_jsx(ToolContextProvider, {
|
|
24
|
+
message: message,
|
|
25
|
+
children: /*#__PURE__*/_jsx(ToolContent, {})
|
|
26
|
+
}), textContent.map((item, index) => /*#__PURE__*/_jsx(Box, {
|
|
27
|
+
sx: styles.contentItem,
|
|
28
|
+
children: /*#__PURE__*/_jsx(MarkdownContent, {
|
|
29
|
+
content: item.value
|
|
30
|
+
})
|
|
31
|
+
}, index))]
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
export default ChatMessage;
|
|
35
|
+
const styles = {
|
|
36
|
+
messageUser: {
|
|
37
|
+
maxWidth: '75%',
|
|
38
|
+
padding: '5px 10px',
|
|
39
|
+
borderRadius: '12px',
|
|
40
|
+
wordWrap: 'break-word',
|
|
41
|
+
fontSize: '13px',
|
|
42
|
+
animation: `${slideIn} 0.3s ease`,
|
|
43
|
+
color: '#333',
|
|
44
|
+
background: '#ecedee',
|
|
45
|
+
alignSelf: 'flex-end',
|
|
46
|
+
marginLeft: 'auto',
|
|
47
|
+
'& .content-tool': {
|
|
48
|
+
background: 'rgba(255, 255, 255, 0.2)',
|
|
49
|
+
borderLeftColor: 'rgba(255, 255, 255, 0.5)'
|
|
50
|
+
},
|
|
51
|
+
'& .tool-header': {
|
|
52
|
+
color: 'rgba(255, 255, 255, 0.95)'
|
|
53
|
+
},
|
|
54
|
+
'& .tool-result': {
|
|
55
|
+
background: 'rgba(255, 255, 255, 0.15)',
|
|
56
|
+
color: 'rgba(255, 255, 255, 0.9)'
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
messageAssistant: {
|
|
60
|
+
width: '100%',
|
|
61
|
+
maxWidth: '100%',
|
|
62
|
+
padding: '1rem 1.25rem',
|
|
63
|
+
borderRadius: '1.25rem',
|
|
64
|
+
wordWrap: 'break-word',
|
|
65
|
+
fontSize: '13px',
|
|
66
|
+
animation: `${slideIn} 0.3s ease`,
|
|
67
|
+
color: '#333',
|
|
68
|
+
alignSelf: 'flex-start'
|
|
69
|
+
},
|
|
70
|
+
contentItem: {
|
|
71
|
+
marginBottom: '0.5rem',
|
|
72
|
+
'&:last-child': {
|
|
73
|
+
marginBottom: 0
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import ChatMessage from './ChatMessage';
|
|
3
|
+
import LoadingIndicator from './LoadingIndicator';
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
const ChatMessages = ({
|
|
6
|
+
messages,
|
|
7
|
+
isLoading,
|
|
8
|
+
chatContainerRef
|
|
9
|
+
}) => {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (messages.length === 0) return;
|
|
12
|
+
const message = messages[messages.length - 1];
|
|
13
|
+
if (message.role === 'assistant') console.log(message);
|
|
14
|
+
}, [messages.length]);
|
|
15
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
16
|
+
style: styles.container,
|
|
17
|
+
ref: chatContainerRef,
|
|
18
|
+
children: [messages.map((message, index) => /*#__PURE__*/_jsx(ChatMessage, {
|
|
19
|
+
message: message
|
|
20
|
+
}, index)), isLoading && /*#__PURE__*/_jsx(LoadingIndicator, {})]
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
export default ChatMessages;
|
|
24
|
+
const styles = {
|
|
25
|
+
container: {
|
|
26
|
+
flex: 1,
|
|
27
|
+
overflowY: 'auto',
|
|
28
|
+
padding: '1.5rem',
|
|
29
|
+
display: 'flex',
|
|
30
|
+
flexDirection: 'column',
|
|
31
|
+
gap: '1rem',
|
|
32
|
+
background: '#fcfcfd'
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, keyframes } from '@mui/material';
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
const bounce = keyframes`
|
|
5
|
+
0%, 60%, 100% {
|
|
6
|
+
transform: translateY(0);
|
|
7
|
+
}
|
|
8
|
+
30% {
|
|
9
|
+
transform: translateY(-10px);
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
const LoadingIndicator = () => {
|
|
13
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
14
|
+
sx: styles.typing,
|
|
15
|
+
children: [/*#__PURE__*/_jsx(Box, {
|
|
16
|
+
component: "span",
|
|
17
|
+
sx: styles.dot
|
|
18
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
19
|
+
component: "span",
|
|
20
|
+
sx: {
|
|
21
|
+
...styles.dot,
|
|
22
|
+
animationDelay: '0.2s'
|
|
23
|
+
}
|
|
24
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
25
|
+
component: "span",
|
|
26
|
+
sx: {
|
|
27
|
+
...styles.dot,
|
|
28
|
+
animationDelay: '0.4s'
|
|
29
|
+
}
|
|
30
|
+
})]
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
export default LoadingIndicator;
|
|
34
|
+
const styles = {
|
|
35
|
+
typing: {
|
|
36
|
+
display: 'inline-block',
|
|
37
|
+
padding: '1rem 1.25rem'
|
|
38
|
+
},
|
|
39
|
+
dot: {
|
|
40
|
+
display: 'inline-block',
|
|
41
|
+
width: '6px',
|
|
42
|
+
height: '6px',
|
|
43
|
+
borderRadius: '50%',
|
|
44
|
+
background: '#666',
|
|
45
|
+
margin: '0 2px',
|
|
46
|
+
animation: `${bounce} 1.4s infinite`
|
|
47
|
+
}
|
|
48
|
+
};
|