@admin-layout/tailwind-ui 12.2.4-alpha.16 → 12.2.4-alpha.21
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/lib/components/InputToolBar/InputToolBar.d.ts +3 -4
- package/lib/components/InputToolBar/InputToolBar.d.ts.map +1 -1
- package/lib/components/InputToolBar/InputToolBar.js +242 -45
- package/lib/components/InputToolBar/InputToolBar.js.map +1 -1
- package/lib/components/InputToolBar/defaults.d.ts +3 -2
- package/lib/components/InputToolBar/defaults.d.ts.map +1 -1
- package/lib/components/InputToolBar/defaults.js +14 -6
- package/lib/components/InputToolBar/defaults.js.map +1 -1
- package/lib/components/InputToolBar/index.d.ts +1 -1
- package/lib/components/InputToolBar/index.d.ts.map +1 -1
- package/lib/components/InputToolBar/types.d.ts +110 -20
- package/lib/components/InputToolBar/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { InputToolBarProps } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* InputToolBar –
|
|
5
|
-
*
|
|
6
|
-
* Layout: left (mode toggles + template pill), flexible middle, right (attach, capture, mic/send).
|
|
4
|
+
* InputToolBar – UI only. Renders toolbar and optional built-in textarea from props.
|
|
5
|
+
* All data (leftItems, rightItems, templateButton, inputConfig, micSendButton) and behavior (onClick, onChange, etc.) come from props.
|
|
7
6
|
*/
|
|
8
|
-
export declare function InputToolBar({ className, leftItems, rightItems, templateButton, leftCustomRender, rightCustomRender, micSendButton, children, }: InputToolBarProps): React.JSX.Element;
|
|
7
|
+
export declare function InputToolBar({ className, classNames, inputConfig, topContent, leftItems: leftItemsProp, rightItems: rightItemsProp, templateButton, templateModalConfig, templateModalRender, projectSettingsModalOpen, onProjectSettingsModalClose, projectSettingsModalRender, leftCustomRender, rightCustomRender, micSendButton, children, onContainerClick, }: InputToolBarProps): React.JSX.Element;
|
|
9
8
|
export default InputToolBar;
|
|
10
9
|
//# sourceMappingURL=InputToolBar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputToolBar.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/InputToolBar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InputToolBar.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/InputToolBar.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,KAAK,EAER,iBAAiB,EAQpB,MAAM,SAAS,CAAC;AAwcjB;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EACzB,SAAS,EACT,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,cAAc,EAC1B,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,gBAAgB,GACnB,EAAE,iBAAiB,qBAwFnB;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Lightbulb,Zap,Search,Mic,Paperclip,Camera,
|
|
1
|
+
import {Lightbulb,Zap,Search,Mic,Paperclip,Image,Camera,WandSparkles,Settings,X,Layout,Check,StopCircle,ArrowUpRight}from'lucide-react';import React__default,{useState,useMemo}from'react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';const iconSize = 'h-3.5 w-3.5';
|
|
2
2
|
const iconSizeRight = 'h-4 w-4';
|
|
3
3
|
const defaultLeftIconMap = {
|
|
4
4
|
search: React__default.createElement(Search, {
|
|
@@ -13,7 +13,10 @@ const defaultLeftIconMap = {
|
|
|
13
13
|
template: null // template is rendered as pill, not in icon group
|
|
14
14
|
};
|
|
15
15
|
const defaultRightIconMap = {
|
|
16
|
-
|
|
16
|
+
projectSettings: React__default.createElement(Settings, {
|
|
17
|
+
className: iconSizeRight
|
|
18
|
+
}),
|
|
19
|
+
tag: React__default.createElement(WandSparkles, {
|
|
17
20
|
className: iconSizeRight
|
|
18
21
|
}),
|
|
19
22
|
chip: React__default.createElement("svg", {
|
|
@@ -56,6 +59,9 @@ const defaultRightIconMap = {
|
|
|
56
59
|
camera: React__default.createElement(Camera, {
|
|
57
60
|
className: iconSizeRight
|
|
58
61
|
}),
|
|
62
|
+
image: React__default.createElement(Image, {
|
|
63
|
+
className: iconSizeRight
|
|
64
|
+
}),
|
|
59
65
|
attach: React__default.createElement(Paperclip, {
|
|
60
66
|
className: iconSizeRight
|
|
61
67
|
}),
|
|
@@ -67,18 +73,26 @@ function MicSendButton({
|
|
|
67
73
|
hasContent,
|
|
68
74
|
onSend,
|
|
69
75
|
onMic,
|
|
70
|
-
disabled
|
|
76
|
+
disabled,
|
|
77
|
+
isLoading,
|
|
78
|
+
onStop,
|
|
79
|
+
className
|
|
71
80
|
}) {
|
|
72
|
-
const
|
|
73
|
-
const
|
|
81
|
+
const isStop = isLoading === true;
|
|
82
|
+
const isSend = !isStop && hasContent;
|
|
83
|
+
const base = 'inline-flex h-7 w-7 items-center justify-center rounded-2xl transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary border border-primary';
|
|
84
|
+
const handleClick = isStop ? onStop : isSend ? onSend : onMic;
|
|
85
|
+
const label = isStop ? 'Stop' : isSend ? 'Send' : 'Start voice input';
|
|
74
86
|
return React__default.createElement("button", {
|
|
75
87
|
type: "button",
|
|
76
|
-
"aria-label":
|
|
77
|
-
title:
|
|
78
|
-
onClick:
|
|
79
|
-
disabled: disabled,
|
|
80
|
-
className: base
|
|
81
|
-
},
|
|
88
|
+
"aria-label": label,
|
|
89
|
+
title: label,
|
|
90
|
+
onClick: handleClick,
|
|
91
|
+
disabled: disabled && !isStop,
|
|
92
|
+
className: cn(base, className)
|
|
93
|
+
}, isStop ? React__default.createElement(StopCircle, {
|
|
94
|
+
className: iconSizeRight
|
|
95
|
+
}) : isSend ? React__default.createElement(ArrowUpRight, {
|
|
82
96
|
className: iconSizeRight
|
|
83
97
|
}) : React__default.createElement(Mic, {
|
|
84
98
|
className: iconSizeRight
|
|
@@ -87,33 +101,43 @@ function MicSendButton({
|
|
|
87
101
|
function ToolbarIconButton({
|
|
88
102
|
item,
|
|
89
103
|
getDefaultIcon,
|
|
90
|
-
isLeftGroup
|
|
104
|
+
isLeftGroup,
|
|
105
|
+
classNames
|
|
91
106
|
}) {
|
|
92
107
|
if (item.enabled === false) return null;
|
|
93
108
|
const icon = item.customButton ?? item.icon ?? getDefaultIcon(item.id);
|
|
94
109
|
if (item.customButton) {
|
|
95
110
|
return React__default.createElement(React__default.Fragment, null, item.customButton);
|
|
96
111
|
}
|
|
112
|
+
const isDisabled = item.disabled === true || item.loading === true;
|
|
97
113
|
const isActive = item.active === true;
|
|
98
114
|
const base = 'inline-flex h-7 w-7 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:opacity-50 disabled:pointer-events-none';
|
|
99
|
-
const leftVariant = isActive ? 'rounded-full border border-primary bg-primary text-primary-foreground hover:bg-primary/90' : 'rounded-full border border-
|
|
100
|
-
const
|
|
115
|
+
const leftVariant = isActive ? cn('rounded-full border border-primary bg-primary text-primary-foreground hover:bg-primary/90', classNames?.leftButtonActive) : cn('rounded-full border border-border bg-muted/50 text-foreground hover:border-primary hover:bg-muted hover:text-primary', classNames?.leftButtonInactive);
|
|
116
|
+
const rightVariantDisabled = cn('rounded-2xl text-muted-foreground/50 cursor-not-allowed disabled:pointer-events-auto', classNames?.rightButtonDisabled);
|
|
117
|
+
const rightVariantActive = cn('rounded-2xl text-primary hover:bg-secondary border border-transparent', classNames?.rightButtonActive);
|
|
118
|
+
const rightVariantDefault = cn('rounded-2xl text-muted-foreground hover:bg-secondary/70 active:bg-secondary border border-transparent', classNames?.rightButton);
|
|
119
|
+
const rightVariant = isDisabled ? rightVariantDisabled : isActive ? rightVariantActive : rightVariantDefault;
|
|
101
120
|
return React__default.createElement("button", {
|
|
102
121
|
type: "button",
|
|
103
122
|
"aria-label": item.label,
|
|
104
123
|
title: item.label,
|
|
105
124
|
onClick: item.onClick,
|
|
125
|
+
disabled: isDisabled,
|
|
106
126
|
className: cn(base, isLeftGroup ? leftVariant : rightVariant)
|
|
107
|
-
},
|
|
127
|
+
}, item.loading ? React__default.createElement("div", {
|
|
128
|
+
className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent",
|
|
129
|
+
"aria-hidden": true
|
|
130
|
+
}) : icon);
|
|
108
131
|
}
|
|
109
132
|
function LeftSection({
|
|
110
133
|
leftItems,
|
|
111
134
|
templateButton,
|
|
112
|
-
leftCustomRender
|
|
135
|
+
leftCustomRender,
|
|
136
|
+
classNames
|
|
113
137
|
}) {
|
|
114
138
|
if (leftCustomRender != null) {
|
|
115
139
|
return React__default.createElement("div", {
|
|
116
|
-
className:
|
|
140
|
+
className: cn('flex items-center gap-2', classNames?.leftGroup)
|
|
117
141
|
}, leftCustomRender);
|
|
118
142
|
}
|
|
119
143
|
const left = leftItems ?? [];
|
|
@@ -121,7 +145,7 @@ function LeftSection({
|
|
|
121
145
|
const hasLeft = left.length > 0 || hasTemplate;
|
|
122
146
|
if (!hasLeft) return null;
|
|
123
147
|
return React__default.createElement("div", {
|
|
124
|
-
className:
|
|
148
|
+
className: cn('flex items-center gap-2', classNames?.leftGroup)
|
|
125
149
|
}, left.length > 0 && React__default.createElement("div", {
|
|
126
150
|
className: "flex items-center gap-1 rounded-full bg-secondary px-2 py-1"
|
|
127
151
|
}, left.map((item, index) => React__default.createElement(React__default.Fragment, {
|
|
@@ -129,36 +153,66 @@ function LeftSection({
|
|
|
129
153
|
}, React__default.createElement(ToolbarIconButton, {
|
|
130
154
|
item: item,
|
|
131
155
|
getDefaultIcon: id => defaultLeftIconMap[id] ?? null,
|
|
132
|
-
isLeftGroup: true
|
|
156
|
+
isLeftGroup: true,
|
|
157
|
+
classNames: classNames
|
|
133
158
|
}), index < left.length - 1 && React__default.createElement("span", {
|
|
134
159
|
"aria-hidden": "true",
|
|
135
160
|
className: "mx-1 h-5 w-px bg-border/70"
|
|
136
161
|
})))), hasTemplate && React__default.createElement(TemplatePill, {
|
|
137
162
|
label: templateButton.label,
|
|
138
163
|
count: templateButton.count,
|
|
164
|
+
selectedLabel: templateButton.selectedLabel,
|
|
139
165
|
onClick: templateButton.onClick,
|
|
140
|
-
|
|
166
|
+
onClearTemplate: templateButton.onClearTemplate,
|
|
167
|
+
disabled: templateButton.disabled,
|
|
168
|
+
classNames: classNames
|
|
141
169
|
}));
|
|
142
170
|
}
|
|
143
171
|
function TemplatePill({
|
|
144
172
|
label,
|
|
145
173
|
count,
|
|
174
|
+
selectedLabel,
|
|
146
175
|
onClick,
|
|
147
|
-
|
|
176
|
+
onClearTemplate,
|
|
177
|
+
disabled,
|
|
178
|
+
classNames
|
|
148
179
|
}) {
|
|
180
|
+
if (selectedLabel) {
|
|
181
|
+
return React__default.createElement("div", {
|
|
182
|
+
className: cn('flex items-center gap-1 px-2 py-1 rounded-full bg-primary/10 text-primary text-xs font-medium border border-primary/20', classNames?.templatePillSelected)
|
|
183
|
+
}, React__default.createElement("span", {
|
|
184
|
+
className: "truncate max-w-[120px]",
|
|
185
|
+
title: selectedLabel
|
|
186
|
+
}, selectedLabel), React__default.createElement("button", {
|
|
187
|
+
type: "button",
|
|
188
|
+
onClick: onClearTemplate,
|
|
189
|
+
className: "ml-1 hover:bg-primary/20 rounded-full p-0.5 transition-colors",
|
|
190
|
+
"aria-label": "Remove template",
|
|
191
|
+
disabled: disabled
|
|
192
|
+
}, React__default.createElement(X, {
|
|
193
|
+
className: "h-3 w-3"
|
|
194
|
+
})), React__default.createElement("button", {
|
|
195
|
+
type: "button",
|
|
196
|
+
onClick: onClick,
|
|
197
|
+
className: "ml-1 hover:bg-primary/20 rounded-full p-0.5 transition-colors text-[10px]",
|
|
198
|
+
"aria-label": "Change template",
|
|
199
|
+
disabled: disabled
|
|
200
|
+
}, "\u25BC"));
|
|
201
|
+
}
|
|
149
202
|
const text = count != null && count > 0 ? `${label} (${count})` : label;
|
|
150
203
|
return React__default.createElement("button", {
|
|
151
204
|
type: "button",
|
|
152
205
|
onClick: onClick,
|
|
153
206
|
disabled: disabled,
|
|
154
|
-
className: cn('flex items-center gap-1 rounded-full border border-border bg-
|
|
207
|
+
className: cn('flex items-center gap-1 rounded-full border border-border bg-muted/50 px-2 py-1 text-xs font-medium text-foreground transition-colors hover:border-primary hover:bg-primary/5', disabled && 'opacity-50 cursor-not-allowed' || '', classNames?.templatePill),
|
|
155
208
|
"aria-label": "Select template"
|
|
156
209
|
}, text);
|
|
157
210
|
}
|
|
158
211
|
function RightSection({
|
|
159
212
|
rightItems,
|
|
160
213
|
rightCustomRender,
|
|
161
|
-
micSendButton
|
|
214
|
+
micSendButton,
|
|
215
|
+
classNames
|
|
162
216
|
}) {
|
|
163
217
|
if (rightCustomRender != null) {
|
|
164
218
|
return React__default.createElement("div", {
|
|
@@ -170,49 +224,191 @@ function RightSection({
|
|
|
170
224
|
const hasRight = filteredRight.length > 0 || micSendButton != null;
|
|
171
225
|
if (!hasRight) return null;
|
|
172
226
|
return React__default.createElement("div", {
|
|
173
|
-
className: "flex flex-wrap items-center gap-
|
|
227
|
+
className: "flex flex-wrap items-center gap-2 text-muted-foreground"
|
|
174
228
|
}, filteredRight.map(item => React__default.createElement(ToolbarIconButton, {
|
|
175
229
|
key: item.id,
|
|
176
230
|
item: item,
|
|
177
|
-
getDefaultIcon: id => defaultRightIconMap[id] ?? null
|
|
231
|
+
getDefaultIcon: id => defaultRightIconMap[id] ?? null,
|
|
232
|
+
classNames: classNames
|
|
178
233
|
})), micSendButton != null && React__default.createElement(MicSendButton, {
|
|
179
234
|
hasContent: micSendButton.hasContent,
|
|
180
235
|
onSend: micSendButton.onSend,
|
|
181
236
|
onMic: micSendButton.onMic,
|
|
182
|
-
disabled: micSendButton.disabled
|
|
237
|
+
disabled: micSendButton.disabled,
|
|
238
|
+
isLoading: micSendButton.isLoading,
|
|
239
|
+
onStop: micSendButton.onStop,
|
|
240
|
+
className: classNames?.micSendButton
|
|
183
241
|
}));
|
|
184
242
|
}
|
|
243
|
+
const defaultTextareaClassName = 'w-full outline-none border-none ring-0 focus:outline-none focus:ring-0 bg-transparent text-base text-foreground placeholder:text-muted-foreground disabled:opacity-50 resize-none overflow-y-auto max-h-[30vh] [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]';
|
|
244
|
+
function DefaultTemplateModal({
|
|
245
|
+
isOpen,
|
|
246
|
+
onClose,
|
|
247
|
+
templates,
|
|
248
|
+
selectedId,
|
|
249
|
+
onSelect,
|
|
250
|
+
suggestedId,
|
|
251
|
+
title = 'Choose Template'
|
|
252
|
+
}) {
|
|
253
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
254
|
+
const [categoryFilter, setCategoryFilter] = useState('All');
|
|
255
|
+
const categories = useMemo(() => {
|
|
256
|
+
const cats = new Set(templates.map(t => t.category || 'Other'));
|
|
257
|
+
return ['All', ...Array.from(cats).sort()];
|
|
258
|
+
}, [templates]);
|
|
259
|
+
const filteredTemplates = useMemo(() => {
|
|
260
|
+
return templates.filter(template => {
|
|
261
|
+
const searchLower = searchQuery.toLowerCase();
|
|
262
|
+
const matchesSearch = !searchQuery || template.label.toLowerCase().includes(searchLower) || (template.description || '').toLowerCase().includes(searchLower);
|
|
263
|
+
const matchesCategory = categoryFilter === 'All' || template.category === categoryFilter;
|
|
264
|
+
return matchesSearch && matchesCategory;
|
|
265
|
+
});
|
|
266
|
+
}, [templates, searchQuery, categoryFilter]);
|
|
267
|
+
if (!isOpen) return null;
|
|
268
|
+
function handleBackdropClick(e) {
|
|
269
|
+
if (e.target === e.currentTarget) onClose();
|
|
270
|
+
}
|
|
271
|
+
return React__default.createElement("div", {
|
|
272
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm p-4",
|
|
273
|
+
onClick: handleBackdropClick
|
|
274
|
+
}, React__default.createElement("div", {
|
|
275
|
+
className: "bg-card w-full max-w-[720px] max-h-[80vh] rounded-xl flex flex-col overflow-hidden border border-border shadow-xl"
|
|
276
|
+
}, React__default.createElement("div", {
|
|
277
|
+
className: "h-12 px-4 border-b border-border flex items-center justify-between shrink-0"
|
|
278
|
+
}, React__default.createElement("h2", {
|
|
279
|
+
className: "text-sm font-semibold text-foreground"
|
|
280
|
+
}, title), React__default.createElement("button", {
|
|
281
|
+
type: "button",
|
|
282
|
+
onClick: onClose,
|
|
283
|
+
className: "p-1.5 rounded-lg hover:bg-accent text-muted-foreground transition-colors focus:outline-none focus:ring-2 focus:ring-ring",
|
|
284
|
+
"aria-label": "Close"
|
|
285
|
+
}, React__default.createElement(X, {
|
|
286
|
+
className: "h-4 w-4"
|
|
287
|
+
}))), React__default.createElement("div", {
|
|
288
|
+
className: "p-4 border-b border-border space-y-3"
|
|
289
|
+
}, React__default.createElement("div", {
|
|
290
|
+
className: "relative"
|
|
291
|
+
}, React__default.createElement(Search, {
|
|
292
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"
|
|
293
|
+
}), React__default.createElement("input", {
|
|
294
|
+
type: "text",
|
|
295
|
+
placeholder: "Search templates...",
|
|
296
|
+
value: searchQuery,
|
|
297
|
+
onChange: e => setSearchQuery(e.target.value),
|
|
298
|
+
className: "w-full pl-9 pr-3 py-2 border border-border rounded-lg bg-muted text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
299
|
+
})), React__default.createElement("div", {
|
|
300
|
+
className: "flex gap-1.5 flex-wrap"
|
|
301
|
+
}, categories.map(category => React__default.createElement("button", {
|
|
302
|
+
key: category,
|
|
303
|
+
type: "button",
|
|
304
|
+
onClick: () => setCategoryFilter(category),
|
|
305
|
+
className: cn('px-2.5 py-1 rounded-md text-xs font-medium transition-colors border', categoryFilter === category ? 'bg-primary/10 text-primary border-primary/20' : 'bg-card text-muted-foreground border-border hover:bg-muted hover:text-foreground')
|
|
306
|
+
}, category)))), React__default.createElement("div", {
|
|
307
|
+
className: "flex-1 overflow-y-auto p-4 min-h-0"
|
|
308
|
+
}, React__default.createElement("div", {
|
|
309
|
+
className: "grid grid-cols-1 sm:grid-cols-2 gap-3"
|
|
310
|
+
}, filteredTemplates.map(template => {
|
|
311
|
+
const isSelected = selectedId === template.id;
|
|
312
|
+
const isSuggested = suggestedId === template.id;
|
|
313
|
+
return React__default.createElement("button", {
|
|
314
|
+
key: template.id,
|
|
315
|
+
type: "button",
|
|
316
|
+
onClick: () => {
|
|
317
|
+
onSelect(template.id);
|
|
318
|
+
onClose();
|
|
319
|
+
},
|
|
320
|
+
className: cn('text-left p-3 rounded-lg border-2 transition-all', isSelected ? 'border-primary bg-primary/10 ring-2 ring-primary/20' : 'border-border hover:border-primary/50 hover:bg-muted/50', isSuggested && !isSelected && 'border-primary/30 bg-primary/5')
|
|
321
|
+
}, React__default.createElement("div", {
|
|
322
|
+
className: "flex items-start gap-2"
|
|
323
|
+
}, React__default.createElement("div", {
|
|
324
|
+
className: cn('p-1.5 rounded-md flex-shrink-0', isSelected ? 'bg-primary' : isSuggested ? 'bg-primary/20' : 'bg-secondary')
|
|
325
|
+
}, React__default.createElement(Layout, {
|
|
326
|
+
className: cn('h-3.5 w-3.5', isSelected ? 'text-primary-foreground' : isSuggested ? 'text-primary' : 'text-foreground')
|
|
327
|
+
})), React__default.createElement("div", {
|
|
328
|
+
className: "min-w-0 flex-1"
|
|
329
|
+
}, React__default.createElement("div", {
|
|
330
|
+
className: "flex items-center gap-1.5"
|
|
331
|
+
}, React__default.createElement("span", {
|
|
332
|
+
className: "font-medium text-sm text-foreground truncate"
|
|
333
|
+
}, template.label), isSelected && React__default.createElement(Check, {
|
|
334
|
+
className: "h-3.5 w-3.5 text-primary flex-shrink-0"
|
|
335
|
+
})), template.description && React__default.createElement("p", {
|
|
336
|
+
className: "text-xs text-muted-foreground mt-0.5 line-clamp-2"
|
|
337
|
+
}, template.description))));
|
|
338
|
+
})), filteredTemplates.length === 0 && React__default.createElement("div", {
|
|
339
|
+
className: "flex flex-col items-center justify-center py-12 text-center"
|
|
340
|
+
}, React__default.createElement(Search, {
|
|
341
|
+
className: "h-10 w-10 text-muted-foreground mb-3"
|
|
342
|
+
}), React__default.createElement("p", {
|
|
343
|
+
className: "text-sm font-medium text-foreground"
|
|
344
|
+
}, "No templates found"), React__default.createElement("p", {
|
|
345
|
+
className: "text-xs text-muted-foreground mt-1"
|
|
346
|
+
}, "Try adjusting search or filters")))));
|
|
347
|
+
}
|
|
185
348
|
/**
|
|
186
|
-
* InputToolBar –
|
|
187
|
-
*
|
|
188
|
-
* Layout: left (mode toggles + template pill), flexible middle, right (attach, capture, mic/send).
|
|
349
|
+
* InputToolBar – UI only. Renders toolbar and optional built-in textarea from props.
|
|
350
|
+
* All data (leftItems, rightItems, templateButton, inputConfig, micSendButton) and behavior (onClick, onChange, etc.) come from props.
|
|
189
351
|
*/
|
|
190
352
|
function InputToolBar({
|
|
191
353
|
className,
|
|
192
|
-
|
|
193
|
-
|
|
354
|
+
classNames,
|
|
355
|
+
inputConfig,
|
|
356
|
+
topContent,
|
|
357
|
+
leftItems: leftItemsProp,
|
|
358
|
+
rightItems: rightItemsProp,
|
|
194
359
|
templateButton,
|
|
360
|
+
templateModalConfig,
|
|
361
|
+
templateModalRender,
|
|
362
|
+
projectSettingsModalOpen,
|
|
363
|
+
onProjectSettingsModalClose,
|
|
364
|
+
projectSettingsModalRender,
|
|
195
365
|
leftCustomRender,
|
|
196
366
|
rightCustomRender,
|
|
197
367
|
micSendButton,
|
|
198
|
-
children
|
|
368
|
+
children,
|
|
369
|
+
onContainerClick
|
|
199
370
|
}) {
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
371
|
+
const leftItems = leftItemsProp ?? [];
|
|
372
|
+
const rightItems = rightItemsProp ?? [];
|
|
373
|
+
const hasInputContent = inputConfig != null || children != null;
|
|
374
|
+
const effectiveTopContent = inputConfig != null ? topContent : null;
|
|
375
|
+
const templateModal = templateModalConfig != null && templateModalConfig.isOpen ? templateModalRender != null ? templateModalRender(templateModalConfig) : React__default.createElement(DefaultTemplateModal, templateModalConfig) : null;
|
|
376
|
+
const projectSettingsModal = projectSettingsModalOpen === true && onProjectSettingsModalClose != null && projectSettingsModalRender != null ? projectSettingsModalRender({
|
|
377
|
+
onClose: onProjectSettingsModalClose
|
|
378
|
+
}) : null;
|
|
379
|
+
return React__default.createElement(React__default.Fragment, null, templateModal, projectSettingsModal, React__default.createElement("section", {
|
|
380
|
+
className: cn('w-full overflow-visible rounded-[24px] border border-border/70 bg-card shadow-md', hasInputContent && 'cursor-text', classNames?.container, className),
|
|
381
|
+
onClick: hasInputContent ? onContainerClick : undefined,
|
|
382
|
+
role: hasInputContent ? 'presentation' : undefined
|
|
203
383
|
}, React__default.createElement("div", {
|
|
204
|
-
className: cn('flex px-3 py-2',
|
|
205
|
-
},
|
|
206
|
-
className: "min-w-0 flex-1"
|
|
207
|
-
},
|
|
208
|
-
|
|
384
|
+
className: cn('flex px-3 py-2', hasInputContent ? 'flex-col gap-2' : 'flex-wrap items-center gap-3')
|
|
385
|
+
}, hasInputContent && React__default.createElement("div", {
|
|
386
|
+
className: "min-w-0 flex-1 flex flex-col gap-2"
|
|
387
|
+
}, effectiveTopContent, inputConfig != null ? React__default.createElement(React__default.Fragment, null, React__default.createElement("label", {
|
|
388
|
+
htmlFor: inputConfig.id ?? 'input-toolbar-input',
|
|
389
|
+
className: "sr-only"
|
|
390
|
+
}, inputConfig.placeholder ?? 'Message'), React__default.createElement("textarea", {
|
|
391
|
+
ref: inputConfig.inputRef,
|
|
392
|
+
id: inputConfig.id ?? 'input-toolbar-input',
|
|
393
|
+
name: inputConfig.name ?? 'query',
|
|
394
|
+
value: inputConfig.value,
|
|
395
|
+
onChange: inputConfig.onChange,
|
|
396
|
+
onKeyDown: inputConfig.onKeyDown,
|
|
397
|
+
onPaste: inputConfig.onPaste,
|
|
398
|
+
placeholder: inputConfig.placeholder ?? 'Ask anything...',
|
|
399
|
+
disabled: inputConfig.disabled,
|
|
400
|
+
rows: 1,
|
|
401
|
+
className: defaultTextareaClassName
|
|
402
|
+
})) : children), React__default.createElement("div", {
|
|
403
|
+
className: cn('flex flex-wrap items-center gap-3', hasInputContent && 'pt-2')
|
|
209
404
|
}, React__default.createElement("div", {
|
|
210
|
-
className: cn('flex items-center gap-2',
|
|
405
|
+
className: cn('flex items-center gap-2', hasInputContent && 'mb-2')
|
|
211
406
|
}, React__default.createElement(LeftSection, {
|
|
212
407
|
leftItems: leftItems,
|
|
213
408
|
templateButton: templateButton,
|
|
214
|
-
leftCustomRender: leftCustomRender
|
|
215
|
-
|
|
409
|
+
leftCustomRender: leftCustomRender,
|
|
410
|
+
classNames: classNames
|
|
411
|
+
})), !hasInputContent && React__default.createElement("div", {
|
|
216
412
|
className: "min-w-0 flex-1",
|
|
217
413
|
"aria-hidden": true
|
|
218
414
|
}), React__default.createElement("div", {
|
|
@@ -220,6 +416,7 @@ function InputToolBar({
|
|
|
220
416
|
}, React__default.createElement(RightSection, {
|
|
221
417
|
rightItems: rightItems,
|
|
222
418
|
rightCustomRender: rightCustomRender,
|
|
223
|
-
micSendButton: micSendButton
|
|
224
|
-
|
|
419
|
+
micSendButton: micSendButton,
|
|
420
|
+
classNames: classNames
|
|
421
|
+
}))))));
|
|
225
422
|
}export{InputToolBar,InputToolBar as default};//# sourceMappingURL=InputToolBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputToolBar.js","sources":["../../../src/components/InputToolBar/InputToolBar.tsx"],"sourcesContent":[null],"names":["React"],"mappings":"
|
|
1
|
+
{"version":3,"file":"InputToolBar.js","sources":["../../../src/components/InputToolBar/InputToolBar.tsx"],"sourcesContent":[null],"names":["React"],"mappings":";;AAueG,MAAA,kBAAA,GAAA;AACH,EAAA,MAAA,EAAAA,cAAA,CAAA,oBAA4B,EAAC;AA4G7B,IAAA,SAAA,EAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,8 +7,9 @@ export type RightItemOverrides = Partial<Record<RightToolbarItemId, Partial<Omit
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function getDefaultLeftItems(overrides?: LeftItemOverrides): ToolbarItemConfig<LeftToolbarItemId>[];
|
|
9
9
|
/**
|
|
10
|
-
* Build default right toolbar items (tag, chip, camera, attach, mic).
|
|
11
|
-
*
|
|
10
|
+
* Build default right toolbar items (projectSettings, tag, chip, camera, image, attach, mic).
|
|
11
|
+
* projectSettings is disabled by default; pass projectSettings: { enabled: true, onClick } to show.
|
|
12
|
+
* Override label, enabled, disabled, loading, active, onClick, icon, customButton per id.
|
|
12
13
|
*/
|
|
13
14
|
export declare function getDefaultRightItems(overrides?: RightItemOverrides): ToolbarItemConfig<RightToolbarItemId>[];
|
|
14
15
|
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAsBxF,MAAM,MAAM,iBAAiB,GAAG,OAAO,CACnC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CACvF,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACpC,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CACzF,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,EAAE,CAezG;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,EAAE,CAgB5G"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const DEFAULT_LEFT_IDS = ['search', 'zap', 'lightbulb'];
|
|
2
|
-
const DEFAULT_RIGHT_IDS = ['tag', 'chip', 'camera', 'attach', 'mic'];
|
|
2
|
+
const DEFAULT_RIGHT_IDS = ['projectSettings', 'tag', 'chip', 'camera', 'image', 'attach', 'mic'];
|
|
3
3
|
const DEFAULT_LEFT_LABELS = {
|
|
4
4
|
search: 'Chat mode',
|
|
5
5
|
zap: 'Deep Search',
|
|
@@ -7,9 +7,11 @@ const DEFAULT_LEFT_LABELS = {
|
|
|
7
7
|
template: 'Template'
|
|
8
8
|
};
|
|
9
9
|
const DEFAULT_RIGHT_LABELS = {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
projectSettings: 'Project settings',
|
|
11
|
+
tag: 'Enhance your prompt with AI',
|
|
12
|
+
chip: 'Configure chat model',
|
|
12
13
|
camera: 'Capture image',
|
|
14
|
+
image: 'Insert image',
|
|
13
15
|
attach: 'Attach file',
|
|
14
16
|
mic: 'Mic / Send'
|
|
15
17
|
};
|
|
@@ -24,6 +26,8 @@ function getDefaultLeftItems(overrides) {
|
|
|
24
26
|
id,
|
|
25
27
|
label: o?.label ?? DEFAULT_LEFT_LABELS[id],
|
|
26
28
|
enabled: o?.enabled ?? true,
|
|
29
|
+
disabled: o?.disabled,
|
|
30
|
+
loading: o?.loading,
|
|
27
31
|
active: o?.active,
|
|
28
32
|
onClick: o?.onClick,
|
|
29
33
|
icon: o?.icon,
|
|
@@ -32,16 +36,20 @@ function getDefaultLeftItems(overrides) {
|
|
|
32
36
|
});
|
|
33
37
|
}
|
|
34
38
|
/**
|
|
35
|
-
* Build default right toolbar items (tag, chip, camera, attach, mic).
|
|
36
|
-
*
|
|
39
|
+
* Build default right toolbar items (projectSettings, tag, chip, camera, image, attach, mic).
|
|
40
|
+
* projectSettings is disabled by default; pass projectSettings: { enabled: true, onClick } to show.
|
|
41
|
+
* Override label, enabled, disabled, loading, active, onClick, icon, customButton per id.
|
|
37
42
|
*/
|
|
38
43
|
function getDefaultRightItems(overrides) {
|
|
39
44
|
return DEFAULT_RIGHT_IDS.map(id => {
|
|
40
45
|
const o = overrides?.[id];
|
|
46
|
+
const defaultEnabled = id === 'projectSettings' ? false : true;
|
|
41
47
|
return {
|
|
42
48
|
id,
|
|
43
49
|
label: o?.label ?? DEFAULT_RIGHT_LABELS[id],
|
|
44
|
-
enabled: o?.enabled ??
|
|
50
|
+
enabled: o?.enabled ?? defaultEnabled,
|
|
51
|
+
disabled: o?.disabled,
|
|
52
|
+
loading: o?.loading,
|
|
45
53
|
active: o?.active,
|
|
46
54
|
onClick: o?.onClick,
|
|
47
55
|
icon: o?.icon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sources":["../../../src/components/InputToolBar/defaults.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA,MAAA,gBAAc,GAAA,CAAA,QAAmB,EAAA,KAAA,EAAA,WAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"defaults.js","sources":["../../../src/components/InputToolBar/defaults.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA,MAAA,gBAAc,GAAA,CAAA,QAAmB,EAAA,KAAA,EAAA,WAAoB,CAAA;AAsBrD,MAAM,sCACF,EAAM,KAAC,EAAA,MAAA,EAAA,QAAmB,EAAA,OAAY,EAAC,QAAA,EAAA,KAAA,CAAiB;AAE5D,MAAM;AAIN,EAAA,MAAA,EAAA,WAAA;;;AAGG,EAAA,QAAA,EAAA;AACH,CAAA;AAiBA,MAAA,oBAAA,GAAA;;;;AAIG,EAAA,MAAA,EAAA,eAAA;AACH,EAAA,KAAA,EAAA,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { InputToolBar } from './InputToolBar';
|
|
2
2
|
export { getDefaultLeftItems, getDefaultRightItems } from './defaults';
|
|
3
|
-
export type { InputToolBarProps, LeftToolbarItemId, MicSendButtonConfig, RightToolbarItemId, TemplateButtonConfig, ToolbarItemConfig, } from './types';
|
|
3
|
+
export type { InputConfig, InputToolBarClassNames, InputToolBarProps, LeftToolbarItemId, MicSendButtonConfig, ProjectSettingsModalRender, ProjectSettingsModalRenderProps, RightToolbarItemId, TemplateButtonConfig, TemplateModalConfig, TemplateModalItem, TemplateModalRender, ToolbarItemConfig, } from './types';
|
|
4
4
|
export type { LeftItemOverrides, RightItemOverrides } from './defaults';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvE,YAAY,EACR,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,GACpB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvE,YAAY,EACR,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,61 +1,151 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
/** Data-only config for built-in textarea. When provided, InputToolBar renders the textarea with default styling. */
|
|
3
|
+
export interface InputConfig {
|
|
4
|
+
value: string;
|
|
5
|
+
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
|
|
9
|
+
onPaste?: (e: React.ClipboardEvent<HTMLTextAreaElement>) => void;
|
|
10
|
+
id?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
/** Optional ref for the textarea (e.g. for focus / height adjustment) */
|
|
13
|
+
inputRef?: React.RefObject<HTMLTextAreaElement | null>;
|
|
14
|
+
}
|
|
2
15
|
/** Predefined toolbar action ids for left section (mode toggles, template) */
|
|
3
16
|
export type LeftToolbarItemId = 'search' | 'zap' | 'lightbulb' | 'template';
|
|
4
|
-
/** Predefined toolbar action ids for right section
|
|
5
|
-
export type RightToolbarItemId = 'tag' | 'chip' | 'camera' | 'attach' | 'mic';
|
|
17
|
+
/** Predefined toolbar action ids for right section. projectSettings = first item, disabled by default; enable via overrides. tag = enhance prompt, chip = configure model; both support enabled/disable and custom label, icon, onClick for app-specific use. */
|
|
18
|
+
export type RightToolbarItemId = 'projectSettings' | 'tag' | 'chip' | 'camera' | 'image' | 'attach' | 'mic';
|
|
6
19
|
/** Single toolbar button/item configuration */
|
|
7
20
|
export interface ToolbarItemConfig<TId extends string = string> {
|
|
8
21
|
/** Unique id for the item (used for enable/disable and callbacks) */
|
|
9
22
|
id: TId;
|
|
10
23
|
/** Icon (React node) or custom content for the button */
|
|
11
24
|
icon?: ReactNode;
|
|
12
|
-
/** Accessible label / title */
|
|
25
|
+
/** Accessible label / title (e.g. "Enhance your prompt with AI" when enabled, "Type something to enhance" when disabled) */
|
|
13
26
|
label: string;
|
|
14
|
-
/** Whether the item is enabled (default true) */
|
|
27
|
+
/** Whether the item is enabled (default true). When false, item is hidden. */
|
|
15
28
|
enabled?: boolean;
|
|
16
|
-
/**
|
|
29
|
+
/** When true, button is visible but disabled (greyed out, not clickable). Use for e.g. "enhance" when input is empty. */
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
/** When true, show loading spinner and treat as disabled. Use for e.g. "enhance" while request is in flight. */
|
|
32
|
+
loading?: boolean;
|
|
33
|
+
/** Whether the item is in active/selected state (e.g. primary color + hover style for right items) */
|
|
17
34
|
active?: boolean;
|
|
18
35
|
/** Click handler */
|
|
19
36
|
onClick?: () => void;
|
|
20
37
|
/** Optional custom button element; when set, icon/label are ignored and this is rendered */
|
|
21
38
|
customButton?: ReactNode;
|
|
22
39
|
}
|
|
23
|
-
/** When provided, the rightmost button shows Send
|
|
40
|
+
/** When provided, the rightmost button shows Stop when loading, Send when hasContent, else Mic. Replaces any "mic" item in rightItems. */
|
|
24
41
|
export interface MicSendButtonConfig {
|
|
25
|
-
/** True when input has content – show send icon; otherwise show mic icon */
|
|
42
|
+
/** True when input has content – show send icon; otherwise show mic icon (unless loading). */
|
|
26
43
|
hasContent: boolean;
|
|
27
44
|
onSend: () => void;
|
|
28
45
|
onMic: () => void;
|
|
29
46
|
disabled?: boolean;
|
|
47
|
+
/** When true, show stop icon and call onStop on click. */
|
|
48
|
+
isLoading?: boolean;
|
|
49
|
+
onStop?: () => void;
|
|
30
50
|
}
|
|
31
|
-
/** Configuration for the optional "+ Template (N)"
|
|
51
|
+
/** Configuration for the optional template pill: either "+ Template (N)" or selected template name with remove/change */
|
|
32
52
|
export interface TemplateButtonConfig {
|
|
33
|
-
/** Button label prefix, e.g. "+ Template" */
|
|
53
|
+
/** Button label prefix when no selection, e.g. "+ Template" */
|
|
34
54
|
label: string;
|
|
35
|
-
/** Count to show in parentheses, e.g. (1) */
|
|
55
|
+
/** Count to show in parentheses when no selection, e.g. (1) */
|
|
36
56
|
count?: number;
|
|
37
|
-
/**
|
|
57
|
+
/** When set, show selected template pill (name + remove + change) instead of "+ Template (N)" */
|
|
58
|
+
selectedLabel?: string | null;
|
|
59
|
+
/** Open template modal / change template (used for main pill click and for "change" when selected) */
|
|
38
60
|
onClick?: () => void;
|
|
61
|
+
/** When template is selected, called when user clicks remove (X) */
|
|
62
|
+
onClearTemplate?: () => void;
|
|
39
63
|
/** Disabled state */
|
|
40
64
|
disabled?: boolean;
|
|
41
65
|
}
|
|
42
|
-
/**
|
|
66
|
+
/** Minimal template item for the default template selection modal. Map your app's template type to this shape. */
|
|
67
|
+
export interface TemplateModalItem {
|
|
68
|
+
id: string;
|
|
69
|
+
label: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
category?: string;
|
|
72
|
+
}
|
|
73
|
+
/** Config for the template selection modal. Pass data from props; InputToolBar renders default modal or custom via templateModalRender. */
|
|
74
|
+
export interface TemplateModalConfig {
|
|
75
|
+
isOpen: boolean;
|
|
76
|
+
onClose: () => void;
|
|
77
|
+
templates: TemplateModalItem[];
|
|
78
|
+
selectedId: string | null;
|
|
79
|
+
onSelect: (id: string) => void;
|
|
80
|
+
suggestedId?: string | null;
|
|
81
|
+
title?: string;
|
|
82
|
+
}
|
|
83
|
+
/** Render prop for custom template modal. When provided, used instead of the default modal UI. */
|
|
84
|
+
export type TemplateModalRender = (config: TemplateModalConfig) => ReactNode;
|
|
85
|
+
/** Props passed to the project settings modal render function. Values are updated via the parent's callback (e.g. onModelConfigChange). */
|
|
86
|
+
export interface ProjectSettingsModalRenderProps {
|
|
87
|
+
onClose: () => void;
|
|
88
|
+
}
|
|
89
|
+
/** Render prop for project settings modal content. When projectSettings is clicked, parent opens modal (sets projectSettingsModalOpen). Modal content receives onClose; parent passes config and onChange from props so values update via parent. */
|
|
90
|
+
export type ProjectSettingsModalRender = (props: ProjectSettingsModalRenderProps) => ReactNode;
|
|
91
|
+
/** Optional class overrides for InputToolBar sections. Use to adapt to light/dark theme or custom styling. */
|
|
92
|
+
export interface InputToolBarClassNames {
|
|
93
|
+
/** Root section (default: rounded border bg-card shadow) */
|
|
94
|
+
container?: string;
|
|
95
|
+
/** Left toolbar group wrapper */
|
|
96
|
+
leftGroup?: string;
|
|
97
|
+
/** Template pill when no selection (e.g. "+ Template (N)") */
|
|
98
|
+
templatePill?: string;
|
|
99
|
+
/** Template pill when selected/suggested (name + remove + change) */
|
|
100
|
+
templatePillSelected?: string;
|
|
101
|
+
/** Left mode buttons – active state (filled) */
|
|
102
|
+
leftButtonActive?: string;
|
|
103
|
+
/** Left mode buttons – inactive state (outline) */
|
|
104
|
+
leftButtonInactive?: string;
|
|
105
|
+
/** Right toolbar buttons – default state */
|
|
106
|
+
rightButton?: string;
|
|
107
|
+
/** Right toolbar buttons – active state */
|
|
108
|
+
rightButtonActive?: string;
|
|
109
|
+
/** Right toolbar buttons – disabled state */
|
|
110
|
+
rightButtonDisabled?: string;
|
|
111
|
+
/** Mic/Send button (primary action) */
|
|
112
|
+
micSendButton?: string;
|
|
113
|
+
}
|
|
114
|
+
/** Props for the InputToolBar container. UI only: all data and behavior come from props. */
|
|
43
115
|
export interface InputToolBarProps {
|
|
44
|
-
/** Optional class name for the toolbar container */
|
|
116
|
+
/** Optional class name for the toolbar container (merged with container in classNames) */
|
|
45
117
|
className?: string;
|
|
46
|
-
/**
|
|
118
|
+
/** Optional class overrides for toolbar sections (works in both light and dark theme) */
|
|
119
|
+
classNames?: InputToolBarClassNames;
|
|
120
|
+
/** When provided, InputToolBar renders a built-in textarea; pass only data (value, onChange, etc.). */
|
|
121
|
+
inputConfig?: InputConfig | null;
|
|
122
|
+
/** Optional content above the input when inputConfig is set (e.g. panels, banners). */
|
|
123
|
+
topContent?: ReactNode;
|
|
124
|
+
/** Left section: items and template pill. All data (active, onClick, etc.) from parent. */
|
|
47
125
|
leftItems?: Array<ToolbarItemConfig<LeftToolbarItemId>>;
|
|
48
|
-
/** Right section:
|
|
126
|
+
/** Right section: items. All data (onClick, etc.) from parent. */
|
|
49
127
|
rightItems?: Array<ToolbarItemConfig<RightToolbarItemId>>;
|
|
50
|
-
/** Optional template pill
|
|
128
|
+
/** Optional template pill (e.g. "+ Template (1)"). Data from parent. */
|
|
51
129
|
templateButton?: TemplateButtonConfig | null;
|
|
52
|
-
/**
|
|
130
|
+
/** Template selection modal: pass data from props. When set, InputToolBar renders the modal (default UI or custom). */
|
|
131
|
+
templateModalConfig?: TemplateModalConfig | null;
|
|
132
|
+
/** When provided, used instead of the default template modal UI. Receives templateModalConfig. */
|
|
133
|
+
templateModalRender?: TemplateModalRender | null;
|
|
134
|
+
/** Custom content for the left section (overrides leftItems) */
|
|
53
135
|
leftCustomRender?: ReactNode;
|
|
54
|
-
/** Custom content
|
|
136
|
+
/** Custom content for the right section (overrides rightItems and micSendButton) */
|
|
55
137
|
rightCustomRender?: ReactNode;
|
|
56
|
-
/** When set,
|
|
138
|
+
/** When set, rightmost button: Stop/Send/Mic; all data and handlers from parent. */
|
|
57
139
|
micSendButton?: MicSendButtonConfig | null;
|
|
58
|
-
/**
|
|
140
|
+
/** When true, the project settings modal (from projectSettingsModalRender) is shown. Set by parent when projectSettings is clicked. */
|
|
141
|
+
projectSettingsModalOpen?: boolean;
|
|
142
|
+
/** Called when the project settings modal should close (e.g. overlay click or close button). */
|
|
143
|
+
onProjectSettingsModalClose?: () => void;
|
|
144
|
+
/** Renders the project settings modal content (e.g. Configuration / Other Settings / Secret tabs). Parent passes config and onChange so values update via parent (same pattern as ModelConfigPanel). */
|
|
145
|
+
projectSettingsModalRender?: ProjectSettingsModalRender | null;
|
|
146
|
+
/** Optional content in the middle when not using inputConfig */
|
|
59
147
|
children?: ReactNode;
|
|
148
|
+
/** Click on container (e.g. to focus input) */
|
|
149
|
+
onContainerClick?: (e: React.MouseEvent) => void;
|
|
60
150
|
}
|
|
61
151
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,8EAA8E;AAC9E,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;AAE5E,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/InputToolBar/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@admin-layout/tailwind-ui",
|
|
3
|
-
"version": "12.2.4-alpha.
|
|
3
|
+
"version": "12.2.4-alpha.21",
|
|
4
4
|
"description": "Sample core for higher packages to depend on",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"typescript": {
|
|
91
91
|
"definition": "lib/index.d.ts"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "c17eccf18dc6a1f3f764c448ed2c65261dd240b8"
|
|
94
94
|
}
|