myoperator-ui 0.0.211 → 0.0.212
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +459 -130
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -252,7 +252,7 @@ function looksLikeTailwindClasses(str) {
|
|
|
252
252
|
return true;
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
|
-
const singleWordUtilities = /^(flex|grid|block|inline|contents|flow-root|hidden|invisible|visible|static|fixed|absolute|relative|sticky|isolate|isolation-auto|overflow-auto|overflow-hidden|overflow-clip|overflow-visible|overflow-scroll|overflow-x-auto|overflow-y-auto|overscroll-auto|overscroll-contain|overscroll-none|truncate|antialiased|subpixel-antialiased|italic|not-italic|underline|overline|line-through|no-underline|uppercase|lowercase|capitalize|normal-case|ordinal|slashed-zero|lining-nums|oldstyle-nums|proportional-nums|tabular-nums|diagonal-fractions|stacked-fractions|sr-only|not-sr-only|resize|resize-none|resize-x|resize-y|snap-start|snap-end|snap-center|snap-align-none|snap-normal|snap-always|touch-auto|touch-none|touch-pan-x|touch-pan-left|touch-pan-right|touch-pan-y|touch-pan-up|touch-pan-down|touch-pinch-zoom|touch-manipulation|select-none|select-text|select-all|select-auto|will-change-auto|will-change-scroll|will-change-contents|will-change-transform|grow|grow-0|shrink|shrink-0|transform|transform-cpu|transform-gpu|transform-none|transition|transition-none|transition-all|transition-colors|transition-opacity|transition-shadow|transition-transform|animate-none|animate-spin|animate-ping|animate-pulse|animate-bounce)$/;
|
|
255
|
+
const singleWordUtilities = /^(flex|inline-flex|grid|inline-grid|block|inline-block|inline-table|inline|contents|flow-root|hidden|invisible|visible|static|fixed|absolute|relative|sticky|isolate|isolation-auto|overflow-auto|overflow-hidden|overflow-clip|overflow-visible|overflow-scroll|overflow-x-auto|overflow-y-auto|overscroll-auto|overscroll-contain|overscroll-none|truncate|antialiased|subpixel-antialiased|italic|not-italic|underline|overline|line-through|no-underline|uppercase|lowercase|capitalize|normal-case|ordinal|slashed-zero|lining-nums|oldstyle-nums|proportional-nums|tabular-nums|diagonal-fractions|stacked-fractions|sr-only|not-sr-only|resize|resize-none|resize-x|resize-y|snap-start|snap-end|snap-center|snap-align-none|snap-normal|snap-always|touch-auto|touch-none|touch-pan-x|touch-pan-left|touch-pan-right|touch-pan-y|touch-pan-up|touch-pan-down|touch-pinch-zoom|touch-manipulation|select-none|select-text|select-all|select-auto|will-change-auto|will-change-scroll|will-change-contents|will-change-transform|grow|grow-0|shrink|shrink-0|transform|transform-cpu|transform-gpu|transform-none|transition|transition-none|transition-all|transition-colors|transition-opacity|transition-shadow|transition-transform|animate-none|animate-spin|animate-ping|animate-pulse|animate-bounce)$/;
|
|
256
256
|
if (!str.includes(" ") && singleWordUtilities.test(str)) return true;
|
|
257
257
|
if (/^(@[a-z0-9-]+\/)?[a-z][a-z0-9-]*$/.test(str) && !str.includes(" ")) return false;
|
|
258
258
|
const words = str.split(/\s+/);
|
|
@@ -12833,7 +12833,7 @@ export type { BrandIconProps } from "./icon";
|
|
|
12833
12833
|
},
|
|
12834
12834
|
"bots": {
|
|
12835
12835
|
name: "bots",
|
|
12836
|
-
description: "AI Bot management components \u2014 BotList page, BotCard, and CreateBotModal",
|
|
12836
|
+
description: "AI Bot management components \u2014 BotList page, BotListHeader, BotListSearch, BotListCreateCard, BotListGrid, BotCard, and CreateBotModal",
|
|
12837
12837
|
category: "custom",
|
|
12838
12838
|
dependencies: [
|
|
12839
12839
|
"clsx",
|
|
@@ -12841,8 +12841,10 @@ export type { BrandIconProps } from "./icon";
|
|
|
12841
12841
|
"lucide-react"
|
|
12842
12842
|
],
|
|
12843
12843
|
internalDependencies: [
|
|
12844
|
+
"badge",
|
|
12844
12845
|
"button",
|
|
12845
|
-
"dialog"
|
|
12846
|
+
"dialog",
|
|
12847
|
+
"dropdown-menu"
|
|
12846
12848
|
],
|
|
12847
12849
|
isMultiFile: true,
|
|
12848
12850
|
directory: "bots",
|
|
@@ -12851,114 +12853,127 @@ export type { BrandIconProps } from "./icon";
|
|
|
12851
12853
|
{
|
|
12852
12854
|
name: "bot-card.tsx",
|
|
12853
12855
|
content: prefixTailwindClasses(`import * as React from "react";
|
|
12854
|
-
import { MessageSquare, Phone
|
|
12856
|
+
import { MessageSquare, Phone } from "lucide-react";
|
|
12855
12857
|
import { cn } from "../../../lib/utils";
|
|
12856
|
-
import {
|
|
12857
|
-
DropdownMenu,
|
|
12858
|
-
DropdownMenuTrigger,
|
|
12859
|
-
DropdownMenuContent,
|
|
12860
|
-
DropdownMenuItem,
|
|
12861
|
-
DropdownMenuSeparator,
|
|
12862
|
-
} from "../dropdown-menu";
|
|
12863
12858
|
import { Badge } from "../badge";
|
|
12864
|
-
import
|
|
12859
|
+
import { BotListAction } from "./bot-list-action";
|
|
12860
|
+
import type { Bot, BotCardProps, BotType } from "./types";
|
|
12865
12861
|
|
|
12866
|
-
const
|
|
12862
|
+
const DEFAULT_TYPE_LABELS: Record<BotType, string> = {
|
|
12867
12863
|
chatbot: "Chatbot",
|
|
12868
12864
|
voicebot: "Voicebot",
|
|
12869
12865
|
};
|
|
12870
12866
|
|
|
12867
|
+
function getTypeLabel(
|
|
12868
|
+
bot: Bot,
|
|
12869
|
+
typeLabels?: Partial<Record<BotType, string>>
|
|
12870
|
+
): string {
|
|
12871
|
+
if (bot.typeLabel) return bot.typeLabel;
|
|
12872
|
+
const custom = typeLabels?.[bot.type];
|
|
12873
|
+
if (custom) return custom;
|
|
12874
|
+
return DEFAULT_TYPE_LABELS[bot.type];
|
|
12875
|
+
}
|
|
12876
|
+
|
|
12877
|
+
/**
|
|
12878
|
+
* Single card component for both Chatbot and Voicebot.
|
|
12879
|
+
* All displayed data (icon, badge, name, count, last published) comes from the \`bot\` prop.
|
|
12880
|
+
* Set bot.type to "chatbot" or "voicebot"; no separate card components needed.
|
|
12881
|
+
*/
|
|
12871
12882
|
export const BotCard = React.forwardRef<HTMLDivElement, BotCardProps>(
|
|
12872
|
-
({ bot, onEdit, onPublish, onDelete, className }, ref) => {
|
|
12883
|
+
({ bot, typeLabels, onEdit, onPublish, onDelete, className, ...props }, ref) => {
|
|
12884
|
+
const typeLabel = getTypeLabel(bot, typeLabels);
|
|
12873
12885
|
const isChatbot = bot.type === "chatbot";
|
|
12874
12886
|
|
|
12887
|
+
const handleCardClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
12888
|
+
if (onEdit && !(e.target as HTMLElement).closest("[data-bot-card-action]")) {
|
|
12889
|
+
onEdit(bot.id);
|
|
12890
|
+
}
|
|
12891
|
+
};
|
|
12892
|
+
|
|
12893
|
+
const handleCardKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
12894
|
+
if (onEdit && !(e.target as HTMLElement).closest("[data-bot-card-action]")) {
|
|
12895
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
12896
|
+
e.preventDefault();
|
|
12897
|
+
onEdit(bot.id);
|
|
12898
|
+
}
|
|
12899
|
+
}
|
|
12900
|
+
};
|
|
12901
|
+
|
|
12875
12902
|
return (
|
|
12876
12903
|
<div
|
|
12877
12904
|
ref={ref}
|
|
12905
|
+
role={onEdit ? "button" : undefined}
|
|
12906
|
+
tabIndex={onEdit ? 0 : undefined}
|
|
12907
|
+
aria-label={onEdit ? \`Edit \${bot.name}\` : undefined}
|
|
12908
|
+
onClick={onEdit ? handleCardClick : undefined}
|
|
12909
|
+
onKeyDown={onEdit ? handleCardKeyDown : undefined}
|
|
12878
12910
|
className={cn(
|
|
12879
|
-
"relative bg-semantic-bg-primary border border-semantic-border-layout rounded-[5px]",
|
|
12880
|
-
"shadow-[0px_4px_15.1px_0px_rgba(0,0,0,0.06)] p-
|
|
12911
|
+
"relative bg-semantic-bg-primary border border-semantic-border-layout rounded-[5px] min-w-0 max-w-full overflow-hidden flex flex-col",
|
|
12912
|
+
"shadow-[0px_4px_15.1px_0px_rgba(0,0,0,0.06)] p-3 sm:p-4 md:p-5",
|
|
12913
|
+
onEdit && "cursor-pointer",
|
|
12881
12914
|
className
|
|
12882
12915
|
)}
|
|
12916
|
+
{...props}
|
|
12883
12917
|
>
|
|
12884
12918
|
{/* Top row: icon + badge + menu */}
|
|
12885
|
-
<div className="flex items-start justify-between mb-4">
|
|
12886
|
-
<div className="flex items-center justify-center size-[38px] rounded-full bg-semantic-info-surface shrink-0">
|
|
12919
|
+
<div className="flex items-start justify-between gap-2 mb-3 sm:mb-4 min-w-0">
|
|
12920
|
+
<div className="flex items-center justify-center size-8 sm:size-[38px] rounded-full bg-semantic-info-surface shrink-0">
|
|
12887
12921
|
{isChatbot ? (
|
|
12888
|
-
<MessageSquare className="size-5 text-semantic-text-secondary" />
|
|
12922
|
+
<MessageSquare className="size-4 sm:size-5 text-semantic-text-secondary" />
|
|
12889
12923
|
) : (
|
|
12890
|
-
<Phone className="size-5 text-semantic-text-secondary" />
|
|
12924
|
+
<Phone className="size-4 sm:size-5 text-semantic-text-secondary" />
|
|
12891
12925
|
)}
|
|
12892
12926
|
</div>
|
|
12893
|
-
<div className="flex items-center gap-2">
|
|
12894
|
-
<Badge variant="outline" className="text-xs font-normal">
|
|
12895
|
-
{
|
|
12927
|
+
<div className="flex items-center gap-1.5 sm:gap-2 min-w-0 shrink-0">
|
|
12928
|
+
<Badge variant="outline" className="text-xs font-normal shrink-0">
|
|
12929
|
+
{typeLabel}
|
|
12896
12930
|
</Badge>
|
|
12897
12931
|
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
>
|
|
12906
|
-
<MoreVertical className="size-4" />
|
|
12907
|
-
</button>
|
|
12908
|
-
</DropdownMenuTrigger>
|
|
12909
|
-
<DropdownMenuContent align="end" className="min-w-[160px]">
|
|
12910
|
-
<DropdownMenuItem
|
|
12911
|
-
className="flex items-center gap-3 px-4 py-3 text-sm cursor-pointer"
|
|
12912
|
-
onClick={() => onEdit?.(bot.id)}
|
|
12913
|
-
>
|
|
12914
|
-
<Pencil className="size-4 text-semantic-text-muted shrink-0" />
|
|
12915
|
-
<span>Edit</span>
|
|
12916
|
-
</DropdownMenuItem>
|
|
12917
|
-
<DropdownMenuItem
|
|
12918
|
-
className="flex items-center gap-3 px-4 py-3 text-sm cursor-pointer"
|
|
12919
|
-
onClick={() => onPublish?.(bot.id)}
|
|
12920
|
-
>
|
|
12921
|
-
<Play className="size-4 text-semantic-text-muted shrink-0" />
|
|
12922
|
-
<span>Publish</span>
|
|
12923
|
-
</DropdownMenuItem>
|
|
12924
|
-
<DropdownMenuSeparator />
|
|
12925
|
-
<DropdownMenuItem
|
|
12926
|
-
className="flex items-center gap-3 px-4 py-3 text-sm cursor-pointer text-semantic-error-primary focus:text-semantic-error-primary focus:bg-semantic-error-surface"
|
|
12927
|
-
onClick={() => onDelete?.(bot.id)}
|
|
12928
|
-
>
|
|
12929
|
-
<Trash2 className="size-4 shrink-0" />
|
|
12930
|
-
<span>Delete</span>
|
|
12931
|
-
</DropdownMenuItem>
|
|
12932
|
-
</DropdownMenuContent>
|
|
12933
|
-
</DropdownMenu>
|
|
12932
|
+
<span data-bot-card-action className="inline-flex" onClick={(e) => e.stopPropagation()}>
|
|
12933
|
+
<BotListAction
|
|
12934
|
+
align="end"
|
|
12935
|
+
onEdit={() => onEdit?.(bot.id)}
|
|
12936
|
+
onDelete={() => onDelete?.(bot.id)}
|
|
12937
|
+
/>
|
|
12938
|
+
</span>
|
|
12934
12939
|
</div>
|
|
12935
12940
|
</div>
|
|
12936
12941
|
|
|
12937
12942
|
{/* Bot name */}
|
|
12938
|
-
<h3 className="m-0 text-base font-normal text-semantic-text-primary truncate mb-1">
|
|
12943
|
+
<h3 className="m-0 text-sm sm:text-base font-normal text-semantic-text-primary truncate mb-1 min-w-0">
|
|
12939
12944
|
{bot.name}
|
|
12940
12945
|
</h3>
|
|
12941
12946
|
|
|
12942
12947
|
{/* Conversations count */}
|
|
12943
|
-
<p className="m-0 text-sm text-semantic-text-muted mb-4">
|
|
12948
|
+
<p className="m-0 text-xs sm:text-sm text-semantic-text-muted mb-3 sm:mb-4">
|
|
12944
12949
|
{bot.conversationCount.toLocaleString()} Conversations
|
|
12945
12950
|
</p>
|
|
12946
12951
|
|
|
12947
12952
|
{/* Divider */}
|
|
12948
|
-
<div className="border-t border-semantic-border-layout mb-3 mt-auto" />
|
|
12953
|
+
<div className="border-t border-semantic-border-layout mb-2 sm:mb-3 mt-auto" />
|
|
12949
12954
|
|
|
12950
12955
|
{/* Last published */}
|
|
12951
|
-
<div className="flex flex-col gap-1">
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12956
|
+
<div className="flex flex-col gap-0.5 sm:gap-1 min-w-0">
|
|
12957
|
+
{bot.status === "draft" ? (
|
|
12958
|
+
<p className="m-0 text-xs font-normal text-semantic-text-secondary uppercase tracking-[0.048px] flex items-center justify-start gap-5">
|
|
12959
|
+
Last Published
|
|
12960
|
+
<span className="text-xs font-normal text-semantic-error-primary flex items-center gap-1.5 shrink-0">
|
|
12961
|
+
<span className="size-1.5 rounded-full bg-semantic-error-primary shrink-0" aria-hidden />
|
|
12962
|
+
Unpublished changes
|
|
12963
|
+
</span>
|
|
12958
12964
|
</p>
|
|
12959
12965
|
) : (
|
|
12960
|
-
<
|
|
12966
|
+
<span className="text-xs font-normal text-semantic-text-secondary uppercase tracking-[0.048px]">
|
|
12967
|
+
Last Published
|
|
12968
|
+
</span>
|
|
12961
12969
|
)}
|
|
12970
|
+
{bot.lastPublishedBy && bot.lastPublishedDate ? (
|
|
12971
|
+
<p className="m-0 text-xs sm:text-sm text-semantic-text-muted truncate">
|
|
12972
|
+
{bot.lastPublishedBy} | {bot.lastPublishedDate}
|
|
12973
|
+
</p>
|
|
12974
|
+
) : bot.status !== "draft" ? (
|
|
12975
|
+
<p className="m-0 text-xs sm:text-sm text-semantic-text-muted">\u2014</p>
|
|
12976
|
+
) : null}
|
|
12962
12977
|
</div>
|
|
12963
12978
|
</div>
|
|
12964
12979
|
);
|
|
@@ -12980,7 +12995,7 @@ import {
|
|
|
12980
12995
|
DialogTitle,
|
|
12981
12996
|
} from "../dialog";
|
|
12982
12997
|
import { Button } from "../button";
|
|
12983
|
-
import type
|
|
12998
|
+
import { BOT_TYPE, type CreateBotModalProps, type BotType } from "./types";
|
|
12984
12999
|
|
|
12985
13000
|
interface BotTypeOption {
|
|
12986
13001
|
id: BotType;
|
|
@@ -13010,7 +13025,8 @@ export const CreateBotModal = React.forwardRef<
|
|
|
13010
13025
|
|
|
13011
13026
|
const handleSubmit = () => {
|
|
13012
13027
|
if (!name.trim()) return;
|
|
13013
|
-
|
|
13028
|
+
const typeValue = selectedType === "chatbot" ? BOT_TYPE.CHAT : BOT_TYPE.VOICE;
|
|
13029
|
+
onSubmit?.({ name: name.trim(), type: typeValue });
|
|
13014
13030
|
setName("");
|
|
13015
13031
|
setSelectedType("chatbot");
|
|
13016
13032
|
};
|
|
@@ -13023,12 +13039,12 @@ export const CreateBotModal = React.forwardRef<
|
|
|
13023
13039
|
|
|
13024
13040
|
return (
|
|
13025
13041
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
13026
|
-
<DialogContent ref={ref} size="sm" className={cn("mx-
|
|
13042
|
+
<DialogContent ref={ref} size="sm" className={cn("mx-3 max-h-[90vh] overflow-y-auto w-[calc(100%-1.5rem)] sm:mx-auto sm:w-full", className)}>
|
|
13027
13043
|
<DialogHeader>
|
|
13028
13044
|
<DialogTitle>Create AI bot</DialogTitle>
|
|
13029
13045
|
</DialogHeader>
|
|
13030
13046
|
|
|
13031
|
-
<div className="flex flex-col gap-6">
|
|
13047
|
+
<div className="flex flex-col gap-4 sm:gap-6">
|
|
13032
13048
|
{/* Name field */}
|
|
13033
13049
|
<div className="flex flex-col gap-1.5">
|
|
13034
13050
|
<label
|
|
@@ -13059,7 +13075,7 @@ export const CreateBotModal = React.forwardRef<
|
|
|
13059
13075
|
<span className="text-sm font-semibold text-semantic-text-secondary tracking-[0.014px]">
|
|
13060
13076
|
Select Bot Type
|
|
13061
13077
|
</span>
|
|
13062
|
-
<div className="flex gap-3">
|
|
13078
|
+
<div className="flex flex-col gap-3 sm:flex-row sm:gap-3">
|
|
13063
13079
|
{BOT_TYPE_OPTIONS.map(({ id, label, description }) => {
|
|
13064
13080
|
const isSelected = selectedType === id;
|
|
13065
13081
|
return (
|
|
@@ -13068,7 +13084,7 @@ export const CreateBotModal = React.forwardRef<
|
|
|
13068
13084
|
type="button"
|
|
13069
13085
|
onClick={() => setSelectedType(id)}
|
|
13070
13086
|
className={cn(
|
|
13071
|
-
"flex flex-col items-start gap-2.5 p-3 rounded-lg border text-left flex-1 h-[134px] justify-center",
|
|
13087
|
+
"flex flex-col items-start gap-2 sm:gap-2.5 p-3 rounded-lg border text-left flex-1 min-h-[100px] sm:h-[134px] justify-center min-w-0",
|
|
13072
13088
|
"transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-semantic-border-focus",
|
|
13073
13089
|
isSelected
|
|
13074
13090
|
? "bg-semantic-brand-surface border-semantic-brand shadow-sm"
|
|
@@ -13114,7 +13130,7 @@ export const CreateBotModal = React.forwardRef<
|
|
|
13114
13130
|
</div>
|
|
13115
13131
|
|
|
13116
13132
|
{/* Footer actions */}
|
|
13117
|
-
<div className="flex gap-4 justify-end mt-2">
|
|
13133
|
+
<div className="flex flex-col-reverse gap-3 sm:flex-row sm:gap-4 justify-end mt-2">
|
|
13118
13134
|
<Button variant="outline" onClick={handleClose}>
|
|
13119
13135
|
Cancel
|
|
13120
13136
|
</Button>
|
|
@@ -13137,9 +13153,12 @@ CreateBotModal.displayName = "CreateBotModal";
|
|
|
13137
13153
|
{
|
|
13138
13154
|
name: "bot-list.tsx",
|
|
13139
13155
|
content: prefixTailwindClasses(`import * as React from "react";
|
|
13140
|
-
import { Plus, Search } from "lucide-react";
|
|
13141
13156
|
import { cn } from "../../../lib/utils";
|
|
13142
13157
|
import { BotCard } from "./bot-card";
|
|
13158
|
+
import { BotListHeader } from "./bot-list-header";
|
|
13159
|
+
import { BotListSearch } from "./bot-list-search";
|
|
13160
|
+
import { BotListCreateCard } from "./bot-list-create-card";
|
|
13161
|
+
import { BotListGrid } from "./bot-list-grid";
|
|
13143
13162
|
import { CreateBotModal } from "./create-bot-modal";
|
|
13144
13163
|
import type { BotListProps } from "./types";
|
|
13145
13164
|
|
|
@@ -13147,6 +13166,7 @@ export const BotList = React.forwardRef<HTMLDivElement, BotListProps>(
|
|
|
13147
13166
|
(
|
|
13148
13167
|
{
|
|
13149
13168
|
bots = [],
|
|
13169
|
+
typeLabels,
|
|
13150
13170
|
onCreateBot,
|
|
13151
13171
|
onCreateBotSubmit,
|
|
13152
13172
|
onBotEdit,
|
|
@@ -13155,7 +13175,10 @@ export const BotList = React.forwardRef<HTMLDivElement, BotListProps>(
|
|
|
13155
13175
|
onSearch,
|
|
13156
13176
|
title = "AI Bot",
|
|
13157
13177
|
subtitle = "Create & manage AI bots",
|
|
13178
|
+
searchPlaceholder = "Search bot...",
|
|
13179
|
+
createCardLabel = "Create new bot",
|
|
13158
13180
|
className,
|
|
13181
|
+
...props
|
|
13159
13182
|
},
|
|
13160
13183
|
ref
|
|
13161
13184
|
) => {
|
|
@@ -13168,64 +13191,41 @@ export const BotList = React.forwardRef<HTMLDivElement, BotListProps>(
|
|
|
13168
13191
|
};
|
|
13169
13192
|
|
|
13170
13193
|
return (
|
|
13171
|
-
<div
|
|
13172
|
-
{
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
<div className="flex items-center gap-2 h-10 px-2.5 border border-semantic-border-input rounded bg-semantic-bg-primary hover:border-semantic-border-input-focus focus-within:border-semantic-border-input-focus focus-within:shadow-[0_0_0_1px_rgba(43,188,202,0.15)] w-full sm:w-auto">
|
|
13185
|
-
<Search className="size-[14px] text-semantic-text-muted shrink-0" />
|
|
13186
|
-
<input
|
|
13187
|
-
type="text"
|
|
13188
|
-
value={searchQuery}
|
|
13189
|
-
onChange={(e) => handleSearch(e.target.value)}
|
|
13190
|
-
placeholder="Search bot..."
|
|
13191
|
-
className="text-sm text-semantic-text-primary placeholder:text-semantic-text-muted bg-transparent outline-none w-full sm:w-[180px]"
|
|
13192
|
-
/>
|
|
13193
|
-
</div>
|
|
13194
|
+
<div
|
|
13195
|
+
ref={ref}
|
|
13196
|
+
className={cn("flex flex-col w-full min-w-0 max-w-full overflow-x-hidden box-border", className)}
|
|
13197
|
+
{...props}
|
|
13198
|
+
>
|
|
13199
|
+
{/* Page header: title, subtitle, and search */}
|
|
13200
|
+
<div className="flex flex-col gap-3 pb-4 mb-4 border-b border-semantic-border-layout sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:pb-5 sm:mb-6 min-w-0">
|
|
13201
|
+
<BotListHeader title={title} subtitle={subtitle} />
|
|
13202
|
+
<BotListSearch
|
|
13203
|
+
value={searchQuery}
|
|
13204
|
+
onSearch={handleSearch}
|
|
13205
|
+
placeholder={searchPlaceholder}
|
|
13206
|
+
/>
|
|
13194
13207
|
</div>
|
|
13195
13208
|
|
|
13196
|
-
{/* Bot grid */}
|
|
13197
|
-
<
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
type="button"
|
|
13209
|
+
{/* Bot grid: create card + bot cards */}
|
|
13210
|
+
<BotListGrid>
|
|
13211
|
+
<BotListCreateCard
|
|
13212
|
+
label={createCardLabel}
|
|
13201
13213
|
onClick={() => {
|
|
13202
13214
|
setCreateModalOpen(true);
|
|
13203
13215
|
onCreateBot?.();
|
|
13204
13216
|
}}
|
|
13205
|
-
|
|
13206
|
-
"flex flex-col items-center justify-center gap-3 p-2.5 rounded-[5px]",
|
|
13207
|
-
"bg-semantic-info-surface-subtle border border-dashed border-[var(--color-primary-100)]",
|
|
13208
|
-
"cursor-pointer hover:bg-semantic-bg-hover transition-colors min-h-[207px]",
|
|
13209
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-semantic-border-focus"
|
|
13210
|
-
)}
|
|
13211
|
-
>
|
|
13212
|
-
<Plus className="size-4 text-semantic-text-secondary" />
|
|
13213
|
-
<span className="text-sm font-semibold text-semantic-text-secondary tracking-[0.014px]">
|
|
13214
|
-
Create new bot
|
|
13215
|
-
</span>
|
|
13216
|
-
</button>
|
|
13217
|
-
|
|
13218
|
-
{/* Bot cards */}
|
|
13217
|
+
/>
|
|
13219
13218
|
{bots.map((bot) => (
|
|
13220
13219
|
<BotCard
|
|
13221
13220
|
key={bot.id}
|
|
13222
13221
|
bot={bot}
|
|
13222
|
+
typeLabels={typeLabels}
|
|
13223
13223
|
onEdit={onBotEdit}
|
|
13224
13224
|
onPublish={onBotPublish}
|
|
13225
13225
|
onDelete={onBotDelete}
|
|
13226
13226
|
/>
|
|
13227
13227
|
))}
|
|
13228
|
-
</
|
|
13228
|
+
</BotListGrid>
|
|
13229
13229
|
|
|
13230
13230
|
<CreateBotModal
|
|
13231
13231
|
open={createModalOpen}
|
|
@@ -13241,52 +13241,365 @@ export const BotList = React.forwardRef<HTMLDivElement, BotListProps>(
|
|
|
13241
13241
|
);
|
|
13242
13242
|
|
|
13243
13243
|
BotList.displayName = "BotList";
|
|
13244
|
+
`, prefix)
|
|
13245
|
+
},
|
|
13246
|
+
{
|
|
13247
|
+
name: "bot-list-header.tsx",
|
|
13248
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
13249
|
+
import { cn } from "../../../lib/utils";
|
|
13250
|
+
import type { BotListHeaderProps } from "./types";
|
|
13251
|
+
|
|
13252
|
+
export const BotListHeader = React.forwardRef<HTMLDivElement, BotListHeaderProps>(
|
|
13253
|
+
({ title, subtitle, className, ...props }, ref) => (
|
|
13254
|
+
<div
|
|
13255
|
+
ref={ref}
|
|
13256
|
+
className={cn("flex flex-col gap-1.5 min-w-0 shrink", className)}
|
|
13257
|
+
{...props}
|
|
13258
|
+
>
|
|
13259
|
+
{title != null && (
|
|
13260
|
+
<h1 className="m-0 text-base font-semibold text-semantic-text-primary tracking-[0.064px] break-words sm:text-lg">
|
|
13261
|
+
{title}
|
|
13262
|
+
</h1>
|
|
13263
|
+
)}
|
|
13264
|
+
{subtitle != null && (
|
|
13265
|
+
<p className="m-0 text-xs sm:text-sm text-semantic-text-muted tracking-[0.035px] break-words">
|
|
13266
|
+
{subtitle}
|
|
13267
|
+
</p>
|
|
13268
|
+
)}
|
|
13269
|
+
</div>
|
|
13270
|
+
)
|
|
13271
|
+
);
|
|
13272
|
+
|
|
13273
|
+
BotListHeader.displayName = "BotListHeader";
|
|
13274
|
+
`, prefix)
|
|
13275
|
+
},
|
|
13276
|
+
{
|
|
13277
|
+
name: "bot-list-search.tsx",
|
|
13278
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
13279
|
+
import { Search } from "lucide-react";
|
|
13280
|
+
import { cn } from "../../../lib/utils";
|
|
13281
|
+
import type { BotListSearchProps } from "./types";
|
|
13282
|
+
|
|
13283
|
+
export const BotListSearch = React.forwardRef<HTMLDivElement, BotListSearchProps>(
|
|
13284
|
+
(
|
|
13285
|
+
{
|
|
13286
|
+
value,
|
|
13287
|
+
placeholder = "Search bot...",
|
|
13288
|
+
onSearch,
|
|
13289
|
+
defaultValue,
|
|
13290
|
+
className,
|
|
13291
|
+
...props
|
|
13292
|
+
},
|
|
13293
|
+
ref
|
|
13294
|
+
) => {
|
|
13295
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
|
|
13296
|
+
const isControlled = value !== undefined;
|
|
13297
|
+
const displayValue = isControlled ? value : internalValue;
|
|
13298
|
+
|
|
13299
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
13300
|
+
const next = e.target.value;
|
|
13301
|
+
if (!isControlled) setInternalValue(next);
|
|
13302
|
+
onSearch?.(next);
|
|
13303
|
+
};
|
|
13304
|
+
|
|
13305
|
+
return (
|
|
13306
|
+
<div
|
|
13307
|
+
ref={ref}
|
|
13308
|
+
className={cn(
|
|
13309
|
+
"flex items-center gap-2 h-9 sm:h-10 px-2.5 sm:px-3 border border-semantic-border-input rounded bg-semantic-bg-primary min-w-0 shrink-0",
|
|
13310
|
+
"hover:border-semantic-border-input-focus focus-within:border-semantic-border-input-focus",
|
|
13311
|
+
"focus-within:shadow-[0_0_0_1px_rgba(43,188,202,0.15)] w-full max-w-full sm:max-w-[180px] md:max-w-[220px] sm:shrink-0",
|
|
13312
|
+
className
|
|
13313
|
+
)}
|
|
13314
|
+
{...props}
|
|
13315
|
+
>
|
|
13316
|
+
<Search className="size-[14px] text-semantic-text-muted shrink-0" />
|
|
13317
|
+
<input
|
|
13318
|
+
type="text"
|
|
13319
|
+
value={displayValue}
|
|
13320
|
+
onChange={handleChange}
|
|
13321
|
+
placeholder={placeholder}
|
|
13322
|
+
className="text-sm text-semantic-text-primary placeholder:text-semantic-text-muted bg-transparent outline-none w-full min-w-0"
|
|
13323
|
+
aria-label={placeholder}
|
|
13324
|
+
/>
|
|
13325
|
+
</div>
|
|
13326
|
+
);
|
|
13327
|
+
}
|
|
13328
|
+
);
|
|
13329
|
+
|
|
13330
|
+
BotListSearch.displayName = "BotListSearch";
|
|
13331
|
+
`, prefix)
|
|
13332
|
+
},
|
|
13333
|
+
{
|
|
13334
|
+
name: "bot-list-create-card.tsx",
|
|
13335
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
13336
|
+
import { Plus } from "lucide-react";
|
|
13337
|
+
import { cn } from "../../../lib/utils";
|
|
13338
|
+
import type { BotListCreateCardProps } from "./types";
|
|
13339
|
+
|
|
13340
|
+
export const BotListCreateCard = React.forwardRef<
|
|
13341
|
+
HTMLButtonElement,
|
|
13342
|
+
BotListCreateCardProps
|
|
13343
|
+
>(
|
|
13344
|
+
(
|
|
13345
|
+
{
|
|
13346
|
+
label = "Create new bot",
|
|
13347
|
+
onClick,
|
|
13348
|
+
className,
|
|
13349
|
+
...props
|
|
13350
|
+
},
|
|
13351
|
+
ref
|
|
13352
|
+
) => (
|
|
13353
|
+
<button
|
|
13354
|
+
ref={ref}
|
|
13355
|
+
type="button"
|
|
13356
|
+
onClick={onClick}
|
|
13357
|
+
className={cn(
|
|
13358
|
+
"flex flex-col items-center justify-center gap-2 sm:gap-3 p-3 sm:p-2.5 rounded-[5px] min-h-[180px] sm:min-h-[207px] w-full min-w-0 max-w-full",
|
|
13359
|
+
"bg-semantic-info-surface-subtle border border-dashed border-semantic-border-layout",
|
|
13360
|
+
"cursor-pointer transition-colors hover:bg-semantic-bg-hover hover:border-semantic-border-input",
|
|
13361
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-semantic-border-focus",
|
|
13362
|
+
"self-stretch justify-self-stretch",
|
|
13363
|
+
className
|
|
13364
|
+
)}
|
|
13365
|
+
aria-label={label}
|
|
13366
|
+
{...props}
|
|
13367
|
+
>
|
|
13368
|
+
<Plus className="size-4 text-semantic-text-secondary shrink-0" />
|
|
13369
|
+
<span className="text-sm font-semibold leading-5 text-semantic-text-secondary text-center tracking-[0.014px]">
|
|
13370
|
+
{label}
|
|
13371
|
+
</span>
|
|
13372
|
+
</button>
|
|
13373
|
+
)
|
|
13374
|
+
);
|
|
13375
|
+
|
|
13376
|
+
BotListCreateCard.displayName = "BotListCreateCard";
|
|
13377
|
+
`, prefix)
|
|
13378
|
+
},
|
|
13379
|
+
{
|
|
13380
|
+
name: "bot-list-grid.tsx",
|
|
13381
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
13382
|
+
import { cn } from "../../../lib/utils";
|
|
13383
|
+
import type { BotListGridProps } from "./types";
|
|
13384
|
+
|
|
13385
|
+
export const BotListGrid = React.forwardRef<HTMLDivElement, BotListGridProps>(
|
|
13386
|
+
({ children, className, ...props }, ref) => (
|
|
13387
|
+
<div
|
|
13388
|
+
ref={ref}
|
|
13389
|
+
className={cn(
|
|
13390
|
+
"grid w-full min-w-0 max-w-full overflow-hidden gap-3 sm:gap-5 md:gap-6",
|
|
13391
|
+
"grid-cols-[repeat(auto-fill,minmax(min(100%,280px),1fr))]",
|
|
13392
|
+
className
|
|
13393
|
+
)}
|
|
13394
|
+
{...props}
|
|
13395
|
+
>
|
|
13396
|
+
{children}
|
|
13397
|
+
</div>
|
|
13398
|
+
)
|
|
13399
|
+
);
|
|
13400
|
+
|
|
13401
|
+
BotListGrid.displayName = "BotListGrid";
|
|
13402
|
+
`, prefix)
|
|
13403
|
+
},
|
|
13404
|
+
{
|
|
13405
|
+
name: "bot-list-action.tsx",
|
|
13406
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
13407
|
+
import { MoreVertical, Pencil, Trash2 } from "lucide-react";
|
|
13408
|
+
import { cn } from "../../../lib/utils";
|
|
13409
|
+
import {
|
|
13410
|
+
DropdownMenu,
|
|
13411
|
+
DropdownMenuTrigger,
|
|
13412
|
+
DropdownMenuContent,
|
|
13413
|
+
DropdownMenuItem,
|
|
13414
|
+
DropdownMenuSeparator,
|
|
13415
|
+
} from "../dropdown-menu";
|
|
13416
|
+
import type { BotListActionProps } from "./types";
|
|
13417
|
+
|
|
13418
|
+
const defaultTrigger = (
|
|
13419
|
+
<button
|
|
13420
|
+
type="button"
|
|
13421
|
+
className="p-2 min-h-[44px] min-w-[44px] sm:p-1 sm:min-h-0 sm:min-w-0 rounded hover:bg-semantic-bg-hover text-semantic-text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-semantic-border-focus flex items-center justify-center touch-manipulation"
|
|
13422
|
+
aria-label="More options"
|
|
13423
|
+
>
|
|
13424
|
+
<MoreVertical className="size-4 shrink-0" />
|
|
13425
|
+
</button>
|
|
13426
|
+
);
|
|
13427
|
+
|
|
13428
|
+
export const BotListAction = React.forwardRef<HTMLDivElement, BotListActionProps>(
|
|
13429
|
+
(
|
|
13430
|
+
{
|
|
13431
|
+
onEdit,
|
|
13432
|
+
onDelete,
|
|
13433
|
+
trigger = defaultTrigger,
|
|
13434
|
+
align = "end",
|
|
13435
|
+
className,
|
|
13436
|
+
...props
|
|
13437
|
+
},
|
|
13438
|
+
ref
|
|
13439
|
+
) => {
|
|
13440
|
+
return (
|
|
13441
|
+
<div ref={ref} className={cn("inline-flex", className)} {...props}>
|
|
13442
|
+
<DropdownMenu>
|
|
13443
|
+
<DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
|
|
13444
|
+
<DropdownMenuContent
|
|
13445
|
+
align={align}
|
|
13446
|
+
className="min-w-[160px] max-w-[min(100vw-2rem,320px)] max-h-[min(70vh,400px)] overflow-y-auto rounded-lg border border-semantic-border-layout bg-semantic-bg-ui p-1 shadow-lg"
|
|
13447
|
+
>
|
|
13448
|
+
<DropdownMenuItem
|
|
13449
|
+
className="flex cursor-pointer items-center gap-2 px-3 py-2.5 text-sm text-semantic-text-primary outline-none transition-colors focus:bg-semantic-bg-hover focus:text-semantic-text-primary"
|
|
13450
|
+
onSelect={(e) => {
|
|
13451
|
+
e.preventDefault();
|
|
13452
|
+
onEdit?.();
|
|
13453
|
+
}}
|
|
13454
|
+
>
|
|
13455
|
+
<Pencil className="size-4 shrink-0 text-semantic-text-primary" />
|
|
13456
|
+
<span>Edit</span>
|
|
13457
|
+
</DropdownMenuItem>
|
|
13458
|
+
<DropdownMenuSeparator className="my-1 bg-semantic-border-layout" />
|
|
13459
|
+
<DropdownMenuItem
|
|
13460
|
+
className="flex cursor-pointer items-center gap-2 px-3 py-2.5 text-sm text-semantic-error-primary outline-none transition-colors focus:bg-semantic-error-surface focus:text-semantic-error-primary"
|
|
13461
|
+
onSelect={(e) => {
|
|
13462
|
+
e.preventDefault();
|
|
13463
|
+
onDelete?.();
|
|
13464
|
+
}}
|
|
13465
|
+
>
|
|
13466
|
+
<Trash2 className="size-4 shrink-0 text-semantic-error-primary" />
|
|
13467
|
+
<span>Delete</span>
|
|
13468
|
+
</DropdownMenuItem>
|
|
13469
|
+
</DropdownMenuContent>
|
|
13470
|
+
</DropdownMenu>
|
|
13471
|
+
</div>
|
|
13472
|
+
);
|
|
13473
|
+
}
|
|
13474
|
+
);
|
|
13475
|
+
|
|
13476
|
+
BotListAction.displayName = "BotListAction";
|
|
13244
13477
|
`, prefix)
|
|
13245
13478
|
},
|
|
13246
13479
|
{
|
|
13247
13480
|
name: "types.ts",
|
|
13248
|
-
content: prefixTailwindClasses(`
|
|
13481
|
+
content: prefixTailwindClasses(`import type * as React from "react";
|
|
13482
|
+
|
|
13483
|
+
export const BOT_TYPE = {
|
|
13484
|
+
CHAT: 1,
|
|
13485
|
+
VOICE: 2,
|
|
13486
|
+
} as const;
|
|
13487
|
+
|
|
13488
|
+
export type BOT_TYPE = (typeof BOT_TYPE)[keyof typeof BOT_TYPE];
|
|
13489
|
+
|
|
13490
|
+
export type BotType = "chatbot" | "voicebot";
|
|
13491
|
+
|
|
13492
|
+
export type BotStatus = "draft" | "published";
|
|
13249
13493
|
|
|
13494
|
+
/**
|
|
13495
|
+
* Single bot shape for both Chatbot and Voicebot.
|
|
13496
|
+
* Use the same BotCard for both; set type to "chatbot" or "voicebot" and pass all data via this prop.
|
|
13497
|
+
*/
|
|
13250
13498
|
export interface Bot {
|
|
13251
13499
|
id: string;
|
|
13252
13500
|
name: string;
|
|
13501
|
+
/** "chatbot" | "voicebot" \u2014 determines icon and default badge label; all other data is from this object */
|
|
13253
13502
|
type: BotType;
|
|
13254
13503
|
conversationCount: number;
|
|
13255
13504
|
lastPublishedBy?: string;
|
|
13256
13505
|
lastPublishedDate?: string;
|
|
13506
|
+
/** Optional custom label for the type badge (overrides typeLabels and default "Chatbot"/"Voicebot") */
|
|
13507
|
+
typeLabel?: string;
|
|
13508
|
+
/** When "draft", card shows "Unpublished changes" with red indicator in the Last Published section */
|
|
13509
|
+
status?: BotStatus;
|
|
13257
13510
|
}
|
|
13258
13511
|
|
|
13259
|
-
export interface BotCardProps
|
|
13512
|
+
export interface BotCardProps
|
|
13513
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
|
|
13514
|
+
/** Single bot object: pass chatbot or voicebot data here; card renders based on bot.type and bot fields */
|
|
13260
13515
|
bot: Bot;
|
|
13516
|
+
/** Override labels for bot types (e.g. { chatbot: "Chat", voicebot: "Voice" }). Ignored if bot.typeLabel is set. */
|
|
13517
|
+
typeLabels?: Partial<Record<BotType, string>>;
|
|
13261
13518
|
/** Called when Edit action is selected */
|
|
13262
13519
|
onEdit?: (botId: string) => void;
|
|
13263
13520
|
/** Called when Publish action is selected */
|
|
13264
13521
|
onPublish?: (botId: string) => void;
|
|
13265
13522
|
/** Called when Delete action is selected */
|
|
13266
13523
|
onDelete?: (botId: string) => void;
|
|
13267
|
-
className?: string;
|
|
13268
13524
|
}
|
|
13269
13525
|
|
|
13270
13526
|
export interface CreateBotModalProps {
|
|
13271
13527
|
open: boolean;
|
|
13272
13528
|
onOpenChange: (open: boolean) => void;
|
|
13273
|
-
|
|
13529
|
+
/** Called with name and BOT_TYPE (CHAT = 1, VOICE = 2) when user submits */
|
|
13530
|
+
onSubmit?: (data: { name: string; type: BOT_TYPE }) => void;
|
|
13274
13531
|
className?: string;
|
|
13275
13532
|
}
|
|
13276
13533
|
|
|
13277
|
-
export interface
|
|
13534
|
+
export interface BotListHeaderProps
|
|
13535
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
13536
|
+
/** Page title */
|
|
13537
|
+
title?: string;
|
|
13538
|
+
/** Optional subtitle below the title */
|
|
13539
|
+
subtitle?: string;
|
|
13540
|
+
}
|
|
13541
|
+
|
|
13542
|
+
export interface BotListSearchProps
|
|
13543
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
13544
|
+
/** Controlled value (use with onSearch) */
|
|
13545
|
+
value?: string;
|
|
13546
|
+
/** Placeholder text */
|
|
13547
|
+
placeholder?: string;
|
|
13548
|
+
/** Called when the search value changes */
|
|
13549
|
+
onSearch?: (query: string) => void;
|
|
13550
|
+
/** Uncontrolled: default value */
|
|
13551
|
+
defaultValue?: string;
|
|
13552
|
+
}
|
|
13553
|
+
|
|
13554
|
+
export interface BotListCreateCardProps
|
|
13555
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
13556
|
+
/** Label for the create card (e.g. "Create new bot") */
|
|
13557
|
+
label?: string;
|
|
13558
|
+
}
|
|
13559
|
+
|
|
13560
|
+
export interface BotListGridProps
|
|
13561
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
13562
|
+
children: React.ReactNode;
|
|
13563
|
+
}
|
|
13564
|
+
|
|
13565
|
+
export interface BotListActionProps
|
|
13566
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
13567
|
+
/** Called when Edit is selected */
|
|
13568
|
+
onEdit?: () => void;
|
|
13569
|
+
/** Called when Delete is selected */
|
|
13570
|
+
onDelete?: () => void;
|
|
13571
|
+
/** Custom trigger element; defaults to three-dot icon button */
|
|
13572
|
+
trigger?: React.ReactNode;
|
|
13573
|
+
/** Content alignment relative to trigger */
|
|
13574
|
+
align?: "start" | "center" | "end";
|
|
13575
|
+
}
|
|
13576
|
+
|
|
13577
|
+
export interface BotListProps
|
|
13578
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
|
|
13579
|
+
/** List of bots to display */
|
|
13278
13580
|
bots?: Bot[];
|
|
13581
|
+
/** Override type badge labels for all cards (e.g. { chatbot: "Chat", voicebot: "Voice" }). Per-bot bot.typeLabel still wins. */
|
|
13582
|
+
typeLabels?: Partial<Record<BotType, string>>;
|
|
13279
13583
|
/** Called when the "Create new bot" card is clicked (modal opens) */
|
|
13280
13584
|
onCreateBot?: () => void;
|
|
13281
|
-
/** Called when the Create Bot modal is submitted with the new bot data */
|
|
13282
|
-
onCreateBotSubmit?: (data: { name: string; type:
|
|
13585
|
+
/** Called when the Create Bot modal is submitted with the new bot data (type is BOT_TYPE: CHAT = 1, VOICE = 2) */
|
|
13586
|
+
onCreateBotSubmit?: (data: { name: string; type: BOT_TYPE }) => void;
|
|
13587
|
+
/** Called when user selects Edit on a bot (card click or menu) */
|
|
13283
13588
|
onBotEdit?: (botId: string) => void;
|
|
13589
|
+
/** Called when user selects Publish on a bot (menu; optional) */
|
|
13284
13590
|
onBotPublish?: (botId: string) => void;
|
|
13591
|
+
/** Called when user selects Delete on a bot */
|
|
13285
13592
|
onBotDelete?: (botId: string) => void;
|
|
13593
|
+
/** Called when the search query changes */
|
|
13286
13594
|
onSearch?: (query: string) => void;
|
|
13595
|
+
/** Page title (default: "AI Bot") */
|
|
13287
13596
|
title?: string;
|
|
13597
|
+
/** Page subtitle (default: "Create & manage AI bots") */
|
|
13288
13598
|
subtitle?: string;
|
|
13289
|
-
|
|
13599
|
+
/** Placeholder for the search input (default: "Search bot...") */
|
|
13600
|
+
searchPlaceholder?: string;
|
|
13601
|
+
/** Label for the create-new-bot card (default: "Create new bot") */
|
|
13602
|
+
createCardLabel?: string;
|
|
13290
13603
|
}
|
|
13291
13604
|
`, prefix)
|
|
13292
13605
|
},
|
|
@@ -13299,7 +13612,23 @@ export { CreateBotModal } from "./create-bot-modal";
|
|
|
13299
13612
|
export type { CreateBotModalProps } from "./types";
|
|
13300
13613
|
|
|
13301
13614
|
export { BotList } from "./bot-list";
|
|
13302
|
-
export
|
|
13615
|
+
export { BotListHeader } from "./bot-list-header";
|
|
13616
|
+
export { BotListSearch } from "./bot-list-search";
|
|
13617
|
+
export { BotListCreateCard } from "./bot-list-create-card";
|
|
13618
|
+
export { BotListGrid } from "./bot-list-grid";
|
|
13619
|
+
export { BotListAction } from "./bot-list-action";
|
|
13620
|
+
export { BOT_TYPE } from "./types";
|
|
13621
|
+
export type {
|
|
13622
|
+
BotListProps,
|
|
13623
|
+
BotListHeaderProps,
|
|
13624
|
+
BotListSearchProps,
|
|
13625
|
+
BotListCreateCardProps,
|
|
13626
|
+
BotListGridProps,
|
|
13627
|
+
BotListActionProps,
|
|
13628
|
+
Bot,
|
|
13629
|
+
BotType,
|
|
13630
|
+
BotStatus,
|
|
13631
|
+
} from "./types";
|
|
13303
13632
|
`, prefix)
|
|
13304
13633
|
}
|
|
13305
13634
|
]
|