@devicai/ui 0.3.0 → 0.5.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.
@@ -0,0 +1,252 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { forwardRef, useMemo, useImperativeHandle, useRef, useEffect, useCallback } from 'react';
3
+ import { useAIGenerationButton } from './useAIGenerationButton.js';
4
+
5
+ const DEFAULT_OPTIONS = {
6
+ mode: 'modal',
7
+ prompt: '',
8
+ placeholder: 'Describe what you want to generate...',
9
+ modalTitle: 'Generate with AI',
10
+ modalDescription: '',
11
+ confirmText: 'Generate',
12
+ cancelText: 'Cancel',
13
+ tooltipPlacement: 'top',
14
+ tooltipWidth: 300,
15
+ variant: 'primary',
16
+ size: 'medium',
17
+ icon: undefined,
18
+ hideIcon: false,
19
+ label: 'Generate with AI',
20
+ hideLabel: false,
21
+ loadingLabel: 'Generating...',
22
+ color: '#3b82f6',
23
+ backgroundColor: '',
24
+ textColor: '',
25
+ borderColor: '',
26
+ borderRadius: 8,
27
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
28
+ fontSize: 14,
29
+ zIndex: 10000,
30
+ animationDuration: 200,
31
+ toolRenderers: undefined,
32
+ toolIcons: undefined,
33
+ processingMessage: 'Processing...',
34
+ };
35
+ /**
36
+ * AIGenerationButton component - a button that triggers AI generation with configurable interaction modes
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // Direct mode - sends predefined prompt on click
41
+ * <AIGenerationButton
42
+ * assistantId="my-assistant"
43
+ * options={{
44
+ * mode: 'direct',
45
+ * prompt: 'Generate a summary of the current page',
46
+ * label: 'Summarize',
47
+ * }}
48
+ * onResponse={({ message }) => console.log(message.content)}
49
+ * />
50
+ *
51
+ * // Modal mode - opens modal for user input
52
+ * <AIGenerationButton
53
+ * assistantId="my-assistant"
54
+ * options={{
55
+ * mode: 'modal',
56
+ * modalTitle: 'Generate Content',
57
+ * placeholder: 'Describe what you want...',
58
+ * }}
59
+ * onResponse={({ message }) => setContent(message.content.message)}
60
+ * />
61
+ *
62
+ * // Tooltip mode - quick inline input
63
+ * <AIGenerationButton
64
+ * assistantId="my-assistant"
65
+ * options={{
66
+ * mode: 'tooltip',
67
+ * tooltipPlacement: 'bottom',
68
+ * }}
69
+ * onResponse={handleGeneration}
70
+ * />
71
+ * ```
72
+ */
73
+ const AIGenerationButton = forwardRef(function AIGenerationButton(props, ref) {
74
+ const { assistantId, apiKey, baseUrl, tenantId, tenantMetadata, options = {}, modelInterfaceTools, onResponse, onBeforeSend, onError, onStart, onOpen, onClose, disabled, className, containerClassName, children, theme, } = props;
75
+ const mergedOptions = useMemo(() => ({ ...DEFAULT_OPTIONS, ...options }), [options]);
76
+ const hook = useAIGenerationButton({
77
+ assistantId,
78
+ apiKey,
79
+ baseUrl,
80
+ tenantId,
81
+ tenantMetadata,
82
+ options: mergedOptions,
83
+ modelInterfaceTools,
84
+ onResponse,
85
+ onBeforeSend,
86
+ onError,
87
+ onStart,
88
+ onOpen,
89
+ onClose,
90
+ disabled,
91
+ });
92
+ // Expose handle
93
+ useImperativeHandle(ref, () => ({
94
+ generate: hook.generate,
95
+ open: hook.open,
96
+ close: hook.close,
97
+ reset: hook.reset,
98
+ isProcessing: hook.isProcessing,
99
+ }));
100
+ // Container ref for theming
101
+ const containerRef = useRef(null);
102
+ const tooltipRef = useRef(null);
103
+ // Apply CSS variables for theming
104
+ useEffect(() => {
105
+ const el = containerRef.current;
106
+ if (!el)
107
+ return;
108
+ const vars = [
109
+ ['--devic-gen-primary', mergedOptions.color],
110
+ ['----devic-gen-bg', mergedOptions.backgroundColor || undefined],
111
+ ['--devic-gen-text', mergedOptions.textColor || undefined],
112
+ ['--devic-gen-border', mergedOptions.borderColor || undefined],
113
+ ['--devic-gen-font-family', mergedOptions.fontFamily],
114
+ ['--devic-gen-font-size', typeof mergedOptions.fontSize === 'number' ? `${mergedOptions.fontSize}px` : mergedOptions.fontSize],
115
+ ['--devic-gen-radius', typeof mergedOptions.borderRadius === 'number' ? `${mergedOptions.borderRadius}px` : mergedOptions.borderRadius],
116
+ ['--devic-gen-z-index', String(mergedOptions.zIndex)],
117
+ ['--devic-gen-animation-duration', `${mergedOptions.animationDuration}ms`],
118
+ ];
119
+ // Apply theme from parent if provided
120
+ if (theme) {
121
+ if (theme.backgroundColor)
122
+ vars.push(['--devic-gen-modal-bg', theme.backgroundColor]);
123
+ if (theme.textColor)
124
+ vars.push(['--devic-gen-modal-text', theme.textColor]);
125
+ if (theme.borderColor)
126
+ vars.push(['--devic-gen-modal-border', theme.borderColor]);
127
+ if (theme.primaryColor)
128
+ vars.push(['--devic-gen-primary', theme.primaryColor]);
129
+ }
130
+ for (const [name, value] of vars) {
131
+ if (value) {
132
+ el.style.setProperty(name, value);
133
+ }
134
+ else {
135
+ el.style.removeProperty(name);
136
+ }
137
+ }
138
+ }, [mergedOptions, theme]);
139
+ // Click outside to close tooltip
140
+ useEffect(() => {
141
+ if (!hook.isOpen || mergedOptions.mode !== 'tooltip')
142
+ return;
143
+ const handleClickOutside = (e) => {
144
+ const tooltip = tooltipRef.current;
145
+ const container = containerRef.current;
146
+ if (tooltip &&
147
+ container &&
148
+ !tooltip.contains(e.target) &&
149
+ !container.contains(e.target)) {
150
+ hook.close();
151
+ }
152
+ };
153
+ document.addEventListener('mousedown', handleClickOutside);
154
+ return () => document.removeEventListener('mousedown', handleClickOutside);
155
+ }, [hook.isOpen, mergedOptions.mode, hook.close]);
156
+ // Handle button click
157
+ const handleButtonClick = useCallback(() => {
158
+ if (disabled || hook.isProcessing)
159
+ return;
160
+ if (mergedOptions.mode === 'direct') {
161
+ hook.generate();
162
+ }
163
+ else {
164
+ hook.open();
165
+ }
166
+ }, [disabled, hook.isProcessing, mergedOptions.mode, hook.generate, hook.open]);
167
+ // Handle confirm in modal/tooltip
168
+ const handleConfirm = useCallback(() => {
169
+ hook.generate();
170
+ }, [hook.generate]);
171
+ // Tooltip position styles
172
+ const tooltipPositionStyle = useMemo(() => {
173
+ const placement = mergedOptions.tooltipPlacement;
174
+ const width = typeof mergedOptions.tooltipWidth === 'number'
175
+ ? `${mergedOptions.tooltipWidth}px`
176
+ : mergedOptions.tooltipWidth;
177
+ const baseStyle = {
178
+ width,
179
+ position: 'absolute',
180
+ zIndex: mergedOptions.zIndex,
181
+ };
182
+ switch (placement) {
183
+ case 'top':
184
+ return { ...baseStyle, bottom: '100%', left: '50%', transform: 'translateX(-50%)', marginBottom: '8px' };
185
+ case 'bottom':
186
+ return { ...baseStyle, top: '100%', left: '50%', transform: 'translateX(-50%)', marginTop: '8px' };
187
+ case 'left':
188
+ return { ...baseStyle, right: '100%', top: '50%', transform: 'translateY(-50%)', marginRight: '8px' };
189
+ case 'right':
190
+ return { ...baseStyle, left: '100%', top: '50%', transform: 'translateY(-50%)', marginLeft: '8px' };
191
+ default:
192
+ return baseStyle;
193
+ }
194
+ }, [mergedOptions.tooltipPlacement, mergedOptions.tooltipWidth, mergedOptions.zIndex]);
195
+ // Render button content
196
+ // Only show loading state on button for direct mode (modal/tooltip have their own loading)
197
+ const showButtonLoading = hook.isProcessing && mergedOptions.mode === 'direct';
198
+ const renderButtonContent = () => {
199
+ if (children) {
200
+ return children;
201
+ }
202
+ return (jsxs(Fragment, { children: [!mergedOptions.hideIcon && (jsx("span", { className: "devic-gen-button-icon", children: showButtonLoading ? (jsx("span", { className: "devic-gen-spinner" })) : (mergedOptions.icon || jsx(SparklesIcon, {})) })), !mergedOptions.hideLabel && (jsx("span", { className: "devic-gen-button-label", children: showButtonLoading ? mergedOptions.loadingLabel : mergedOptions.label }))] }));
203
+ };
204
+ // Render tool calls display
205
+ const renderToolCalls = () => {
206
+ if (!hook.isProcessing || hook.toolCalls.length === 0) {
207
+ return null;
208
+ }
209
+ return (jsx("div", { className: "devic-gen-tool-calls", children: hook.toolCalls.map((tc) => {
210
+ // Check for custom renderer
211
+ const customRenderer = mergedOptions.toolRenderers?.[tc.name];
212
+ if (customRenderer && tc.status === 'completed') {
213
+ return (jsx("div", { className: "devic-gen-tool-item devic-gen-tool-custom", children: customRenderer(tc.input, tc.output) }, tc.id));
214
+ }
215
+ // Use custom icon or default
216
+ const customIcon = mergedOptions.toolIcons?.[tc.name];
217
+ const isExecuting = tc.status === 'executing';
218
+ return (jsxs("div", { className: "devic-gen-tool-item", "data-status": tc.status, children: [jsx("span", { className: "devic-gen-tool-icon", children: isExecuting ? (jsx("span", { className: "devic-gen-spinner devic-gen-spinner-small" })) : customIcon ? (customIcon) : (jsx(CheckIcon, {})) }), jsx("span", { className: "devic-gen-tool-name", children: tc.summary || tc.name })] }, tc.id));
219
+ }) }));
220
+ };
221
+ // Render processing status
222
+ const renderProcessingStatus = () => {
223
+ if (!hook.isProcessing)
224
+ return null;
225
+ return (jsxs("div", { className: "devic-gen-processing-status", children: [jsx("span", { className: "devic-gen-spinner devic-gen-spinner-small" }), jsx("span", { className: "devic-gen-processing-text", children: hook.currentToolSummary || mergedOptions.processingMessage })] }));
226
+ };
227
+ return (jsxs("div", { ref: containerRef, className: `devic-gen-container ${containerClassName || ''}`, style: { position: 'relative', display: 'inline-block' }, children: [jsx("button", { type: "button", className: `devic-gen-button ${className || ''}`, "data-variant": mergedOptions.variant, "data-size": mergedOptions.size, "data-processing": showButtonLoading, onClick: handleButtonClick, disabled: disabled || showButtonLoading, children: renderButtonContent() }), mergedOptions.mode === 'tooltip' && hook.isOpen && (jsxs("div", { ref: tooltipRef, className: "devic-gen-tooltip", style: tooltipPositionStyle, "data-placement": mergedOptions.tooltipPlacement, children: [renderToolCalls(), hook.isProcessing && hook.toolCalls.length === 0 && renderProcessingStatus(), jsx("textarea", { ref: hook.inputRef, className: "devic-gen-input", placeholder: mergedOptions.placeholder, value: hook.inputValue, onChange: (e) => hook.setInputValue(e.target.value), onKeyDown: hook.handleKeyDown, rows: 3, disabled: hook.isProcessing }), hook.error && (jsx("div", { className: "devic-gen-error", children: hook.error.message })), jsxs("div", { className: "devic-gen-tooltip-actions", children: [jsx("button", { type: "button", className: "devic-gen-tooltip-cancel", onClick: hook.close, disabled: hook.isProcessing, children: mergedOptions.cancelText }), jsx("button", { type: "button", className: "devic-gen-tooltip-confirm", onClick: handleConfirm, disabled: hook.isProcessing || !hook.inputValue.trim(), children: hook.isProcessing ? (jsxs(Fragment, { children: [jsx("span", { className: "devic-gen-spinner devic-gen-spinner-small" }), mergedOptions.loadingLabel] })) : (mergedOptions.confirmText) })] })] })), mergedOptions.mode === 'modal' && hook.isOpen && (jsx("div", { className: "devic-gen-modal-overlay", onClick: (e) => {
228
+ if (e.target === e.currentTarget && !hook.isProcessing)
229
+ hook.close();
230
+ }, children: jsxs("div", { className: "devic-gen-modal", children: [jsxs("div", { className: "devic-gen-modal-header", children: [jsx("h3", { className: "devic-gen-modal-title", children: mergedOptions.modalTitle }), jsx("button", { type: "button", className: "devic-gen-modal-close", onClick: hook.close, "aria-label": "Close", disabled: hook.isProcessing, children: jsx(CloseIcon, {}) })] }), mergedOptions.modalDescription && (jsx("p", { className: "devic-gen-modal-description", children: mergedOptions.modalDescription })), jsxs("div", { className: "devic-gen-modal-body", children: [renderToolCalls(), hook.isProcessing && hook.toolCalls.length === 0 && renderProcessingStatus(), jsx("textarea", { ref: hook.inputRef, className: "devic-gen-input", placeholder: mergedOptions.placeholder, value: hook.inputValue, onChange: (e) => hook.setInputValue(e.target.value), onKeyDown: hook.handleKeyDown, rows: 4, disabled: hook.isProcessing }), hook.error && (jsx("div", { className: "devic-gen-error", children: hook.error.message }))] }), jsxs("div", { className: "devic-gen-modal-footer", children: [jsx("button", { type: "button", className: "devic-gen-modal-cancel", onClick: hook.close, disabled: hook.isProcessing, children: mergedOptions.cancelText }), jsx("button", { type: "button", className: "devic-gen-modal-confirm", onClick: handleConfirm, disabled: hook.isProcessing || !hook.inputValue.trim(), children: hook.isProcessing ? (jsxs(Fragment, { children: [jsx("span", { className: "devic-gen-spinner devic-gen-spinner-small" }), mergedOptions.loadingLabel] })) : (mergedOptions.confirmText) })] })] }) }))] }));
231
+ });
232
+ /**
233
+ * Default sparkles icon
234
+ */
235
+ function SparklesIcon() {
236
+ return (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("path", { d: "M10 2L11.5 8.5L18 10L11.5 11.5L10 18L8.5 11.5L2 10L8.5 8.5L10 2Z", fill: "currentColor", opacity: "0.9" }), jsx("path", { d: "M16 3L16.5 5L18.5 5.5L16.5 6L16 8L15.5 6L13.5 5.5L15.5 5L16 3Z", fill: "currentColor", opacity: "0.6" }), jsx("circle", { cx: "4", cy: "15", r: "1", fill: "currentColor", opacity: "0.4" })] }));
237
+ }
238
+ /**
239
+ * Close icon
240
+ */
241
+ function CloseIcon() {
242
+ return (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
243
+ }
244
+ /**
245
+ * Check icon for completed tool calls
246
+ */
247
+ function CheckIcon() {
248
+ return (jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "20 6 9 17 4 12" }) }));
249
+ }
250
+
251
+ export { AIGenerationButton };
252
+ //# sourceMappingURL=AIGenerationButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIGenerationButton.js","sources":["../../../../src/components/AIGenerationButton/AIGenerationButton.tsx"],"sourcesContent":["import React, { forwardRef, useImperativeHandle, useMemo, useEffect, useRef, useCallback } from 'react';\nimport { useAIGenerationButton } from './useAIGenerationButton';\nimport type {\n AIGenerationButtonProps,\n AIGenerationButtonHandle,\n AIGenerationButtonOptions,\n} from './AIGenerationButton.types';\nimport './AIGenerationButton.css';\n\nconst DEFAULT_OPTIONS: Required<AIGenerationButtonOptions> = {\n mode: 'modal',\n prompt: '',\n placeholder: 'Describe what you want to generate...',\n modalTitle: 'Generate with AI',\n modalDescription: '',\n confirmText: 'Generate',\n cancelText: 'Cancel',\n tooltipPlacement: 'top',\n tooltipWidth: 300,\n variant: 'primary',\n size: 'medium',\n icon: undefined as any,\n hideIcon: false,\n label: 'Generate with AI',\n hideLabel: false,\n loadingLabel: 'Generating...',\n color: '#3b82f6',\n backgroundColor: '',\n textColor: '',\n borderColor: '',\n borderRadius: 8,\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\",\n fontSize: 14,\n zIndex: 10000,\n animationDuration: 200,\n toolRenderers: undefined as any,\n toolIcons: undefined as any,\n processingMessage: 'Processing...',\n};\n\n/**\n * AIGenerationButton component - a button that triggers AI generation with configurable interaction modes\n *\n * @example\n * ```tsx\n * // Direct mode - sends predefined prompt on click\n * <AIGenerationButton\n * assistantId=\"my-assistant\"\n * options={{\n * mode: 'direct',\n * prompt: 'Generate a summary of the current page',\n * label: 'Summarize',\n * }}\n * onResponse={({ message }) => console.log(message.content)}\n * />\n *\n * // Modal mode - opens modal for user input\n * <AIGenerationButton\n * assistantId=\"my-assistant\"\n * options={{\n * mode: 'modal',\n * modalTitle: 'Generate Content',\n * placeholder: 'Describe what you want...',\n * }}\n * onResponse={({ message }) => setContent(message.content.message)}\n * />\n *\n * // Tooltip mode - quick inline input\n * <AIGenerationButton\n * assistantId=\"my-assistant\"\n * options={{\n * mode: 'tooltip',\n * tooltipPlacement: 'bottom',\n * }}\n * onResponse={handleGeneration}\n * />\n * ```\n */\nexport const AIGenerationButton = forwardRef<AIGenerationButtonHandle, AIGenerationButtonProps>(\n function AIGenerationButton(props, ref) {\n const {\n assistantId,\n apiKey,\n baseUrl,\n tenantId,\n tenantMetadata,\n options = {},\n modelInterfaceTools,\n onResponse,\n onBeforeSend,\n onError,\n onStart,\n onOpen,\n onClose,\n disabled,\n className,\n containerClassName,\n children,\n theme,\n } = props;\n\n const mergedOptions = useMemo(\n () => ({ ...DEFAULT_OPTIONS, ...options }),\n [options]\n );\n\n const hook = useAIGenerationButton({\n assistantId,\n apiKey,\n baseUrl,\n tenantId,\n tenantMetadata,\n options: mergedOptions,\n modelInterfaceTools,\n onResponse,\n onBeforeSend,\n onError,\n onStart,\n onOpen,\n onClose,\n disabled,\n });\n\n // Expose handle\n useImperativeHandle(ref, () => ({\n generate: hook.generate,\n open: hook.open,\n close: hook.close,\n reset: hook.reset,\n isProcessing: hook.isProcessing,\n }));\n\n // Container ref for theming\n const containerRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n\n // Apply CSS variables for theming\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const vars: [string, string | undefined][] = [\n ['--devic-gen-primary', mergedOptions.color],\n ['----devic-gen-bg', mergedOptions.backgroundColor || undefined],\n ['--devic-gen-text', mergedOptions.textColor || undefined],\n ['--devic-gen-border', mergedOptions.borderColor || undefined],\n ['--devic-gen-font-family', mergedOptions.fontFamily],\n ['--devic-gen-font-size', typeof mergedOptions.fontSize === 'number' ? `${mergedOptions.fontSize}px` : mergedOptions.fontSize],\n ['--devic-gen-radius', typeof mergedOptions.borderRadius === 'number' ? `${mergedOptions.borderRadius}px` : mergedOptions.borderRadius],\n ['--devic-gen-z-index', String(mergedOptions.zIndex)],\n ['--devic-gen-animation-duration', `${mergedOptions.animationDuration}ms`],\n ];\n\n // Apply theme from parent if provided\n if (theme) {\n if (theme.backgroundColor) vars.push(['--devic-gen-modal-bg', theme.backgroundColor]);\n if (theme.textColor) vars.push(['--devic-gen-modal-text', theme.textColor]);\n if (theme.borderColor) vars.push(['--devic-gen-modal-border', theme.borderColor]);\n if (theme.primaryColor) vars.push(['--devic-gen-primary', theme.primaryColor]);\n }\n\n for (const [name, value] of vars) {\n if (value) {\n el.style.setProperty(name, value);\n } else {\n el.style.removeProperty(name);\n }\n }\n }, [mergedOptions, theme]);\n\n // Click outside to close tooltip\n useEffect(() => {\n if (!hook.isOpen || mergedOptions.mode !== 'tooltip') return;\n\n const handleClickOutside = (e: MouseEvent) => {\n const tooltip = tooltipRef.current;\n const container = containerRef.current;\n if (\n tooltip &&\n container &&\n !tooltip.contains(e.target as Node) &&\n !container.contains(e.target as Node)\n ) {\n hook.close();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [hook.isOpen, mergedOptions.mode, hook.close]);\n\n // Handle button click\n const handleButtonClick = useCallback(() => {\n if (disabled || hook.isProcessing) return;\n\n if (mergedOptions.mode === 'direct') {\n hook.generate();\n } else {\n hook.open();\n }\n }, [disabled, hook.isProcessing, mergedOptions.mode, hook.generate, hook.open]);\n\n // Handle confirm in modal/tooltip\n const handleConfirm = useCallback(() => {\n hook.generate();\n }, [hook.generate]);\n\n // Tooltip position styles\n const tooltipPositionStyle = useMemo(() => {\n const placement = mergedOptions.tooltipPlacement;\n const width = typeof mergedOptions.tooltipWidth === 'number'\n ? `${mergedOptions.tooltipWidth}px`\n : mergedOptions.tooltipWidth;\n\n const baseStyle: React.CSSProperties = {\n width,\n position: 'absolute',\n zIndex: mergedOptions.zIndex,\n };\n\n switch (placement) {\n case 'top':\n return { ...baseStyle, bottom: '100%', left: '50%', transform: 'translateX(-50%)', marginBottom: '8px' };\n case 'bottom':\n return { ...baseStyle, top: '100%', left: '50%', transform: 'translateX(-50%)', marginTop: '8px' };\n case 'left':\n return { ...baseStyle, right: '100%', top: '50%', transform: 'translateY(-50%)', marginRight: '8px' };\n case 'right':\n return { ...baseStyle, left: '100%', top: '50%', transform: 'translateY(-50%)', marginLeft: '8px' };\n default:\n return baseStyle;\n }\n }, [mergedOptions.tooltipPlacement, mergedOptions.tooltipWidth, mergedOptions.zIndex]);\n\n // Render button content\n // Only show loading state on button for direct mode (modal/tooltip have their own loading)\n const showButtonLoading = hook.isProcessing && mergedOptions.mode === 'direct';\n\n const renderButtonContent = () => {\n if (children) {\n return children;\n }\n\n return (\n <>\n {!mergedOptions.hideIcon && (\n <span className=\"devic-gen-button-icon\">\n {showButtonLoading ? (\n <span className=\"devic-gen-spinner\" />\n ) : (\n mergedOptions.icon || <SparklesIcon />\n )}\n </span>\n )}\n {!mergedOptions.hideLabel && (\n <span className=\"devic-gen-button-label\">\n {showButtonLoading ? mergedOptions.loadingLabel : mergedOptions.label}\n </span>\n )}\n </>\n );\n };\n\n // Render tool calls display\n const renderToolCalls = () => {\n if (!hook.isProcessing || hook.toolCalls.length === 0) {\n return null;\n }\n\n return (\n <div className=\"devic-gen-tool-calls\">\n {hook.toolCalls.map((tc) => {\n // Check for custom renderer\n const customRenderer = mergedOptions.toolRenderers?.[tc.name];\n if (customRenderer && tc.status === 'completed') {\n return (\n <div key={tc.id} className=\"devic-gen-tool-item devic-gen-tool-custom\">\n {customRenderer(tc.input, tc.output)}\n </div>\n );\n }\n\n // Use custom icon or default\n const customIcon = mergedOptions.toolIcons?.[tc.name];\n const isExecuting = tc.status === 'executing';\n\n return (\n <div\n key={tc.id}\n className=\"devic-gen-tool-item\"\n data-status={tc.status}\n >\n <span className=\"devic-gen-tool-icon\">\n {isExecuting ? (\n <span className=\"devic-gen-spinner devic-gen-spinner-small\" />\n ) : customIcon ? (\n customIcon\n ) : (\n <CheckIcon />\n )}\n </span>\n <span className=\"devic-gen-tool-name\">{tc.summary || tc.name}</span>\n </div>\n );\n })}\n </div>\n );\n };\n\n // Render processing status\n const renderProcessingStatus = () => {\n if (!hook.isProcessing) return null;\n\n return (\n <div className=\"devic-gen-processing-status\">\n <span className=\"devic-gen-spinner devic-gen-spinner-small\" />\n <span className=\"devic-gen-processing-text\">\n {hook.currentToolSummary || mergedOptions.processingMessage}\n </span>\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={`devic-gen-container ${containerClassName || ''}`}\n style={{ position: 'relative', display: 'inline-block' }}\n >\n {/* Button */}\n <button\n type=\"button\"\n className={`devic-gen-button ${className || ''}`}\n data-variant={mergedOptions.variant}\n data-size={mergedOptions.size}\n data-processing={showButtonLoading}\n onClick={handleButtonClick}\n disabled={disabled || showButtonLoading}\n >\n {renderButtonContent()}\n </button>\n\n {/* Tooltip */}\n {mergedOptions.mode === 'tooltip' && hook.isOpen && (\n <div\n ref={tooltipRef}\n className=\"devic-gen-tooltip\"\n style={tooltipPositionStyle}\n data-placement={mergedOptions.tooltipPlacement}\n >\n {/* Tool calls display */}\n {renderToolCalls()}\n {/* Processing status when no tool calls yet */}\n {hook.isProcessing && hook.toolCalls.length === 0 && renderProcessingStatus()}\n <textarea\n ref={hook.inputRef}\n className=\"devic-gen-input\"\n placeholder={mergedOptions.placeholder}\n value={hook.inputValue}\n onChange={(e) => hook.setInputValue(e.target.value)}\n onKeyDown={hook.handleKeyDown}\n rows={3}\n disabled={hook.isProcessing}\n />\n {hook.error && (\n <div className=\"devic-gen-error\">{hook.error.message}</div>\n )}\n <div className=\"devic-gen-tooltip-actions\">\n <button\n type=\"button\"\n className=\"devic-gen-tooltip-cancel\"\n onClick={hook.close}\n disabled={hook.isProcessing}\n >\n {mergedOptions.cancelText}\n </button>\n <button\n type=\"button\"\n className=\"devic-gen-tooltip-confirm\"\n onClick={handleConfirm}\n disabled={hook.isProcessing || !hook.inputValue.trim()}\n >\n {hook.isProcessing ? (\n <>\n <span className=\"devic-gen-spinner devic-gen-spinner-small\" />\n {mergedOptions.loadingLabel}\n </>\n ) : (\n mergedOptions.confirmText\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Modal */}\n {mergedOptions.mode === 'modal' && hook.isOpen && (\n <div\n className=\"devic-gen-modal-overlay\"\n onClick={(e) => {\n if (e.target === e.currentTarget && !hook.isProcessing) hook.close();\n }}\n >\n <div className=\"devic-gen-modal\">\n <div className=\"devic-gen-modal-header\">\n <h3 className=\"devic-gen-modal-title\">{mergedOptions.modalTitle}</h3>\n <button\n type=\"button\"\n className=\"devic-gen-modal-close\"\n onClick={hook.close}\n aria-label=\"Close\"\n disabled={hook.isProcessing}\n >\n <CloseIcon />\n </button>\n </div>\n {mergedOptions.modalDescription && (\n <p className=\"devic-gen-modal-description\">{mergedOptions.modalDescription}</p>\n )}\n <div className=\"devic-gen-modal-body\">\n {/* Tool calls display */}\n {renderToolCalls()}\n {/* Processing status when no tool calls yet */}\n {hook.isProcessing && hook.toolCalls.length === 0 && renderProcessingStatus()}\n <textarea\n ref={hook.inputRef}\n className=\"devic-gen-input\"\n placeholder={mergedOptions.placeholder}\n value={hook.inputValue}\n onChange={(e) => hook.setInputValue(e.target.value)}\n onKeyDown={hook.handleKeyDown}\n rows={4}\n disabled={hook.isProcessing}\n />\n {hook.error && (\n <div className=\"devic-gen-error\">{hook.error.message}</div>\n )}\n </div>\n <div className=\"devic-gen-modal-footer\">\n <button\n type=\"button\"\n className=\"devic-gen-modal-cancel\"\n onClick={hook.close}\n disabled={hook.isProcessing}\n >\n {mergedOptions.cancelText}\n </button>\n <button\n type=\"button\"\n className=\"devic-gen-modal-confirm\"\n onClick={handleConfirm}\n disabled={hook.isProcessing || !hook.inputValue.trim()}\n >\n {hook.isProcessing ? (\n <>\n <span className=\"devic-gen-spinner devic-gen-spinner-small\" />\n {mergedOptions.loadingLabel}\n </>\n ) : (\n mergedOptions.confirmText\n )}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n }\n);\n\n/**\n * Default sparkles icon\n */\nfunction SparklesIcon(): JSX.Element {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10 2L11.5 8.5L18 10L11.5 11.5L10 18L8.5 11.5L2 10L8.5 8.5L10 2Z\"\n fill=\"currentColor\"\n opacity=\"0.9\"\n />\n <path\n d=\"M16 3L16.5 5L18.5 5.5L16.5 6L16 8L15.5 6L13.5 5.5L15.5 5L16 3Z\"\n fill=\"currentColor\"\n opacity=\"0.6\"\n />\n <circle cx=\"4\" cy=\"15\" r=\"1\" fill=\"currentColor\" opacity=\"0.4\" />\n </svg>\n );\n}\n\n/**\n * Close icon\n */\nfunction CloseIcon(): JSX.Element {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Check icon for completed tool calls\n */\nfunction CheckIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
@@ -0,0 +1,260 @@
1
+ import type { ChatMessage, ModelInterfaceTool } from '../../api/types';
2
+ import type { FeedbackTheme } from '../Feedback';
3
+ import type { ToolCallSummary } from '../AICommandBar/AICommandBar.types';
4
+ /**
5
+ * Interaction mode for the AIGenerationButton
6
+ * - 'direct': Sends a message immediately on button click (uses predefined prompt)
7
+ * - 'modal': Opens a modal to input a prompt before sending
8
+ * - 'tooltip': Shows a tooltip input for quick prompt entry
9
+ */
10
+ export type AIGenerationButtonMode = 'direct' | 'modal' | 'tooltip';
11
+ /**
12
+ * Result returned after generation completes
13
+ */
14
+ export interface GenerationResult {
15
+ chatUid: string;
16
+ message: ChatMessage;
17
+ toolCalls: ToolCallSummary[];
18
+ rawResponse?: any;
19
+ }
20
+ /**
21
+ * Options for the AIGenerationButton
22
+ */
23
+ export interface AIGenerationButtonOptions {
24
+ /**
25
+ * Interaction mode
26
+ * @default 'modal'
27
+ */
28
+ mode?: AIGenerationButtonMode;
29
+ /**
30
+ * Predefined prompt for 'direct' mode
31
+ * Required when mode is 'direct'
32
+ */
33
+ prompt?: string;
34
+ /**
35
+ * Placeholder text for the input (modal and tooltip modes)
36
+ * @default 'Describe what you want to generate...'
37
+ */
38
+ placeholder?: string;
39
+ /**
40
+ * Modal title (modal mode only)
41
+ * @default 'Generate with AI'
42
+ */
43
+ modalTitle?: string;
44
+ /**
45
+ * Modal description (modal mode only)
46
+ */
47
+ modalDescription?: string;
48
+ /**
49
+ * Confirm button text
50
+ * @default 'Generate'
51
+ */
52
+ confirmText?: string;
53
+ /**
54
+ * Cancel button text
55
+ * @default 'Cancel'
56
+ */
57
+ cancelText?: string;
58
+ /**
59
+ * Tooltip placement (tooltip mode only)
60
+ * @default 'top'
61
+ */
62
+ tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
63
+ /**
64
+ * Tooltip width
65
+ * @default 300
66
+ */
67
+ tooltipWidth?: number | string;
68
+ /**
69
+ * Button variant
70
+ * @default 'primary'
71
+ */
72
+ variant?: 'primary' | 'secondary' | 'ghost' | 'outline';
73
+ /**
74
+ * Button size
75
+ * @default 'medium'
76
+ */
77
+ size?: 'small' | 'medium' | 'large';
78
+ /**
79
+ * Custom icon for the button (replaces default sparkles icon)
80
+ */
81
+ icon?: React.ReactNode;
82
+ /**
83
+ * Hide the icon
84
+ * @default false
85
+ */
86
+ hideIcon?: boolean;
87
+ /**
88
+ * Button label
89
+ * @default 'Generate with AI'
90
+ */
91
+ label?: string;
92
+ /**
93
+ * Hide the label (icon only button)
94
+ * @default false
95
+ */
96
+ hideLabel?: boolean;
97
+ /**
98
+ * Loading label shown during processing
99
+ * @default 'Generating...'
100
+ */
101
+ loadingLabel?: string;
102
+ /**
103
+ * Primary color
104
+ */
105
+ color?: string;
106
+ /**
107
+ * Background color
108
+ */
109
+ backgroundColor?: string;
110
+ /**
111
+ * Text color
112
+ */
113
+ textColor?: string;
114
+ /**
115
+ * Border color
116
+ */
117
+ borderColor?: string;
118
+ /**
119
+ * Border radius
120
+ * @default 8
121
+ */
122
+ borderRadius?: number | string;
123
+ /**
124
+ * Font family
125
+ */
126
+ fontFamily?: string;
127
+ /**
128
+ * Font size
129
+ */
130
+ fontSize?: number | string;
131
+ /**
132
+ * Z-index for modal/tooltip overlays
133
+ * @default 10000
134
+ */
135
+ zIndex?: number;
136
+ /**
137
+ * Animation duration in ms
138
+ * @default 200
139
+ */
140
+ animationDuration?: number;
141
+ /**
142
+ * Custom renderers for tool calls by tool name.
143
+ * When a completed tool has a matching renderer, it replaces the default summary line.
144
+ */
145
+ toolRenderers?: Record<string, (input: any, output: any) => React.ReactNode>;
146
+ /**
147
+ * Custom icons for completed tool calls by tool name.
148
+ * Replaces the default check icon.
149
+ */
150
+ toolIcons?: Record<string, React.ReactNode>;
151
+ /**
152
+ * Message shown while processing (before any tools are called)
153
+ * @default 'Processing...'
154
+ */
155
+ processingMessage?: string;
156
+ }
157
+ /**
158
+ * Handle for programmatically controlling the AIGenerationButton
159
+ */
160
+ export interface AIGenerationButtonHandle {
161
+ /**
162
+ * Trigger generation programmatically
163
+ * @param prompt Optional prompt (overrides predefined prompt in direct mode)
164
+ */
165
+ generate: (prompt?: string) => Promise<GenerationResult | null>;
166
+ /**
167
+ * Open the modal/tooltip (for modal and tooltip modes)
168
+ */
169
+ open: () => void;
170
+ /**
171
+ * Close the modal/tooltip
172
+ */
173
+ close: () => void;
174
+ /**
175
+ * Reset the component state
176
+ */
177
+ reset: () => void;
178
+ /**
179
+ * Check if currently processing
180
+ */
181
+ isProcessing: boolean;
182
+ }
183
+ /**
184
+ * Props for the AIGenerationButton component
185
+ */
186
+ export interface AIGenerationButtonProps {
187
+ /**
188
+ * Assistant identifier
189
+ */
190
+ assistantId: string;
191
+ /**
192
+ * API key (overrides DevicContext)
193
+ */
194
+ apiKey?: string;
195
+ /**
196
+ * Base URL (overrides DevicContext)
197
+ */
198
+ baseUrl?: string;
199
+ /**
200
+ * Tenant ID
201
+ */
202
+ tenantId?: string;
203
+ /**
204
+ * Tenant metadata
205
+ */
206
+ tenantMetadata?: Record<string, any>;
207
+ /**
208
+ * Display and behavior options
209
+ */
210
+ options?: AIGenerationButtonOptions;
211
+ /**
212
+ * Client-side tools for model interface protocol
213
+ */
214
+ modelInterfaceTools?: ModelInterfaceTool[];
215
+ /**
216
+ * Callback when generation completes successfully
217
+ */
218
+ onResponse?: (result: GenerationResult) => void;
219
+ /**
220
+ * Callback before sending the message (can modify the prompt)
221
+ * Return the modified prompt or undefined to use the original
222
+ */
223
+ onBeforeSend?: (prompt: string) => string | undefined | Promise<string | undefined>;
224
+ /**
225
+ * Callback when an error occurs
226
+ */
227
+ onError?: (error: Error) => void;
228
+ /**
229
+ * Callback when processing starts
230
+ */
231
+ onStart?: () => void;
232
+ /**
233
+ * Callback when modal/tooltip opens
234
+ */
235
+ onOpen?: () => void;
236
+ /**
237
+ * Callback when modal/tooltip closes
238
+ */
239
+ onClose?: () => void;
240
+ /**
241
+ * Whether the button is disabled
242
+ */
243
+ disabled?: boolean;
244
+ /**
245
+ * Additional CSS class for the button
246
+ */
247
+ className?: string;
248
+ /**
249
+ * Additional CSS class for the modal/tooltip container
250
+ */
251
+ containerClassName?: string;
252
+ /**
253
+ * Custom button content (replaces default button rendering)
254
+ */
255
+ children?: React.ReactNode;
256
+ /**
257
+ * Theme for the modal/tooltip (inherited from parent component styling)
258
+ */
259
+ theme?: FeedbackTheme;
260
+ }
@@ -0,0 +1,3 @@
1
+ export { AIGenerationButton } from './AIGenerationButton';
2
+ export { useAIGenerationButton } from './useAIGenerationButton';
3
+ export type { AIGenerationButtonProps, AIGenerationButtonOptions, AIGenerationButtonHandle, AIGenerationButtonMode, GenerationResult, } from './AIGenerationButton.types';
@@ -0,0 +1,40 @@
1
+ import type { ModelInterfaceTool } from '../../api/types';
2
+ import type { AIGenerationButtonOptions, GenerationResult } from './AIGenerationButton.types';
3
+ import type { ToolCallSummary } from '../AICommandBar/AICommandBar.types';
4
+ export interface UseAIGenerationButtonOptions {
5
+ assistantId: string;
6
+ apiKey?: string;
7
+ baseUrl?: string;
8
+ tenantId?: string;
9
+ tenantMetadata?: Record<string, any>;
10
+ options?: AIGenerationButtonOptions;
11
+ modelInterfaceTools?: ModelInterfaceTool[];
12
+ onResponse?: (result: GenerationResult) => void;
13
+ onBeforeSend?: (prompt: string) => string | undefined | Promise<string | undefined>;
14
+ onError?: (error: Error) => void;
15
+ onStart?: () => void;
16
+ onOpen?: () => void;
17
+ onClose?: () => void;
18
+ disabled?: boolean;
19
+ }
20
+ export interface UseAIGenerationButtonResult {
21
+ isOpen: boolean;
22
+ isProcessing: boolean;
23
+ inputValue: string;
24
+ setInputValue: (value: string) => void;
25
+ error: Error | null;
26
+ result: GenerationResult | null;
27
+ toolCalls: ToolCallSummary[];
28
+ currentToolSummary: string | null;
29
+ inputRef: React.RefObject<HTMLTextAreaElement>;
30
+ open: () => void;
31
+ close: () => void;
32
+ toggle: () => void;
33
+ generate: (prompt?: string) => Promise<GenerationResult | null>;
34
+ reset: () => void;
35
+ handleKeyDown: (e: React.KeyboardEvent) => void;
36
+ }
37
+ /**
38
+ * Hook for managing AIGenerationButton state and behavior
39
+ */
40
+ export declare function useAIGenerationButton(options: UseAIGenerationButtonOptions): UseAIGenerationButtonResult;