@autobe/ui 0.29.2 → 0.30.0-dev.20260315

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 (151) hide show
  1. package/LICENSE +661 -661
  2. package/README.md +261 -0
  3. package/lib/components/AutoBeChatMain.js +5 -5
  4. package/lib/components/AutoBeChatMain.js.map +1 -1
  5. package/lib/components/AutoBeConfigModal.js +9 -9
  6. package/lib/components/AutoBeStatusModal.js +4 -4
  7. package/lib/components/AutoBeStatusModal.js.map +1 -1
  8. package/lib/components/AutoBeUserMessageMovie.d.ts +2 -2
  9. package/lib/components/common/ChatBubble.d.ts +2 -2
  10. package/lib/components/common/openai/OpenAIContent.d.ts +2 -2
  11. package/lib/components/common/openai/OpenAIContent.js.map +1 -1
  12. package/lib/components/common/openai/OpenAIUserAudioContent.js +1 -1
  13. package/lib/components/common/openai/OpenAIUserAudioContent.js.map +1 -1
  14. package/lib/components/common/openai/OpenAIUserFileContent.js +1 -1
  15. package/lib/components/common/openai/OpenAIUserFileContent.js.map +1 -1
  16. package/lib/components/common/openai/OpenAIUserImageContent.d.ts +2 -2
  17. package/lib/components/events/AutoBeCompleteEventMovie.d.ts +2 -2
  18. package/lib/components/events/AutoBeCompleteEventMovie.js +5 -5
  19. package/lib/components/events/AutoBeCompleteEventMovie.js.map +1 -1
  20. package/lib/components/events/AutoBeCorrectEventMovie.d.ts +2 -2
  21. package/lib/components/events/AutoBeCorrectEventMovie.js +4 -4
  22. package/lib/components/events/AutoBeCorrectEventMovie.js.map +1 -1
  23. package/lib/components/events/AutoBeEventMovie.js +38 -17
  24. package/lib/components/events/AutoBeEventMovie.js.map +1 -1
  25. package/lib/components/events/AutoBeProgressEventMovie.js +73 -13
  26. package/lib/components/events/AutoBeProgressEventMovie.js.map +1 -1
  27. package/lib/components/events/AutoBeScenarioEventMovie.d.ts +2 -2
  28. package/lib/components/events/AutoBeScenarioEventMovie.js +18 -5
  29. package/lib/components/events/AutoBeScenarioEventMovie.js.map +1 -1
  30. package/lib/components/events/AutoBeStartEventMovie.d.ts +2 -2
  31. package/lib/components/events/AutoBeStartEventMovie.js +2 -2
  32. package/lib/components/events/AutoBeStartEventMovie.js.map +1 -1
  33. package/lib/components/events/AutoBeValidateEventMovie.d.ts +2 -2
  34. package/lib/components/events/AutoBeValidateEventMovie.js +3 -11
  35. package/lib/components/events/AutoBeValidateEventMovie.js.map +1 -1
  36. package/lib/components/events/groups/CorrectEventGroup.d.ts +2 -2
  37. package/lib/components/events/groups/CorrectEventGroup.js +1 -1
  38. package/lib/components/events/groups/CorrectEventGroup.js.map +1 -1
  39. package/lib/components/events/groups/ValidateEventGroup.d.ts +2 -2
  40. package/lib/components/events/groups/ValidateEventGroup.js +1 -2
  41. package/lib/components/events/groups/ValidateEventGroup.js.map +1 -1
  42. package/lib/components/events/utils/eventGrouper.js +1 -2
  43. package/lib/components/events/utils/eventGrouper.js.map +1 -1
  44. package/lib/components/upload/AutoBeChatUploadBox.d.ts +3 -4
  45. package/lib/components/upload/AutoBeChatUploadBox.js +2 -1
  46. package/lib/components/upload/AutoBeChatUploadBox.js.map +1 -1
  47. package/lib/components/upload/AutoBeChatUploadSendButton.js +1 -1
  48. package/lib/components/upload/AutoBeChatUploadSendButton.js.map +1 -1
  49. package/lib/context/AutoBeAgentContext.d.ts +1 -3
  50. package/lib/context/AutoBeAgentContext.js +0 -4
  51. package/lib/context/AutoBeAgentContext.js.map +1 -1
  52. package/lib/hooks/useSessionStorage.d.ts +4 -0
  53. package/lib/hooks/useSessionStorage.js +16 -0
  54. package/lib/hooks/useSessionStorage.js.map +1 -0
  55. package/lib/index.d.ts +1 -0
  56. package/lib/index.js +1 -0
  57. package/lib/index.js.map +1 -1
  58. package/lib/strategy/AutoBeAgentSessionStorageStrategy.d.ts +10 -0
  59. package/lib/strategy/AutoBeAgentSessionStorageStrategy.js +117 -0
  60. package/lib/strategy/AutoBeAgentSessionStorageStrategy.js.map +1 -0
  61. package/lib/structure/AutoBeListener.js +91 -23
  62. package/lib/structure/AutoBeListener.js.map +1 -1
  63. package/lib/structure/AutoBeListenerState.d.ts +3 -3
  64. package/lib/structure/AutoBeListenerState.js +4 -4
  65. package/lib/structure/AutoBeListenerState.js.map +1 -1
  66. package/lib/structure/IAutoBeAgentSessionStorageStrategy.js +1 -1
  67. package/lib/structure/IAutoBeAgentSessionStorageStrategy.js.map +1 -1
  68. package/lib/utils/AutoBeFileUploader.d.ts +2 -2
  69. package/lib/utils/AutoBeFileUploader.js.map +1 -1
  70. package/package.json +3 -4
  71. package/src/components/AutoBeAssistantMessageMovie.tsx +22 -22
  72. package/src/components/AutoBeChatMain.tsx +376 -376
  73. package/src/components/AutoBeChatSidebar.tsx +414 -414
  74. package/src/components/AutoBeConfigButton.tsx +83 -83
  75. package/src/components/AutoBeConfigModal.tsx +443 -443
  76. package/src/components/AutoBeStatusButton.tsx +75 -75
  77. package/src/components/AutoBeStatusModal.tsx +486 -484
  78. package/src/components/AutoBeUserMessageMovie.tsx +27 -27
  79. package/src/components/common/ActionButton.tsx +205 -205
  80. package/src/components/common/ActionButtonGroup.tsx +80 -80
  81. package/src/components/common/AutoBeConfigInput.tsx +185 -185
  82. package/src/components/common/ChatBubble.tsx +119 -119
  83. package/src/components/common/Collapsible.tsx +95 -95
  84. package/src/components/common/CompactSessionIndicator.tsx +73 -73
  85. package/src/components/common/CompactSessionList.tsx +82 -82
  86. package/src/components/common/index.ts +8 -8
  87. package/src/components/common/openai/OpenAIContent.tsx +53 -53
  88. package/src/components/common/openai/OpenAIUserAudioContent.tsx +70 -70
  89. package/src/components/common/openai/OpenAIUserFileContent.tsx +76 -76
  90. package/src/components/common/openai/OpenAIUserImageContent.tsx +34 -34
  91. package/src/components/common/openai/OpenAIUserTextContent.tsx +15 -15
  92. package/src/components/common/openai/index.ts +5 -5
  93. package/src/components/events/AutoBeCompleteEventMovie.tsx +402 -402
  94. package/src/components/events/AutoBeCorrectEventMovie.tsx +354 -368
  95. package/src/components/events/AutoBeEventGroupMovie.tsx +18 -18
  96. package/src/components/events/AutoBeEventMovie.tsx +158 -139
  97. package/src/components/events/AutoBeProgressEventMovie.tsx +217 -157
  98. package/src/components/events/AutoBeScenarioEventMovie.tsx +135 -95
  99. package/src/components/events/AutoBeStartEventMovie.tsx +82 -82
  100. package/src/components/events/AutoBeValidateEventMovie.tsx +249 -286
  101. package/src/components/events/README.md +300 -300
  102. package/src/components/events/common/CollapsibleEventGroup.tsx +211 -211
  103. package/src/components/events/common/EventCard.tsx +61 -61
  104. package/src/components/events/common/EventContent.tsx +31 -31
  105. package/src/components/events/common/EventHeader.tsx +85 -85
  106. package/src/components/events/common/EventIcon.tsx +82 -82
  107. package/src/components/events/common/ProgressBar.tsx +64 -64
  108. package/src/components/events/common/index.ts +13 -13
  109. package/src/components/events/groups/CorrectEventGroup.tsx +183 -183
  110. package/src/components/events/groups/ValidateEventGroup.tsx +143 -146
  111. package/src/components/events/groups/index.ts +8 -8
  112. package/src/components/events/index.ts +16 -16
  113. package/src/components/events/utils/eventGrouper.tsx +116 -117
  114. package/src/components/events/utils/index.ts +1 -1
  115. package/src/components/index.ts +13 -13
  116. package/src/components/upload/AutoBeChatUploadBox.tsx +425 -424
  117. package/src/components/upload/AutoBeChatUploadSendButton.tsx +66 -66
  118. package/src/components/upload/AutoBeFileUploadBox.tsx +123 -123
  119. package/src/components/upload/AutoBeUploadConfig.ts +5 -5
  120. package/src/components/upload/AutoBeVoiceRecoderButton.tsx +100 -100
  121. package/src/components/upload/index.ts +5 -5
  122. package/src/constant/color.ts +28 -28
  123. package/src/context/AutoBeAgentContext.tsx +245 -258
  124. package/src/context/AutoBeAgentSessionList.tsx +58 -58
  125. package/src/context/SearchParamsContext.tsx +49 -49
  126. package/src/hooks/index.ts +3 -3
  127. package/src/hooks/useEscapeKey.ts +24 -24
  128. package/src/hooks/useIsomorphicLayoutEffect.ts +8 -8
  129. package/src/hooks/useMediaQuery.ts +73 -73
  130. package/src/hooks/useSessionStorage.ts +10 -0
  131. package/src/icons/Receipt.tsx +74 -74
  132. package/src/index.ts +9 -8
  133. package/src/strategy/AutoBeAgentSessionStorageStrategy.ts +127 -0
  134. package/src/structure/AutoBeListener.ts +373 -304
  135. package/src/structure/AutoBeListenerState.ts +53 -53
  136. package/src/structure/IAutoBeAgentSessionStorageStrategy.ts +87 -87
  137. package/src/structure/IAutoBeEventGroup.ts +6 -6
  138. package/src/structure/index.ts +4 -4
  139. package/src/types/config.ts +44 -44
  140. package/src/types/index.ts +1 -1
  141. package/src/utils/AutoBeFileUploader.ts +279 -279
  142. package/src/utils/AutoBeVoiceRecorder.ts +95 -95
  143. package/src/utils/__tests__/crypto.test.ts +286 -286
  144. package/src/utils/__tests__/storage.test.ts +229 -229
  145. package/src/utils/crypto.ts +95 -95
  146. package/src/utils/index.ts +6 -6
  147. package/src/utils/number.ts +17 -17
  148. package/src/utils/storage.ts +96 -96
  149. package/src/utils/time.ts +14 -14
  150. package/tsconfig.json +9 -9
  151. package/vitest.config.ts +15 -15
@@ -1,27 +1,27 @@
1
- import { AutoBeUserMessageContent } from "@autobe/interface";
2
-
3
- import ChatBubble from "./common/ChatBubble";
4
-
5
- interface IAutoBeUserMessageHistoryMovieProps {
6
- message: Array<AutoBeUserMessageContent>;
7
- }
8
-
9
- export const AutoBeUserMessageMovie = (
10
- props: IAutoBeUserMessageHistoryMovieProps,
11
- ) => {
12
- const { message } = props;
13
-
14
- return (
15
- <div
16
- style={{
17
- display: "flex",
18
- flexDirection: "column",
19
- gap: 8,
20
- }}
21
- >
22
- <ChatBubble content={message} direction="right" assistantName="You" />
23
- </div>
24
- );
25
- };
26
-
27
- export default AutoBeUserMessageMovie;
1
+ import { AutoBeUserConversateContent } from "@autobe/interface";
2
+
3
+ import ChatBubble from "./common/ChatBubble";
4
+
5
+ interface IAutoBeUserMessageHistoryMovieProps {
6
+ message: Array<AutoBeUserConversateContent>;
7
+ }
8
+
9
+ export const AutoBeUserMessageMovie = (
10
+ props: IAutoBeUserMessageHistoryMovieProps,
11
+ ) => {
12
+ const { message } = props;
13
+
14
+ return (
15
+ <div
16
+ style={{
17
+ display: "flex",
18
+ flexDirection: "column",
19
+ gap: 8,
20
+ }}
21
+ >
22
+ <ChatBubble content={message} direction="right" assistantName="You" />
23
+ </div>
24
+ );
25
+ };
26
+
27
+ export default AutoBeUserMessageMovie;
@@ -1,205 +1,205 @@
1
- export function ActionButton(props: ActionButton.IProps) {
2
- //----
3
- // STYLES
4
- //----
5
- const baseButtonStyle: React.CSSProperties = {
6
- background: "rgba(255, 255, 255, 0.9)",
7
- border: "1px solid rgba(0, 0, 0, 0.1)",
8
- cursor: "pointer",
9
- padding: "0.25rem",
10
- borderRadius: "0.375rem",
11
- display: "flex",
12
- alignItems: "center",
13
- justifyContent: "center",
14
- color: "#4b5563",
15
- transition: "all 0.2s ease",
16
- width: "1.5rem",
17
- height: "1.5rem",
18
- boxShadow: "0 1px 2px rgba(0, 0, 0, 0.1)",
19
- };
20
-
21
- const getHoverColors = (variant: ActionButton.Variant) => {
22
- switch (variant) {
23
- case "edit":
24
- return {
25
- backgroundColor: "#f1f5f9",
26
- color: "#475569",
27
- borderColor: "#cbd5e1",
28
- boxShadow: "0 2px 4px rgba(71, 85, 105, 0.12)",
29
- };
30
- case "delete":
31
- return {
32
- backgroundColor: "#fef2f2",
33
- color: "#dc2626",
34
- borderColor: "#fecaca",
35
- boxShadow: "0 2px 4px rgba(220, 38, 38, 0.15)",
36
- };
37
- case "save":
38
- return {
39
- backgroundColor: "#f0fdf4",
40
- color: "#22c55e",
41
- borderColor: "#bbf7d0",
42
- boxShadow: "0 2px 4px rgba(34, 197, 94, 0.15)",
43
- };
44
- case "cancel":
45
- return {
46
- backgroundColor: "#fff1f2",
47
- color: "#ef4444",
48
- borderColor: "#fecdd3",
49
- boxShadow: "0 2px 4px rgba(239, 68, 68, 0.15)",
50
- };
51
- default:
52
- return {
53
- backgroundColor: "#f1f5f9",
54
- color: "#475569",
55
- borderColor: "#cbd5e1",
56
- boxShadow: "0 2px 4px rgba(71, 85, 105, 0.12)",
57
- };
58
- }
59
- };
60
-
61
- const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
62
- const hoverColors = getHoverColors(props.variant);
63
- e.currentTarget.style.backgroundColor = hoverColors.backgroundColor;
64
- e.currentTarget.style.color = hoverColors.color;
65
- e.currentTarget.style.borderColor = hoverColors.borderColor;
66
- e.currentTarget.style.boxShadow = hoverColors.boxShadow;
67
- e.currentTarget.style.transform = "translateY(-1px)";
68
- };
69
-
70
- const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
71
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
72
- e.currentTarget.style.color = "#4b5563";
73
- e.currentTarget.style.borderColor = "rgba(0, 0, 0, 0.1)";
74
- e.currentTarget.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.1)";
75
- e.currentTarget.style.transform = "translateY(0)";
76
- };
77
-
78
- //----
79
- // ICONS
80
- //----
81
- const renderIcon = () => {
82
- switch (props.variant) {
83
- case "edit":
84
- return (
85
- <svg
86
- width="12"
87
- height="12"
88
- viewBox="0 0 24 24"
89
- fill="none"
90
- stroke="currentColor"
91
- strokeWidth="2"
92
- strokeLinecap="round"
93
- strokeLinejoin="round"
94
- >
95
- <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
96
- <path d="m18.5 2.5 a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4Z" />
97
- </svg>
98
- );
99
- case "delete":
100
- return (
101
- <svg
102
- width="12"
103
- height="12"
104
- viewBox="0 0 24 24"
105
- fill="none"
106
- stroke="currentColor"
107
- strokeWidth="2.5"
108
- strokeLinecap="round"
109
- strokeLinejoin="round"
110
- >
111
- <path d="M18 6L6 18" />
112
- <path d="M6 6l12 12" />
113
- </svg>
114
- );
115
- case "save":
116
- return (
117
- <svg
118
- width="12"
119
- height="12"
120
- viewBox="0 0 24 24"
121
- fill="none"
122
- stroke="currentColor"
123
- strokeWidth="2.5"
124
- strokeLinecap="round"
125
- strokeLinejoin="round"
126
- >
127
- <polyline points="20,6 9,17 4,12" />
128
- </svg>
129
- );
130
- case "cancel":
131
- return (
132
- <svg
133
- width="12"
134
- height="12"
135
- viewBox="0 0 24 24"
136
- fill="none"
137
- stroke="currentColor"
138
- strokeWidth="2.5"
139
- strokeLinecap="round"
140
- strokeLinejoin="round"
141
- >
142
- <path d="M18 6L6 18" />
143
- <path d="M6 6l12 12" />
144
- </svg>
145
- );
146
- default:
147
- return null;
148
- }
149
- };
150
-
151
- const getTitle = () => {
152
- switch (props.variant) {
153
- case "edit":
154
- return "Edit title";
155
- case "delete":
156
- return "Delete conversation";
157
- case "save":
158
- return "Save changes";
159
- case "cancel":
160
- return "Cancel editing";
161
- default:
162
- return "";
163
- }
164
- };
165
-
166
- //----
167
- // RENDER
168
- //----
169
- return (
170
- <button
171
- onClick={props.onClick}
172
- onMouseEnter={handleMouseEnter}
173
- onMouseLeave={handleMouseLeave}
174
- style={{
175
- ...baseButtonStyle,
176
- ...props.style,
177
- }}
178
- title={props.title ?? getTitle()}
179
- disabled={props.disabled}
180
- >
181
- {renderIcon()}
182
- </button>
183
- );
184
- }
185
-
186
- export namespace ActionButton {
187
- export type Variant = "edit" | "delete" | "save" | "cancel";
188
-
189
- export interface IProps {
190
- /** Button variant that determines icon and hover colors */
191
- variant: Variant;
192
-
193
- /** Click handler */
194
- onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
195
-
196
- /** Custom title for tooltip */
197
- title?: string;
198
-
199
- /** Whether button is disabled */
200
- disabled?: boolean;
201
-
202
- /** Custom style overrides */
203
- style?: React.CSSProperties;
204
- }
205
- }
1
+ export function ActionButton(props: ActionButton.IProps) {
2
+ //----
3
+ // STYLES
4
+ //----
5
+ const baseButtonStyle: React.CSSProperties = {
6
+ background: "rgba(255, 255, 255, 0.9)",
7
+ border: "1px solid rgba(0, 0, 0, 0.1)",
8
+ cursor: "pointer",
9
+ padding: "0.25rem",
10
+ borderRadius: "0.375rem",
11
+ display: "flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ color: "#4b5563",
15
+ transition: "all 0.2s ease",
16
+ width: "1.5rem",
17
+ height: "1.5rem",
18
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.1)",
19
+ };
20
+
21
+ const getHoverColors = (variant: ActionButton.Variant) => {
22
+ switch (variant) {
23
+ case "edit":
24
+ return {
25
+ backgroundColor: "#f1f5f9",
26
+ color: "#475569",
27
+ borderColor: "#cbd5e1",
28
+ boxShadow: "0 2px 4px rgba(71, 85, 105, 0.12)",
29
+ };
30
+ case "delete":
31
+ return {
32
+ backgroundColor: "#fef2f2",
33
+ color: "#dc2626",
34
+ borderColor: "#fecaca",
35
+ boxShadow: "0 2px 4px rgba(220, 38, 38, 0.15)",
36
+ };
37
+ case "save":
38
+ return {
39
+ backgroundColor: "#f0fdf4",
40
+ color: "#22c55e",
41
+ borderColor: "#bbf7d0",
42
+ boxShadow: "0 2px 4px rgba(34, 197, 94, 0.15)",
43
+ };
44
+ case "cancel":
45
+ return {
46
+ backgroundColor: "#fff1f2",
47
+ color: "#ef4444",
48
+ borderColor: "#fecdd3",
49
+ boxShadow: "0 2px 4px rgba(239, 68, 68, 0.15)",
50
+ };
51
+ default:
52
+ return {
53
+ backgroundColor: "#f1f5f9",
54
+ color: "#475569",
55
+ borderColor: "#cbd5e1",
56
+ boxShadow: "0 2px 4px rgba(71, 85, 105, 0.12)",
57
+ };
58
+ }
59
+ };
60
+
61
+ const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
62
+ const hoverColors = getHoverColors(props.variant);
63
+ e.currentTarget.style.backgroundColor = hoverColors.backgroundColor;
64
+ e.currentTarget.style.color = hoverColors.color;
65
+ e.currentTarget.style.borderColor = hoverColors.borderColor;
66
+ e.currentTarget.style.boxShadow = hoverColors.boxShadow;
67
+ e.currentTarget.style.transform = "translateY(-1px)";
68
+ };
69
+
70
+ const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
71
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
72
+ e.currentTarget.style.color = "#4b5563";
73
+ e.currentTarget.style.borderColor = "rgba(0, 0, 0, 0.1)";
74
+ e.currentTarget.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.1)";
75
+ e.currentTarget.style.transform = "translateY(0)";
76
+ };
77
+
78
+ //----
79
+ // ICONS
80
+ //----
81
+ const renderIcon = () => {
82
+ switch (props.variant) {
83
+ case "edit":
84
+ return (
85
+ <svg
86
+ width="12"
87
+ height="12"
88
+ viewBox="0 0 24 24"
89
+ fill="none"
90
+ stroke="currentColor"
91
+ strokeWidth="2"
92
+ strokeLinecap="round"
93
+ strokeLinejoin="round"
94
+ >
95
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
96
+ <path d="m18.5 2.5 a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4Z" />
97
+ </svg>
98
+ );
99
+ case "delete":
100
+ return (
101
+ <svg
102
+ width="12"
103
+ height="12"
104
+ viewBox="0 0 24 24"
105
+ fill="none"
106
+ stroke="currentColor"
107
+ strokeWidth="2.5"
108
+ strokeLinecap="round"
109
+ strokeLinejoin="round"
110
+ >
111
+ <path d="M18 6L6 18" />
112
+ <path d="M6 6l12 12" />
113
+ </svg>
114
+ );
115
+ case "save":
116
+ return (
117
+ <svg
118
+ width="12"
119
+ height="12"
120
+ viewBox="0 0 24 24"
121
+ fill="none"
122
+ stroke="currentColor"
123
+ strokeWidth="2.5"
124
+ strokeLinecap="round"
125
+ strokeLinejoin="round"
126
+ >
127
+ <polyline points="20,6 9,17 4,12" />
128
+ </svg>
129
+ );
130
+ case "cancel":
131
+ return (
132
+ <svg
133
+ width="12"
134
+ height="12"
135
+ viewBox="0 0 24 24"
136
+ fill="none"
137
+ stroke="currentColor"
138
+ strokeWidth="2.5"
139
+ strokeLinecap="round"
140
+ strokeLinejoin="round"
141
+ >
142
+ <path d="M18 6L6 18" />
143
+ <path d="M6 6l12 12" />
144
+ </svg>
145
+ );
146
+ default:
147
+ return null;
148
+ }
149
+ };
150
+
151
+ const getTitle = () => {
152
+ switch (props.variant) {
153
+ case "edit":
154
+ return "Edit title";
155
+ case "delete":
156
+ return "Delete conversation";
157
+ case "save":
158
+ return "Save changes";
159
+ case "cancel":
160
+ return "Cancel editing";
161
+ default:
162
+ return "";
163
+ }
164
+ };
165
+
166
+ //----
167
+ // RENDER
168
+ //----
169
+ return (
170
+ <button
171
+ onClick={props.onClick}
172
+ onMouseEnter={handleMouseEnter}
173
+ onMouseLeave={handleMouseLeave}
174
+ style={{
175
+ ...baseButtonStyle,
176
+ ...props.style,
177
+ }}
178
+ title={props.title ?? getTitle()}
179
+ disabled={props.disabled}
180
+ >
181
+ {renderIcon()}
182
+ </button>
183
+ );
184
+ }
185
+
186
+ export namespace ActionButton {
187
+ export type Variant = "edit" | "delete" | "save" | "cancel";
188
+
189
+ export interface IProps {
190
+ /** Button variant that determines icon and hover colors */
191
+ variant: Variant;
192
+
193
+ /** Click handler */
194
+ onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
195
+
196
+ /** Custom title for tooltip */
197
+ title?: string;
198
+
199
+ /** Whether button is disabled */
200
+ disabled?: boolean;
201
+
202
+ /** Custom style overrides */
203
+ style?: React.CSSProperties;
204
+ }
205
+ }
@@ -1,80 +1,80 @@
1
- import { ActionButton } from "./ActionButton";
2
-
3
- export function ActionButtonGroup(props: ActionButtonGroup.IProps) {
4
- //----
5
- // STYLES
6
- //----
7
- const containerStyle: React.CSSProperties = {
8
- display: "flex",
9
- alignItems: "center",
10
- gap: "0.375rem",
11
- flexShrink: 0,
12
- };
13
-
14
- //----
15
- // RENDER
16
- //----
17
- return (
18
- <div style={containerStyle}>
19
- {/* Edit button */}
20
- {props.onEdit && (
21
- <ActionButton
22
- variant="edit"
23
- onClick={(e) => {
24
- e.stopPropagation();
25
- props.onEdit?.();
26
- }}
27
- />
28
- )}
29
-
30
- {/* Delete button */}
31
- {props.onDelete && (
32
- <ActionButton
33
- variant="delete"
34
- onClick={(e) => {
35
- e.stopPropagation();
36
- props.onDelete?.();
37
- }}
38
- />
39
- )}
40
-
41
- {/* Save button */}
42
- {props.onSave && (
43
- <ActionButton
44
- variant="save"
45
- onClick={(e) => {
46
- e.stopPropagation();
47
- props.onSave?.();
48
- }}
49
- />
50
- )}
51
-
52
- {/* Cancel button */}
53
- {props.onCancel && (
54
- <ActionButton
55
- variant="cancel"
56
- onClick={(e) => {
57
- e.stopPropagation();
58
- props.onCancel?.();
59
- }}
60
- />
61
- )}
62
- </div>
63
- );
64
- }
65
-
66
- export namespace ActionButtonGroup {
67
- export interface IProps {
68
- /** Edit handler - if provided, edit button will be shown */
69
- onEdit?: () => void;
70
-
71
- /** Delete handler - if provided, delete button will be shown */
72
- onDelete?: () => void;
73
-
74
- /** Save handler - if provided, save button will be shown */
75
- onSave?: () => void;
76
-
77
- /** Cancel handler - if provided, cancel button will be shown */
78
- onCancel?: () => void;
79
- }
80
- }
1
+ import { ActionButton } from "./ActionButton";
2
+
3
+ export function ActionButtonGroup(props: ActionButtonGroup.IProps) {
4
+ //----
5
+ // STYLES
6
+ //----
7
+ const containerStyle: React.CSSProperties = {
8
+ display: "flex",
9
+ alignItems: "center",
10
+ gap: "0.375rem",
11
+ flexShrink: 0,
12
+ };
13
+
14
+ //----
15
+ // RENDER
16
+ //----
17
+ return (
18
+ <div style={containerStyle}>
19
+ {/* Edit button */}
20
+ {props.onEdit && (
21
+ <ActionButton
22
+ variant="edit"
23
+ onClick={(e) => {
24
+ e.stopPropagation();
25
+ props.onEdit?.();
26
+ }}
27
+ />
28
+ )}
29
+
30
+ {/* Delete button */}
31
+ {props.onDelete && (
32
+ <ActionButton
33
+ variant="delete"
34
+ onClick={(e) => {
35
+ e.stopPropagation();
36
+ props.onDelete?.();
37
+ }}
38
+ />
39
+ )}
40
+
41
+ {/* Save button */}
42
+ {props.onSave && (
43
+ <ActionButton
44
+ variant="save"
45
+ onClick={(e) => {
46
+ e.stopPropagation();
47
+ props.onSave?.();
48
+ }}
49
+ />
50
+ )}
51
+
52
+ {/* Cancel button */}
53
+ {props.onCancel && (
54
+ <ActionButton
55
+ variant="cancel"
56
+ onClick={(e) => {
57
+ e.stopPropagation();
58
+ props.onCancel?.();
59
+ }}
60
+ />
61
+ )}
62
+ </div>
63
+ );
64
+ }
65
+
66
+ export namespace ActionButtonGroup {
67
+ export interface IProps {
68
+ /** Edit handler - if provided, edit button will be shown */
69
+ onEdit?: () => void;
70
+
71
+ /** Delete handler - if provided, delete button will be shown */
72
+ onDelete?: () => void;
73
+
74
+ /** Save handler - if provided, save button will be shown */
75
+ onSave?: () => void;
76
+
77
+ /** Cancel handler - if provided, cancel button will be shown */
78
+ onCancel?: () => void;
79
+ }
80
+ }