@carto/ps-react-ui 4.9.1 → 4.11.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/category-Dnd2_j0x.js +719 -0
- package/dist/category-Dnd2_j0x.js.map +1 -0
- package/dist/change-column-DjjwoPt1.js +1143 -0
- package/dist/change-column-DjjwoPt1.js.map +1 -0
- package/dist/chat.js +1507 -0
- package/dist/chat.js.map +1 -0
- package/dist/components.js +122 -120
- package/dist/components.js.map +1 -1
- package/dist/copy-button-DGL1tyli.js +26 -0
- package/dist/copy-button-DGL1tyli.js.map +1 -0
- package/dist/{data-zoom-layout-0QSptXG_.js → data-zoom-layout-CkVnm6ej.js} +3 -3
- package/dist/{data-zoom-layout-0QSptXG_.js.map → data-zoom-layout-CkVnm6ej.js.map} +1 -1
- package/dist/{download-config-CzmjOT2T.js → download-config-oJIFZ2WC.js} +9 -8
- package/dist/{download-config-CzmjOT2T.js.map → download-config-oJIFZ2WC.js.map} +1 -1
- package/dist/{png-item-CS4z1iSH.js → png-item-BE9uEqlD.js} +2 -2
- package/dist/png-item-BE9uEqlD.js.map +1 -0
- package/dist/{spread-Y9R1f5dm.js → spread-DYNpzgh_.js} +10 -11
- package/dist/{spread-Y9R1f5dm.js.map → spread-DYNpzgh_.js.map} +1 -1
- package/dist/{table-CQCAnDLb.js → table-C9IMbTr0.js} +50 -53
- package/dist/table-C9IMbTr0.js.map +1 -0
- package/dist/types/chat/bubbles/chat-error-message.d.ts +2 -0
- package/dist/types/chat/bubbles/chat-suggestion-button.d.ts +2 -0
- package/dist/types/chat/bubbles/chat-user-message.d.ts +2 -0
- package/dist/types/chat/bubbles/index.d.ts +4 -0
- package/dist/types/chat/const.d.ts +4 -0
- package/dist/types/chat/containers/chat-content.d.ts +2 -0
- package/dist/types/chat/containers/chat-footer.d.ts +2 -0
- package/dist/types/chat/containers/chat-header.d.ts +2 -0
- package/dist/types/chat/containers/chat-starter.d.ts +2 -0
- package/dist/types/chat/containers/index.d.ts +4 -0
- package/dist/types/chat/containers/styles.d.ts +93 -0
- package/dist/types/chat/feedback/chat-loader.d.ts +2 -0
- package/dist/types/chat/feedback/chat-rating-action.d.ts +2 -0
- package/dist/types/chat/feedback/chat-thinking.d.ts +2 -0
- package/dist/types/chat/feedback/chat-tool-code-area.d.ts +2 -0
- package/dist/types/chat/feedback/chat-tool-full-view-dialog.d.ts +2 -0
- package/dist/types/chat/feedback/chat-tool-group.d.ts +2 -0
- package/dist/types/chat/feedback/chat-tool-trace.d.ts +3 -0
- package/dist/types/chat/feedback/get-tool-label.d.ts +2 -0
- package/dist/types/chat/feedback/index.d.ts +8 -0
- package/dist/types/chat/feedback/styles.d.ts +211 -0
- package/dist/types/chat/index.d.ts +20 -0
- package/dist/types/chat/types.d.ts +184 -0
- package/dist/types/chat/use-typewriter.d.ts +30 -0
- package/dist/types/components/copy-button/copy-button.d.ts +2 -0
- package/dist/types/components/copy-button/types.d.ts +6 -0
- package/dist/types/components/index.d.ts +2 -0
- package/dist/types/widgets/actions/brush-toggle/style.d.ts +1 -1
- package/dist/types/widgets/actions/shared/styles.d.ts +1 -1
- package/dist/types/widgets/actions/zoom-toggle/style.d.ts +1 -1
- package/dist/types/widgets/echart/types.d.ts +1 -1
- package/dist/types/widgets/toolbar-actions/styles.d.ts +1 -1
- package/dist/types/widgets-v2/actions/brush-toggle/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/change-column/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/fullscreen/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/index.d.ts +1 -0
- package/dist/types/widgets-v2/actions/lock-selection/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/relative-data/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/searcher/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/show-all/index.d.ts +2 -0
- package/dist/types/widgets-v2/actions/show-all/labels.d.ts +5 -0
- package/dist/types/widgets-v2/actions/show-all/show-all.d.ts +33 -0
- package/dist/types/widgets-v2/actions/show-all/style.d.ts +8 -0
- package/dist/types/widgets-v2/actions/stack-toggle/style.d.ts +1 -1
- package/dist/types/widgets-v2/actions/zoom-toggle/style.d.ts +1 -1
- package/dist/types/widgets-v2/category/category-ui.d.ts +9 -2
- package/dist/types/widgets-v2/category/category.d.ts +9 -2
- package/dist/types/widgets-v2/category/components/category-row-other.d.ts +19 -6
- package/dist/types/widgets-v2/category/style.d.ts +21 -2
- package/dist/types/widgets-v2/category/types.d.ts +2 -0
- package/dist/types/widgets-v2/index.d.ts +3 -2
- package/dist/types/widgets-v2/selection-summary/labels.d.ts +7 -2
- package/dist/types/widgets-v2/selection-summary/selection-summary.d.ts +13 -6
- package/dist/types/widgets-v2/selection-summary/style.d.ts +15 -0
- package/dist/widgets/actions.js +115 -114
- package/dist/widgets/actions.js.map +1 -1
- package/dist/widgets/bar.js +1 -1
- package/dist/widgets/category.js +9 -8
- package/dist/widgets/category.js.map +1 -1
- package/dist/widgets/formula.js +11 -10
- package/dist/widgets/formula.js.map +1 -1
- package/dist/widgets/histogram.js +7 -6
- package/dist/widgets/histogram.js.map +1 -1
- package/dist/widgets/markdown.js +9 -8
- package/dist/widgets/markdown.js.map +1 -1
- package/dist/widgets/pie.js +1 -1
- package/dist/widgets/scatterplot.js +1 -1
- package/dist/widgets/spread.js +9 -8
- package/dist/widgets/spread.js.map +1 -1
- package/dist/widgets/table.js +17 -16
- package/dist/widgets/table.js.map +1 -1
- package/dist/widgets/timeseries.js +1 -1
- package/dist/widgets/utils.js +1 -1
- package/dist/widgets/wrapper.js +3 -2
- package/dist/widgets/wrapper.js.map +1 -1
- package/dist/widgets-v2/actions.js +41 -37
- package/dist/widgets-v2/bar.js +9 -10
- package/dist/widgets-v2/bar.js.map +1 -1
- package/dist/widgets-v2/category.js +25 -26
- package/dist/widgets-v2/category.js.map +1 -1
- package/dist/widgets-v2/formula.js +3 -3
- package/dist/widgets-v2/histogram.js +11 -13
- package/dist/widgets-v2/histogram.js.map +1 -1
- package/dist/widgets-v2/markdown.js +26 -27
- package/dist/widgets-v2/markdown.js.map +1 -1
- package/dist/widgets-v2/pie.js +8 -10
- package/dist/widgets-v2/pie.js.map +1 -1
- package/dist/widgets-v2/scatterplot.js +10 -12
- package/dist/widgets-v2/scatterplot.js.map +1 -1
- package/dist/widgets-v2/spread.js +15 -16
- package/dist/widgets-v2/spread.js.map +1 -1
- package/dist/widgets-v2/table.js +39 -40
- package/dist/widgets-v2/table.js.map +1 -1
- package/dist/widgets-v2/timeseries.js +9 -11
- package/dist/widgets-v2/timeseries.js.map +1 -1
- package/dist/widgets-v2/utils.js +1 -1
- package/dist/widgets-v2.js +284 -282
- package/dist/widgets-v2.js.map +1 -1
- package/package.json +5 -1
- package/src/chat/bubbles/chat-agent-message.test.tsx +30 -0
- package/src/chat/bubbles/chat-agent-message.tsx +11 -0
- package/src/chat/bubbles/chat-error-message.test.tsx +40 -0
- package/src/chat/bubbles/chat-error-message.tsx +47 -0
- package/src/chat/bubbles/chat-suggestion-button.test.tsx +24 -0
- package/src/chat/bubbles/chat-suggestion-button.tsx +27 -0
- package/src/chat/bubbles/chat-user-message.test.tsx +27 -0
- package/src/chat/bubbles/chat-user-message.tsx +27 -0
- package/src/chat/bubbles/index.ts +4 -0
- package/src/chat/bubbles/styles.ts +148 -0
- package/src/chat/const.ts +4 -0
- package/src/chat/containers/chat-content.test.tsx +269 -0
- package/src/chat/containers/chat-content.tsx +142 -0
- package/src/chat/containers/chat-footer.test.tsx +34 -0
- package/src/chat/containers/chat-footer.tsx +78 -0
- package/src/chat/containers/chat-header.test.tsx +28 -0
- package/src/chat/containers/chat-header.tsx +29 -0
- package/src/chat/containers/chat-starter.test.tsx +32 -0
- package/src/chat/containers/chat-starter.tsx +75 -0
- package/src/chat/containers/index.ts +4 -0
- package/src/chat/containers/styles.ts +96 -0
- package/src/chat/feedback/chat-actions-container.test.tsx +64 -0
- package/src/chat/feedback/chat-actions-container.tsx +7 -0
- package/src/chat/feedback/chat-loader.test.tsx +10 -0
- package/src/chat/feedback/chat-loader.tsx +31 -0
- package/src/chat/feedback/chat-rating-action.tsx +43 -0
- package/src/chat/feedback/chat-thinking.test.tsx +15 -0
- package/src/chat/feedback/chat-thinking.tsx +23 -0
- package/src/chat/feedback/chat-tool-code-area.test.tsx +23 -0
- package/src/chat/feedback/chat-tool-code-area.tsx +71 -0
- package/src/chat/feedback/chat-tool-full-view-dialog.test.tsx +39 -0
- package/src/chat/feedback/chat-tool-full-view-dialog.tsx +121 -0
- package/src/chat/feedback/chat-tool-group.test.tsx +84 -0
- package/src/chat/feedback/chat-tool-group.tsx +156 -0
- package/src/chat/feedback/chat-tool-trace.test.tsx +81 -0
- package/src/chat/feedback/chat-tool-trace.tsx +192 -0
- package/src/chat/feedback/get-tool-label.test.tsx +91 -0
- package/src/chat/feedback/get-tool-label.ts +13 -0
- package/src/chat/feedback/index.ts +8 -0
- package/src/chat/feedback/styles.ts +229 -0
- package/src/chat/index.ts +59 -0
- package/src/chat/types.ts +215 -0
- package/src/chat/use-typewriter.test.tsx +38 -0
- package/src/chat/use-typewriter.ts +82 -0
- package/src/components/copy-button/copy-button.test.tsx +41 -0
- package/src/components/copy-button/copy-button.tsx +31 -0
- package/src/components/copy-button/types.ts +10 -0
- package/src/components/index.ts +3 -0
- package/src/widgets/echart/types.ts +1 -1
- package/src/widgets-v2/actions/brush-toggle/brush-toggle.tsx +1 -1
- package/src/widgets-v2/actions/change-column/sortable-column-item.tsx +1 -1
- package/src/widgets-v2/actions/download/download.tsx +1 -1
- package/src/widgets-v2/actions/download/icons.tsx +1 -1
- package/src/widgets-v2/actions/fullscreen/fullscreen.tsx +3 -3
- package/src/widgets-v2/actions/index.ts +8 -0
- package/src/widgets-v2/actions/lock-selection/lock-selection.tsx +2 -2
- package/src/widgets-v2/actions/relative-data/relative-data.tsx +1 -1
- package/src/widgets-v2/actions/searcher/searcher-toggle.tsx +1 -1
- package/src/widgets-v2/actions/searcher/searcher.tsx +2 -2
- package/src/widgets-v2/actions/show-all/index.ts +7 -0
- package/src/widgets-v2/actions/show-all/labels.ts +8 -0
- package/src/widgets-v2/actions/show-all/show-all.test.tsx +50 -0
- package/src/widgets-v2/actions/show-all/show-all.tsx +72 -0
- package/src/widgets-v2/actions/show-all/style.ts +8 -0
- package/src/widgets-v2/actions/stack-toggle/stack-toggle.tsx +1 -1
- package/src/widgets-v2/actions/zoom-toggle/zoom-toggle.tsx +1 -1
- package/src/widgets-v2/category/category-ui.test.tsx +26 -10
- package/src/widgets-v2/category/category-ui.tsx +13 -3
- package/src/widgets-v2/category/category.test.tsx +4 -4
- package/src/widgets-v2/category/category.tsx +10 -1
- package/src/widgets-v2/category/components/category-row-other.test.tsx +36 -7
- package/src/widgets-v2/category/components/category-row-other.tsx +64 -13
- package/src/widgets-v2/category/style.ts +35 -4
- package/src/widgets-v2/category/types.ts +2 -0
- package/src/widgets-v2/index.ts +3 -0
- package/src/widgets-v2/selection-summary/labels.ts +8 -4
- package/src/widgets-v2/selection-summary/selection-summary.test.tsx +15 -9
- package/src/widgets-v2/selection-summary/selection-summary.tsx +42 -22
- package/src/widgets-v2/selection-summary/style.ts +15 -0
- package/src/widgets-v2/table/table-ui.tsx +4 -4
- package/src/widgets-v2/toolbox/toolbox.tsx +1 -1
- package/src/widgets-v2/wrapper/widget-wrapper.tsx +1 -1
- package/dist/category-DwaeYjpX.js +0 -656
- package/dist/category-DwaeYjpX.js.map +0 -1
- package/dist/change-column-B4IT0rh6.js +0 -1110
- package/dist/change-column-B4IT0rh6.js.map +0 -1
- package/dist/png-item-CS4z1iSH.js.map +0 -1
- package/dist/table-CQCAnDLb.js.map +0 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest'
|
|
2
|
+
import { getToolLabel } from './get-tool-label'
|
|
3
|
+
import type { ChatToolItem } from '../types'
|
|
4
|
+
|
|
5
|
+
describe('getToolLabel', () => {
|
|
6
|
+
test('uses runningLabel when status is running', () => {
|
|
7
|
+
const tool: ChatToolItem = {
|
|
8
|
+
id: '1',
|
|
9
|
+
name: 'execute_sql',
|
|
10
|
+
status: 'running',
|
|
11
|
+
runningLabel: 'Running query',
|
|
12
|
+
}
|
|
13
|
+
expect(getToolLabel(tool)).toBe('Running query')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('falls back to capitalized name when running without runningLabel', () => {
|
|
17
|
+
const tool: ChatToolItem = {
|
|
18
|
+
id: '1',
|
|
19
|
+
name: 'execute_sql',
|
|
20
|
+
status: 'running',
|
|
21
|
+
}
|
|
22
|
+
expect(getToolLabel(tool)).toBe('Execute sql')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('uses label for completed status', () => {
|
|
26
|
+
const tool: ChatToolItem = {
|
|
27
|
+
id: '1',
|
|
28
|
+
name: 'execute_sql',
|
|
29
|
+
status: 'complete',
|
|
30
|
+
label: 'Database query',
|
|
31
|
+
}
|
|
32
|
+
expect(getToolLabel(tool)).toBe('Database query')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('uses label for error status', () => {
|
|
36
|
+
const tool: ChatToolItem = {
|
|
37
|
+
id: '1',
|
|
38
|
+
name: 'execute_sql',
|
|
39
|
+
status: 'error',
|
|
40
|
+
label: 'Database query',
|
|
41
|
+
}
|
|
42
|
+
expect(getToolLabel(tool)).toBe('Database query')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('falls back to capitalized name for non-running without label', () => {
|
|
46
|
+
const tool: ChatToolItem = {
|
|
47
|
+
id: '1',
|
|
48
|
+
name: 'add_marker',
|
|
49
|
+
status: 'complete',
|
|
50
|
+
}
|
|
51
|
+
expect(getToolLabel(tool)).toBe('Add marker')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('replaces underscores with spaces and capitalizes first letter', () => {
|
|
55
|
+
const tool: ChatToolItem = {
|
|
56
|
+
id: '1',
|
|
57
|
+
name: 'geocode_address_v2',
|
|
58
|
+
status: 'complete',
|
|
59
|
+
}
|
|
60
|
+
expect(getToolLabel(tool)).toBe('Geocode address v2')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('preserves names that are already formatted', () => {
|
|
64
|
+
const tool: ChatToolItem = {
|
|
65
|
+
id: '1',
|
|
66
|
+
name: 'Tool #1',
|
|
67
|
+
status: 'complete',
|
|
68
|
+
}
|
|
69
|
+
expect(getToolLabel(tool)).toBe('Tool #1')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('runningLabel does not leak into non-running statuses', () => {
|
|
73
|
+
const tool: ChatToolItem = {
|
|
74
|
+
id: '1',
|
|
75
|
+
name: 'execute_sql',
|
|
76
|
+
status: 'complete',
|
|
77
|
+
runningLabel: 'Running query',
|
|
78
|
+
}
|
|
79
|
+
expect(getToolLabel(tool)).toBe('Execute sql')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('label does not leak into running status', () => {
|
|
83
|
+
const tool: ChatToolItem = {
|
|
84
|
+
id: '1',
|
|
85
|
+
name: 'execute_sql',
|
|
86
|
+
status: 'running',
|
|
87
|
+
label: 'Database query',
|
|
88
|
+
}
|
|
89
|
+
expect(getToolLabel(tool)).toBe('Execute sql')
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChatToolItem } from '../types'
|
|
2
|
+
|
|
3
|
+
function capitalize(str: string): string {
|
|
4
|
+
const spaced = str.replace(/_/g, ' ')
|
|
5
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getToolLabel(tool: ChatToolItem): string {
|
|
9
|
+
if (tool.status === 'running') {
|
|
10
|
+
return tool.runningLabel ?? capitalize(tool.name)
|
|
11
|
+
}
|
|
12
|
+
return tool.label ?? capitalize(tool.name)
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ChatThinking } from './chat-thinking'
|
|
2
|
+
export { ChatLoader } from './chat-loader'
|
|
3
|
+
export { ChatActionsContainer } from './chat-actions-container'
|
|
4
|
+
export { ChatRatingAction } from './chat-rating-action'
|
|
5
|
+
export { ChatToolTrace } from './chat-tool-trace'
|
|
6
|
+
export { ChatToolCodeArea } from './chat-tool-code-area'
|
|
7
|
+
export { ChatToolFullViewDialog } from './chat-tool-full-view-dialog'
|
|
8
|
+
export { ChatToolGroup } from './chat-tool-group'
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { type SxProps, type Theme } from '@mui/material'
|
|
2
|
+
import { keyframes } from '@mui/material/styles'
|
|
3
|
+
|
|
4
|
+
const shimmer = keyframes`
|
|
5
|
+
0% {
|
|
6
|
+
background-position: 150% 0;
|
|
7
|
+
}
|
|
8
|
+
100% {
|
|
9
|
+
background-position: -50% 0;
|
|
10
|
+
}
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
const breatheOuter = keyframes`
|
|
14
|
+
0% { transform: scale(0.68); opacity: 0.7; }
|
|
15
|
+
40% { transform: scale(1); opacity: 1; }
|
|
16
|
+
80% { transform: scale(0.6); opacity: 0.65; }
|
|
17
|
+
100% { transform: scale(0.68); opacity: 0.7; }
|
|
18
|
+
`
|
|
19
|
+
|
|
20
|
+
const breatheInner = keyframes`
|
|
21
|
+
0% { transform: scale(1); }
|
|
22
|
+
40% { transform: scale(0.75); }
|
|
23
|
+
80% { transform: scale(1.125); }
|
|
24
|
+
100% { transform: scale(1); }
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
export const styles = {
|
|
28
|
+
thinking: {
|
|
29
|
+
display: 'flex',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
minHeight: ({ spacing }) => spacing(3),
|
|
32
|
+
background: ({ palette }) => `linear-gradient(
|
|
33
|
+
90deg,
|
|
34
|
+
${palette.text.disabled} 25%,
|
|
35
|
+
${palette.text.secondary} 50%,
|
|
36
|
+
${palette.text.disabled} 75%
|
|
37
|
+
)`,
|
|
38
|
+
backgroundSize: '200% 100%',
|
|
39
|
+
backgroundClip: 'text',
|
|
40
|
+
WebkitBackgroundClip: 'text',
|
|
41
|
+
WebkitTextFillColor: 'transparent',
|
|
42
|
+
animation: `${shimmer} 2s ease-in-out infinite`,
|
|
43
|
+
animationDuration: '2s',
|
|
44
|
+
},
|
|
45
|
+
loader: {
|
|
46
|
+
display: 'flex',
|
|
47
|
+
alignItems: 'center',
|
|
48
|
+
justifyContent: 'center',
|
|
49
|
+
position: 'relative',
|
|
50
|
+
p: 1,
|
|
51
|
+
},
|
|
52
|
+
loaderOuterCircle: {
|
|
53
|
+
position: 'absolute',
|
|
54
|
+
inset: 0,
|
|
55
|
+
margin: 'auto',
|
|
56
|
+
borderRadius: '50%',
|
|
57
|
+
backgroundColor: ({ palette }) => palette.action.disabled,
|
|
58
|
+
animation: `${breatheOuter} 1s ease-in-out infinite`,
|
|
59
|
+
},
|
|
60
|
+
loaderInnerCircle: {
|
|
61
|
+
position: 'absolute',
|
|
62
|
+
inset: 0,
|
|
63
|
+
margin: 'auto',
|
|
64
|
+
borderRadius: '50%',
|
|
65
|
+
backgroundColor: ({ palette }) => palette.text.primary,
|
|
66
|
+
animation: `${breatheInner} 1s ease-in-out infinite`,
|
|
67
|
+
},
|
|
68
|
+
// --- Tool Trace styles ---
|
|
69
|
+
traceHeader: {
|
|
70
|
+
display: 'flex',
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
padding: 0,
|
|
73
|
+
paddingLeft: ({ spacing }) => spacing(0.5),
|
|
74
|
+
borderRadius: ({ spacing }) => spacing(0.5),
|
|
75
|
+
width: 'fit-content',
|
|
76
|
+
color: ({ palette }) => palette.text.secondary,
|
|
77
|
+
'&:hover': {
|
|
78
|
+
backgroundColor: ({ palette }) => palette.action.hover,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
traceChevron: {
|
|
82
|
+
color: ({ palette }) => palette.text.secondary,
|
|
83
|
+
transition: 'transform 0.2s',
|
|
84
|
+
},
|
|
85
|
+
traceDetailsWrapper: {
|
|
86
|
+
marginTop: ({ spacing }) => spacing(0.5),
|
|
87
|
+
padding: ({ spacing }) => spacing(1.5),
|
|
88
|
+
border: '1px solid',
|
|
89
|
+
borderColor: 'divider',
|
|
90
|
+
borderRadius: ({ spacing }) => spacing(1),
|
|
91
|
+
},
|
|
92
|
+
traceField: {
|
|
93
|
+
display: 'flex',
|
|
94
|
+
alignItems: 'flex-start',
|
|
95
|
+
gap: ({ spacing }) => spacing(1),
|
|
96
|
+
},
|
|
97
|
+
traceFieldLabel: {
|
|
98
|
+
flexShrink: 0,
|
|
99
|
+
},
|
|
100
|
+
traceReference: {
|
|
101
|
+
display: 'flex',
|
|
102
|
+
borderRadius: ({ spacing }) => spacing(0.25),
|
|
103
|
+
padding: ({ spacing }) => spacing(0, 0.5),
|
|
104
|
+
gap: ({ spacing }) => spacing(0.5),
|
|
105
|
+
backgroundColor: ({ palette }) => palette.success.relatedLight,
|
|
106
|
+
color: ({ palette }) => palette.success.dark,
|
|
107
|
+
},
|
|
108
|
+
traceStatusSuccess: {
|
|
109
|
+
color: ({ palette }) => palette.success.main,
|
|
110
|
+
},
|
|
111
|
+
traceStatusError: {
|
|
112
|
+
color: ({ palette }) => palette.error.main,
|
|
113
|
+
},
|
|
114
|
+
// --- Code Area styles ---
|
|
115
|
+
codeArea: {
|
|
116
|
+
position: 'relative',
|
|
117
|
+
width: '100%',
|
|
118
|
+
},
|
|
119
|
+
codeAreaPre: {
|
|
120
|
+
margin: 0,
|
|
121
|
+
padding: ({ spacing }) => spacing(1),
|
|
122
|
+
borderRadius: ({ spacing }) => spacing(0.5),
|
|
123
|
+
backgroundColor: ({ palette }) => palette.background.default,
|
|
124
|
+
fontSize: '0.75rem',
|
|
125
|
+
fontFamily: 'monospace',
|
|
126
|
+
whiteSpace: 'pre-wrap',
|
|
127
|
+
wordBreak: 'break-word',
|
|
128
|
+
overflowY: 'auto',
|
|
129
|
+
},
|
|
130
|
+
codeAreaPreError: {
|
|
131
|
+
borderLeft: ({ palette }) => `3px solid ${palette.error.main}`,
|
|
132
|
+
backgroundColor: ({ palette }) => `${palette.error.main}08`,
|
|
133
|
+
},
|
|
134
|
+
codeAreaFullViewButton: {
|
|
135
|
+
position: 'absolute',
|
|
136
|
+
top: ({ spacing }) => spacing(0.5),
|
|
137
|
+
right: ({ spacing }) => spacing(0.5),
|
|
138
|
+
},
|
|
139
|
+
// --- Full View Dialog styles ---
|
|
140
|
+
fullViewDialog: {
|
|
141
|
+
margin: ({ spacing }) => spacing(5),
|
|
142
|
+
},
|
|
143
|
+
fullViewPaper: {
|
|
144
|
+
borderRadius: 1,
|
|
145
|
+
},
|
|
146
|
+
fullViewTitle: {
|
|
147
|
+
display: 'flex',
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
justifyContent: 'space-between',
|
|
150
|
+
padding: ({ spacing }) => spacing(2),
|
|
151
|
+
borderBottom: '1px solid',
|
|
152
|
+
borderBottomColor: 'divider',
|
|
153
|
+
},
|
|
154
|
+
fullViewDialogContent: {
|
|
155
|
+
padding: 0,
|
|
156
|
+
'&:first-of-type': { paddingTop: 0 },
|
|
157
|
+
},
|
|
158
|
+
fullViewPre: {
|
|
159
|
+
margin: 0,
|
|
160
|
+
padding: ({ spacing }) => spacing(1),
|
|
161
|
+
background: ({ palette, spacing }) =>
|
|
162
|
+
`linear-gradient(to right, ${palette.action.hover} calc(${spacing(1)} + 3em), ${palette.background.default} calc(${spacing(1)} + 3em))`,
|
|
163
|
+
fontFamily: 'monospace',
|
|
164
|
+
fontSize: '0.8125rem',
|
|
165
|
+
whiteSpace: 'pre-wrap',
|
|
166
|
+
wordBreak: 'break-word',
|
|
167
|
+
lineHeight: 1.6,
|
|
168
|
+
counterReset: 'line',
|
|
169
|
+
},
|
|
170
|
+
fullViewLine: {
|
|
171
|
+
display: 'block',
|
|
172
|
+
'&::before': {
|
|
173
|
+
counterIncrement: 'line',
|
|
174
|
+
content: 'counter(line)',
|
|
175
|
+
display: 'inline-block',
|
|
176
|
+
width: '2em',
|
|
177
|
+
marginRight: '2em',
|
|
178
|
+
textAlign: 'right',
|
|
179
|
+
color: ({ palette }) => palette.text.secondary,
|
|
180
|
+
userSelect: 'none',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
groupHeader: {
|
|
184
|
+
textAlign: 'left',
|
|
185
|
+
display: 'flex',
|
|
186
|
+
alignItems: 'center',
|
|
187
|
+
borderRadius: 0,
|
|
188
|
+
gap: ({ spacing }) => spacing(0.5),
|
|
189
|
+
},
|
|
190
|
+
errorBadge: {
|
|
191
|
+
color: ({ palette }) => palette.error.main,
|
|
192
|
+
fontWeight: 600,
|
|
193
|
+
display: 'flex',
|
|
194
|
+
alignItems: 'center',
|
|
195
|
+
gap: ({ spacing }) => spacing(0.25),
|
|
196
|
+
},
|
|
197
|
+
// --- Syntax highlighting token styles ---
|
|
198
|
+
syntaxToken_key: {
|
|
199
|
+
color: '#881280',
|
|
200
|
+
},
|
|
201
|
+
syntaxToken_string: {
|
|
202
|
+
color: '#c41a16',
|
|
203
|
+
},
|
|
204
|
+
syntaxToken_number: {
|
|
205
|
+
color: '#1c00cf',
|
|
206
|
+
},
|
|
207
|
+
syntaxToken_boolean: {
|
|
208
|
+
color: '#1c00cf',
|
|
209
|
+
},
|
|
210
|
+
syntaxToken_null: {
|
|
211
|
+
color: '#808080',
|
|
212
|
+
},
|
|
213
|
+
syntaxToken_punctuation: {
|
|
214
|
+
color: ({ palette }) => palette.text.primary,
|
|
215
|
+
},
|
|
216
|
+
groupListItem: {
|
|
217
|
+
borderBottom: '1px solid',
|
|
218
|
+
borderColor: 'divider',
|
|
219
|
+
'&:first-of-type .MuiButton-root': {
|
|
220
|
+
borderRadius: ({ spacing }) => spacing(1, 1, 0, 0),
|
|
221
|
+
},
|
|
222
|
+
'&:last-of-type:not([aria-expanded=true]) .MuiButton-root': {
|
|
223
|
+
borderRadius: ({ spacing }) => spacing(0, 0, 1, 1),
|
|
224
|
+
},
|
|
225
|
+
'&:last-of-type': {
|
|
226
|
+
borderBottomWidth: 0,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
} satisfies Record<string, SxProps<Theme>>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Types
|
|
2
|
+
export type {
|
|
3
|
+
ChatSxProps,
|
|
4
|
+
ChatErrorAction,
|
|
5
|
+
ChatUserMessageProps,
|
|
6
|
+
ChatAgentMessageProps,
|
|
7
|
+
ChatErrorMessageProps,
|
|
8
|
+
ChatSuggestionButtonProps,
|
|
9
|
+
ChatThinkingProps,
|
|
10
|
+
ChatLoaderProps,
|
|
11
|
+
ChatContentProps,
|
|
12
|
+
ChatContentRef,
|
|
13
|
+
ChatHeaderProps,
|
|
14
|
+
ChatFooterProps,
|
|
15
|
+
ChatStarterItem,
|
|
16
|
+
ChatStarterProps,
|
|
17
|
+
ChatRatingActionProps,
|
|
18
|
+
ChatToolItem,
|
|
19
|
+
ChatToolTraceProps,
|
|
20
|
+
ChatToolCodeAreaProps,
|
|
21
|
+
ChatToolFullViewDialogProps,
|
|
22
|
+
ChatToolGroupProps,
|
|
23
|
+
} from './types'
|
|
24
|
+
|
|
25
|
+
// Constants
|
|
26
|
+
export {
|
|
27
|
+
CHAT_MAX_WIDTH,
|
|
28
|
+
CHAT_SCROLL_DELAY,
|
|
29
|
+
CHAT_DIVIDER_DELAY,
|
|
30
|
+
CHAT_TOOL_CODE_AREA_MAX_HEIGHT,
|
|
31
|
+
} from './const'
|
|
32
|
+
|
|
33
|
+
// Hooks
|
|
34
|
+
export { useTypewriter } from './use-typewriter'
|
|
35
|
+
|
|
36
|
+
// Messages
|
|
37
|
+
export { ChatUserMessage } from './bubbles/chat-user-message'
|
|
38
|
+
export { ChatAgentMessage } from './bubbles/chat-agent-message'
|
|
39
|
+
export { ChatErrorMessage } from './bubbles/chat-error-message'
|
|
40
|
+
export { ChatSuggestionButton } from './bubbles/chat-suggestion-button'
|
|
41
|
+
export { ChatMessageOverflow } from './bubbles/styles'
|
|
42
|
+
|
|
43
|
+
// Feedback
|
|
44
|
+
export { ChatThinking } from './feedback/chat-thinking'
|
|
45
|
+
export { ChatLoader } from './feedback/chat-loader'
|
|
46
|
+
|
|
47
|
+
// Containers
|
|
48
|
+
export { ChatContent } from './containers/chat-content'
|
|
49
|
+
export { ChatHeader } from './containers/chat-header'
|
|
50
|
+
export { ChatFooter } from './containers/chat-footer'
|
|
51
|
+
export { ChatStarter } from './containers/chat-starter'
|
|
52
|
+
|
|
53
|
+
// Feedback
|
|
54
|
+
export { ChatActionsContainer } from './feedback/chat-actions-container'
|
|
55
|
+
export { ChatRatingAction } from './feedback/chat-rating-action'
|
|
56
|
+
export { ChatToolTrace } from './feedback/chat-tool-trace'
|
|
57
|
+
export { ChatToolCodeArea } from './feedback/chat-tool-code-area'
|
|
58
|
+
export { ChatToolFullViewDialog } from './feedback/chat-tool-full-view-dialog'
|
|
59
|
+
export { ChatToolGroup } from './feedback/chat-tool-group'
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { ButtonBaseProps, SxProps, Theme } from '@mui/material'
|
|
3
|
+
|
|
4
|
+
// === Shared base props ===
|
|
5
|
+
export interface ChatSxProps {
|
|
6
|
+
sx?: SxProps<Theme>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// === Error types ===
|
|
10
|
+
export interface ChatErrorAction {
|
|
11
|
+
label: string
|
|
12
|
+
onClick: () => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// === Message props ===
|
|
16
|
+
export interface ChatUserMessageProps extends ChatSxProps {
|
|
17
|
+
children: ReactNode
|
|
18
|
+
/** enabled to render text with a lighter color for indicating things like an error sending the message */
|
|
19
|
+
muted?: boolean
|
|
20
|
+
/** content to render on top of the message for user attachments */
|
|
21
|
+
topContext?: ReactNode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ChatAgentMessageProps extends ChatSxProps {
|
|
25
|
+
children: ReactNode
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ChatErrorMessageProps extends ChatSxProps {
|
|
29
|
+
errors: string[]
|
|
30
|
+
icon?: ReactNode
|
|
31
|
+
actions?: ChatErrorAction[]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ChatSuggestionButtonProps
|
|
35
|
+
extends ChatSxProps, Omit<ButtonBaseProps, 'children'> {
|
|
36
|
+
label: ReactNode
|
|
37
|
+
color?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// === Feedback props ===
|
|
41
|
+
export interface ChatThinkingProps extends ChatSxProps {
|
|
42
|
+
duration?: number
|
|
43
|
+
children?: ReactNode
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ChatLoaderProps extends ChatSxProps {
|
|
47
|
+
size?: number
|
|
48
|
+
labels?: {
|
|
49
|
+
loading?: string
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// === Layout props ===
|
|
54
|
+
export interface ChatContentProps extends ChatSxProps {
|
|
55
|
+
children: ReactNode
|
|
56
|
+
/**
|
|
57
|
+
* Smooth-scrolls to the bottom whenever new content is added — but only if
|
|
58
|
+
* the user was already at (or near) the bottom. Readers who scrolled up to
|
|
59
|
+
* revisit older messages are left alone. Defaults to `true`; pass `false`
|
|
60
|
+
* to opt out and manage scroll yourself via the ref.
|
|
61
|
+
*/
|
|
62
|
+
autoScroll?: boolean
|
|
63
|
+
labels?: {
|
|
64
|
+
jumpToLatest?: string
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Imperative handle exposed by `ChatContent` via `ref`. Use it to drive scroll
|
|
70
|
+
* from the parent — for example, calling `scrollToBottom()` when a new agent
|
|
71
|
+
* message arrives.
|
|
72
|
+
*/
|
|
73
|
+
export interface ChatContentRef {
|
|
74
|
+
/** Smooth-scrolls the content area to the bottom. */
|
|
75
|
+
scrollToBottom: () => void
|
|
76
|
+
/** Smooth-scrolls the content area to the top. */
|
|
77
|
+
scrollToTop: () => void
|
|
78
|
+
/** `true` when the content area is scrolled to (or near) its bottom edge. */
|
|
79
|
+
isAtBottom: boolean
|
|
80
|
+
/** `true` when the content area is scrolled to (or near) its top edge. */
|
|
81
|
+
isAtTop: boolean
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// === Container props ===
|
|
85
|
+
export interface ChatHeaderProps extends ChatSxProps {
|
|
86
|
+
leftSlot?: ReactNode
|
|
87
|
+
title: ReactNode
|
|
88
|
+
rightSlot?: ReactNode
|
|
89
|
+
onClose?: () => void
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ChatFooterProps extends ChatSxProps {
|
|
93
|
+
/** Current value of the chat message area. */
|
|
94
|
+
value: string
|
|
95
|
+
/** Called with the new textarea value on every keystroke. */
|
|
96
|
+
onChange: (value: string) => void
|
|
97
|
+
/** Called when the send button is clicked or Enter is pressed (without Shift). */
|
|
98
|
+
onSend: () => void
|
|
99
|
+
/** Called when the stop button is clicked. Only shown while `isGenerating` is true. */
|
|
100
|
+
onStop?: () => void
|
|
101
|
+
/** When true, swaps the send button for a stop button and disables the textarea. */
|
|
102
|
+
isGenerating?: boolean
|
|
103
|
+
/** Disables the textarea and both send/stop buttons. */
|
|
104
|
+
disabled?: boolean
|
|
105
|
+
/** Placeholder text for the textarea. Defaults to `'Type a message...'`. */
|
|
106
|
+
placeholder?: string
|
|
107
|
+
/** Accessible labels for the send and stop buttons (used as `aria-label`). */
|
|
108
|
+
labels?: {
|
|
109
|
+
/** Defaults to `'Send'`. */
|
|
110
|
+
send?: string
|
|
111
|
+
/** Defaults to `'Stop'`. */
|
|
112
|
+
stop?: string
|
|
113
|
+
}
|
|
114
|
+
/** Helper text rendered under the input. Defaults to an AI disclaimer; pass `null` to hide. */
|
|
115
|
+
caption?: ReactNode
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// === Extras props ===
|
|
119
|
+
export interface ChatStarterItem {
|
|
120
|
+
label: string
|
|
121
|
+
color?: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface ChatStarterProps extends ChatSxProps {
|
|
125
|
+
icon?: ReactNode
|
|
126
|
+
title?: ReactNode
|
|
127
|
+
description?: ReactNode
|
|
128
|
+
items: string[] | ChatStarterItem[]
|
|
129
|
+
size?: 'small' | 'medium'
|
|
130
|
+
onSelect?: (prompt: string) => void
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface ChatRatingActionProps {
|
|
134
|
+
onRatingChange?: (rating: 'up' | 'down' | null) => void
|
|
135
|
+
rating?: 'up' | 'down' | null
|
|
136
|
+
labels?: {
|
|
137
|
+
thumbUp?: string
|
|
138
|
+
thumbDown?: string
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface ChatToolItem {
|
|
143
|
+
id: string
|
|
144
|
+
name: string
|
|
145
|
+
status: 'running' | 'complete' | 'error'
|
|
146
|
+
/** Display label shown while status is 'running'. Falls back to a capitalized `name`. */
|
|
147
|
+
runningLabel?: string
|
|
148
|
+
/** Display label shown for non-running statuses. Falls back to a capitalized `name`. */
|
|
149
|
+
label?: string
|
|
150
|
+
/** Friendly reference name for the tool (e.g. "add_marker"). Displayed with icon. */
|
|
151
|
+
reference?: string
|
|
152
|
+
/** Execution duration in seconds (e.g. 1.8) */
|
|
153
|
+
duration?: number
|
|
154
|
+
/** Input arguments as a JSON string or plain text */
|
|
155
|
+
inputArguments?: string
|
|
156
|
+
/** Output as a JSON string or plain text */
|
|
157
|
+
output?: string
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface ChatToolTraceProps extends ChatSxProps {
|
|
161
|
+
tool: ChatToolItem
|
|
162
|
+
/** Whether the trace accordion is expanded */
|
|
163
|
+
expanded?: boolean
|
|
164
|
+
/** Callback when accordion expansion state changes */
|
|
165
|
+
onExpandedChange?: (expanded: boolean) => void
|
|
166
|
+
labels?: {
|
|
167
|
+
toolExecuted?: string
|
|
168
|
+
reference?: string
|
|
169
|
+
duration?: string
|
|
170
|
+
status?: string
|
|
171
|
+
inputArguments?: string
|
|
172
|
+
output?: string
|
|
173
|
+
fullView?: string
|
|
174
|
+
success?: string
|
|
175
|
+
error?: string
|
|
176
|
+
running?: string
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface ChatToolCodeAreaProps extends ChatSxProps {
|
|
181
|
+
/** Code content to display */
|
|
182
|
+
content: string
|
|
183
|
+
/** Label for the full view dialog title */
|
|
184
|
+
title?: string
|
|
185
|
+
/** Render with error styling (red left border, tinted background) */
|
|
186
|
+
isError?: boolean
|
|
187
|
+
labels?: {
|
|
188
|
+
fullView?: string
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface ChatToolFullViewDialogProps {
|
|
193
|
+
open: boolean
|
|
194
|
+
onClose: () => void
|
|
195
|
+
title: string
|
|
196
|
+
content: string
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface ChatToolGroupProps extends ChatSxProps {
|
|
200
|
+
tools: ChatToolItem[]
|
|
201
|
+
/** Whether the group accordion is expanded */
|
|
202
|
+
expanded?: boolean
|
|
203
|
+
/** Callback when group expansion state changes */
|
|
204
|
+
onExpandedChange?: (expanded: boolean) => void
|
|
205
|
+
/** Map of tool IDs to their individual expanded state. Used to preserve expansion state during grouping. */
|
|
206
|
+
expandedTools?: Record<string, boolean>
|
|
207
|
+
/** Callback when an individual tool's expansion state changes */
|
|
208
|
+
onToolExpandedChange?: (
|
|
209
|
+
value: Record<string, boolean>,
|
|
210
|
+
toolId?: string,
|
|
211
|
+
) => void
|
|
212
|
+
labels?: ChatToolTraceProps['labels'] & {
|
|
213
|
+
toolsUsed?: string
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { renderHook } from '@testing-library/react'
|
|
3
|
+
import { useTypewriter } from './use-typewriter'
|
|
4
|
+
|
|
5
|
+
describe('useTypewriter', () => {
|
|
6
|
+
test('starts with empty text and isTyping=true when fullText is non-empty', () => {
|
|
7
|
+
const { result } = renderHook(() => useTypewriter('hello'))
|
|
8
|
+
expect(result.current.displayedText).toBe('')
|
|
9
|
+
expect(result.current.isTyping).toBe(true)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('returns the full text immediately when skipAnimation is true', () => {
|
|
13
|
+
const { result } = renderHook(() =>
|
|
14
|
+
useTypewriter('hello', { skipAnimation: true }),
|
|
15
|
+
)
|
|
16
|
+
expect(result.current.displayedText).toBe('hello')
|
|
17
|
+
expect(result.current.isTyping).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('isTyping=false for empty fullText', () => {
|
|
21
|
+
const { result } = renderHook(() => useTypewriter(''))
|
|
22
|
+
expect(result.current.displayedText).toBe('')
|
|
23
|
+
expect(result.current.isTyping).toBe(false)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('skipAnimation captured at mount — toggling later does not retrigger reveal', () => {
|
|
27
|
+
const { result, rerender } = renderHook(
|
|
28
|
+
({ skip }: { skip: boolean }) =>
|
|
29
|
+
useTypewriter('hello', { skipAnimation: skip }),
|
|
30
|
+
{ initialProps: { skip: true } },
|
|
31
|
+
)
|
|
32
|
+
expect(result.current.displayedText).toBe('hello')
|
|
33
|
+
|
|
34
|
+
rerender({ skip: false })
|
|
35
|
+
expect(result.current.displayedText).toBe('hello')
|
|
36
|
+
expect(result.current.isTyping).toBe(false)
|
|
37
|
+
})
|
|
38
|
+
})
|