myoperator-ui 0.0.208 → 0.0.209
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 +264 -63
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1127,41 +1127,84 @@ const SelectScrollDownButton = React.forwardRef<
|
|
|
1127
1127
|
SelectScrollDownButton.displayName =
|
|
1128
1128
|
SelectPrimitive.ScrollDownButton.displayName;
|
|
1129
1129
|
|
|
1130
|
+
/**
|
|
1131
|
+
* Radix Select v2 wraps content in RemoveScroll which locks body scroll
|
|
1132
|
+
* via both CSS (overflow:hidden) and JS (preventDefault on wheel/touchmove).
|
|
1133
|
+
*
|
|
1134
|
+
* CSS fix: react-remove-scroll-bar uses \`body[data-scroll-locked]\` with
|
|
1135
|
+
* \`!important\`. We use a doubled attribute selector for higher specificity
|
|
1136
|
+
* so our override always wins regardless of style injection order.
|
|
1137
|
+
*
|
|
1138
|
+
* JS fix: react-remove-scroll checks \`event.cancelable\` before calling
|
|
1139
|
+
* \`preventDefault()\`. We override this property in a capture-phase listener
|
|
1140
|
+
* so the library skips the preventDefault call.
|
|
1141
|
+
*/
|
|
1142
|
+
function useUnlockBodyScroll() {
|
|
1143
|
+
React.useEffect(() => {
|
|
1144
|
+
const style = document.createElement("style");
|
|
1145
|
+
style.setAttribute("data-select-scroll-fix", "");
|
|
1146
|
+
style.textContent =
|
|
1147
|
+
"body[data-scroll-locked][data-scroll-locked] { overflow: auto !important; margin-right: 0 !important; overscroll-behavior: auto !important; }";
|
|
1148
|
+
document.head.appendChild(style);
|
|
1149
|
+
|
|
1150
|
+
const preventScrollLock = (e: Event) => {
|
|
1151
|
+
if (!document.body.hasAttribute("data-scroll-locked")) return;
|
|
1152
|
+
Object.defineProperty(e, "cancelable", {
|
|
1153
|
+
value: false,
|
|
1154
|
+
configurable: true,
|
|
1155
|
+
});
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
document.addEventListener("wheel", preventScrollLock, true);
|
|
1159
|
+
document.addEventListener("touchmove", preventScrollLock, true);
|
|
1160
|
+
|
|
1161
|
+
return () => {
|
|
1162
|
+
document.head.removeChild(style);
|
|
1163
|
+
document.removeEventListener("wheel", preventScrollLock, true);
|
|
1164
|
+
document.removeEventListener("touchmove", preventScrollLock, true);
|
|
1165
|
+
};
|
|
1166
|
+
}, []);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1130
1169
|
const SelectContent = React.forwardRef<
|
|
1131
1170
|
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
1132
1171
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
1133
|
-
>(({ className, children, position = "popper", ...props }, ref) =>
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1141
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
1142
|
-
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
1143
|
-
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
1144
|
-
position === "popper" &&
|
|
1145
|
-
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
1146
|
-
className
|
|
1147
|
-
)}
|
|
1148
|
-
position={position}
|
|
1149
|
-
{...props}
|
|
1150
|
-
>
|
|
1151
|
-
<SelectScrollUpButton />
|
|
1152
|
-
<SelectPrimitive.Viewport
|
|
1172
|
+
>(({ className, children, position = "popper", ...props }, ref) => {
|
|
1173
|
+
useUnlockBodyScroll();
|
|
1174
|
+
|
|
1175
|
+
return (
|
|
1176
|
+
<SelectPrimitive.Portal>
|
|
1177
|
+
<SelectPrimitive.Content
|
|
1178
|
+
ref={ref}
|
|
1153
1179
|
className={cn(
|
|
1154
|
-
"
|
|
1180
|
+
"relative z-[9999] max-h-96 min-w-[8rem] overflow-hidden rounded bg-semantic-bg-primary border border-semantic-border-layout shadow-md",
|
|
1181
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1182
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1183
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
1184
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
1185
|
+
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
1155
1186
|
position === "popper" &&
|
|
1156
|
-
"
|
|
1187
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
1188
|
+
className
|
|
1157
1189
|
)}
|
|
1190
|
+
position={position}
|
|
1191
|
+
{...props}
|
|
1158
1192
|
>
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
))
|
|
1193
|
+
<SelectScrollUpButton />
|
|
1194
|
+
<SelectPrimitive.Viewport
|
|
1195
|
+
className={cn(
|
|
1196
|
+
"p-1",
|
|
1197
|
+
position === "popper" &&
|
|
1198
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
1199
|
+
)}
|
|
1200
|
+
>
|
|
1201
|
+
{children}
|
|
1202
|
+
</SelectPrimitive.Viewport>
|
|
1203
|
+
<SelectScrollDownButton />
|
|
1204
|
+
</SelectPrimitive.Content>
|
|
1205
|
+
</SelectPrimitive.Portal>
|
|
1206
|
+
);
|
|
1207
|
+
});
|
|
1165
1208
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
1166
1209
|
|
|
1167
1210
|
const SelectLabel = React.forwardRef<
|
|
@@ -10939,6 +10982,8 @@ const PlanUpgradeSummaryModal = React.forwardRef<
|
|
|
10939
10982
|
cancelLabel = "Cancel",
|
|
10940
10983
|
primaryActionLabel,
|
|
10941
10984
|
onPrimaryAction,
|
|
10985
|
+
loading = false,
|
|
10986
|
+
disabled = false,
|
|
10942
10987
|
onCancel,
|
|
10943
10988
|
onClose,
|
|
10944
10989
|
closeAriaLabel = "Close plan summary modal",
|
|
@@ -11037,7 +11082,7 @@ const PlanUpgradeSummaryModal = React.forwardRef<
|
|
|
11037
11082
|
<Button variant="outline" onClick={handleCancel}>
|
|
11038
11083
|
{cancelLabel}
|
|
11039
11084
|
</Button>
|
|
11040
|
-
<Button variant="primary" onClick={onPrimaryAction}>
|
|
11085
|
+
<Button variant="primary" onClick={onPrimaryAction} loading={loading} disabled={disabled}>
|
|
11041
11086
|
{resolvedPrimaryActionLabel}
|
|
11042
11087
|
</Button>
|
|
11043
11088
|
</div>
|
|
@@ -11103,6 +11148,10 @@ export interface PlanUpgradeSummaryModalProps
|
|
|
11103
11148
|
primaryActionLabel?: string;
|
|
11104
11149
|
/** Called when the primary CTA is clicked */
|
|
11105
11150
|
onPrimaryAction?: () => void;
|
|
11151
|
+
/** Shows loading spinner on the primary CTA button */
|
|
11152
|
+
loading?: boolean;
|
|
11153
|
+
/** Disables the primary CTA button */
|
|
11154
|
+
disabled?: boolean;
|
|
11106
11155
|
/** Called when the cancel button is clicked */
|
|
11107
11156
|
onCancel?: () => void;
|
|
11108
11157
|
/** Called when the close icon is clicked */
|
|
@@ -11475,7 +11524,7 @@ export type { PowerUpCardProps } from "./types";
|
|
|
11475
11524
|
import { cn } from "../../../lib/utils";
|
|
11476
11525
|
import { Button } from "../button";
|
|
11477
11526
|
import { Badge } from "../badge";
|
|
11478
|
-
import { CircleCheck } from "lucide-react";
|
|
11527
|
+
import { CircleCheck, Info } from "lucide-react";
|
|
11479
11528
|
import type { PricingCardProps } from "./types";
|
|
11480
11529
|
|
|
11481
11530
|
/**
|
|
@@ -11516,6 +11565,7 @@ const PricingCard = React.forwardRef<HTMLDivElement, PricingCardProps>(
|
|
|
11516
11565
|
onFeatureDetails,
|
|
11517
11566
|
addon,
|
|
11518
11567
|
usageDetails,
|
|
11568
|
+
infoText,
|
|
11519
11569
|
className,
|
|
11520
11570
|
...props
|
|
11521
11571
|
},
|
|
@@ -11608,6 +11658,16 @@ const PricingCard = React.forwardRef<HTMLDivElement, PricingCardProps>(
|
|
|
11608
11658
|
{buttonText}
|
|
11609
11659
|
</Button>
|
|
11610
11660
|
</div>
|
|
11661
|
+
|
|
11662
|
+
{/* Info text */}
|
|
11663
|
+
{infoText && (
|
|
11664
|
+
<div className="flex items-start gap-1.5">
|
|
11665
|
+
<Info className="size-3.5 text-semantic-info-primary shrink-0 mt-0.5" />
|
|
11666
|
+
<p className="text-xs text-semantic-info-primary tracking-[0.035px] m-0">
|
|
11667
|
+
{infoText}
|
|
11668
|
+
</p>
|
|
11669
|
+
</div>
|
|
11670
|
+
)}
|
|
11611
11671
|
</div>
|
|
11612
11672
|
|
|
11613
11673
|
{/* Features */}
|
|
@@ -11899,6 +11959,8 @@ export interface PricingCardProps
|
|
|
11899
11959
|
addon?: PricingCardAddon;
|
|
11900
11960
|
/** Usage details displayed in a bulleted list at the bottom (e.g., AIO plan) */
|
|
11901
11961
|
usageDetails?: UsageDetail[];
|
|
11962
|
+
/** Informational text shown below the CTA button (e.g., "Your package change will be effective from 23-03-2026") */
|
|
11963
|
+
infoText?: string;
|
|
11902
11964
|
}
|
|
11903
11965
|
`, prefix)
|
|
11904
11966
|
},
|
|
@@ -13160,7 +13222,7 @@ const FileUploadModal = React.forwardRef<HTMLDivElement, FileUploadModalProps>(
|
|
|
13160
13222
|
dropDescription = "or drag and drop file here",
|
|
13161
13223
|
saveLabel = "Save",
|
|
13162
13224
|
cancelLabel = "Cancel",
|
|
13163
|
-
|
|
13225
|
+
loading = false,
|
|
13164
13226
|
className,
|
|
13165
13227
|
...props
|
|
13166
13228
|
},
|
|
@@ -13442,7 +13504,7 @@ const FileUploadModal = React.forwardRef<HTMLDivElement, FileUploadModalProps>(
|
|
|
13442
13504
|
className="w-full sm:w-auto"
|
|
13443
13505
|
onClick={handleSave}
|
|
13444
13506
|
disabled={!hasCompleted || hasUploading}
|
|
13445
|
-
loading={
|
|
13507
|
+
loading={loading}
|
|
13446
13508
|
>
|
|
13447
13509
|
{saveLabel}
|
|
13448
13510
|
</Button>
|
|
@@ -13495,7 +13557,8 @@ export interface FileUploadModalProps
|
|
|
13495
13557
|
dropDescription?: string;
|
|
13496
13558
|
saveLabel?: string;
|
|
13497
13559
|
cancelLabel?: string;
|
|
13498
|
-
|
|
13560
|
+
/** Shows a loading spinner on the save button (e.g. while processing files server-side) */
|
|
13561
|
+
loading?: boolean;
|
|
13499
13562
|
}
|
|
13500
13563
|
`, prefix)
|
|
13501
13564
|
},
|
|
@@ -13572,12 +13635,14 @@ function StyledTextarea({
|
|
|
13572
13635
|
value,
|
|
13573
13636
|
rows = 3,
|
|
13574
13637
|
onChange,
|
|
13638
|
+
disabled,
|
|
13575
13639
|
className,
|
|
13576
13640
|
}: {
|
|
13577
13641
|
placeholder?: string;
|
|
13578
13642
|
value?: string;
|
|
13579
13643
|
rows?: number;
|
|
13580
13644
|
onChange?: (v: string) => void;
|
|
13645
|
+
disabled?: boolean;
|
|
13581
13646
|
className?: string;
|
|
13582
13647
|
}) {
|
|
13583
13648
|
return (
|
|
@@ -13586,12 +13651,14 @@ function StyledTextarea({
|
|
|
13586
13651
|
rows={rows}
|
|
13587
13652
|
onChange={(e) => onChange?.(e.target.value)}
|
|
13588
13653
|
placeholder={placeholder}
|
|
13654
|
+
disabled={disabled}
|
|
13589
13655
|
className={cn(
|
|
13590
13656
|
"w-full px-4 py-2.5 text-base rounded border resize-none",
|
|
13591
13657
|
"border-semantic-border-input bg-semantic-bg-primary",
|
|
13592
13658
|
"text-semantic-text-primary placeholder:text-semantic-text-muted",
|
|
13593
13659
|
"outline-none hover:border-semantic-border-input-focus",
|
|
13594
13660
|
"focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
13661
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
13595
13662
|
className
|
|
13596
13663
|
)}
|
|
13597
13664
|
/>
|
|
@@ -13620,9 +13687,11 @@ function Field({
|
|
|
13620
13687
|
function FallbackPromptsAccordion({
|
|
13621
13688
|
data,
|
|
13622
13689
|
onChange,
|
|
13690
|
+
disabled,
|
|
13623
13691
|
}: {
|
|
13624
13692
|
data: Partial<IvrBotConfigData>;
|
|
13625
13693
|
onChange: (patch: Partial<IvrBotConfigData>) => void;
|
|
13694
|
+
disabled?: boolean;
|
|
13626
13695
|
}) {
|
|
13627
13696
|
return (
|
|
13628
13697
|
<div className="bg-semantic-bg-primary border border-semantic-border-layout rounded-lg overflow-hidden">
|
|
@@ -13641,6 +13710,7 @@ function FallbackPromptsAccordion({
|
|
|
13641
13710
|
value={data.agentBusyPrompt ?? ""}
|
|
13642
13711
|
onChange={(v) => onChange({ agentBusyPrompt: v })}
|
|
13643
13712
|
placeholder="Executives are busy at the moment, we will connect you soon."
|
|
13713
|
+
disabled={disabled}
|
|
13644
13714
|
/>
|
|
13645
13715
|
</Field>
|
|
13646
13716
|
<Field label="No Extension Found">
|
|
@@ -13648,6 +13718,7 @@ function FallbackPromptsAccordion({
|
|
|
13648
13718
|
value={data.noExtensionPrompt ?? ""}
|
|
13649
13719
|
onChange={(v) => onChange({ noExtensionPrompt: v })}
|
|
13650
13720
|
placeholder="Sorry, the requested extension is currently unavailable. Let me help you directly."
|
|
13721
|
+
disabled={disabled}
|
|
13651
13722
|
/>
|
|
13652
13723
|
</Field>
|
|
13653
13724
|
</div>
|
|
@@ -13699,10 +13770,14 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13699
13770
|
onEditFunction,
|
|
13700
13771
|
onDeleteFunction,
|
|
13701
13772
|
onTestApi,
|
|
13773
|
+
functionsInfoTooltip,
|
|
13774
|
+
functionPromptMinLength,
|
|
13775
|
+
functionPromptMaxLength,
|
|
13702
13776
|
onBack,
|
|
13703
13777
|
onPlayVoice,
|
|
13704
13778
|
onPauseVoice,
|
|
13705
13779
|
playingVoice,
|
|
13780
|
+
disabled,
|
|
13706
13781
|
roleOptions,
|
|
13707
13782
|
toneOptions,
|
|
13708
13783
|
voiceOptions,
|
|
@@ -13755,12 +13830,14 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13755
13830
|
<Button
|
|
13756
13831
|
variant="outline"
|
|
13757
13832
|
onClick={() => onSaveAsDraft?.(data)}
|
|
13833
|
+
disabled={disabled}
|
|
13758
13834
|
>
|
|
13759
13835
|
Save as Draft
|
|
13760
13836
|
</Button>
|
|
13761
13837
|
<Button
|
|
13762
13838
|
variant="default"
|
|
13763
13839
|
onClick={() => onPublish?.(data)}
|
|
13840
|
+
disabled={disabled}
|
|
13764
13841
|
>
|
|
13765
13842
|
Publish Bot
|
|
13766
13843
|
</Button>
|
|
@@ -13782,13 +13859,15 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13782
13859
|
toneOptions={toneOptions}
|
|
13783
13860
|
voiceOptions={voiceOptions}
|
|
13784
13861
|
languageOptions={languageOptions}
|
|
13862
|
+
disabled={disabled}
|
|
13785
13863
|
/>
|
|
13786
13864
|
<BotBehaviorCard
|
|
13787
13865
|
data={data}
|
|
13788
13866
|
onChange={update}
|
|
13789
13867
|
sessionVariables={sessionVariables}
|
|
13868
|
+
disabled={disabled}
|
|
13790
13869
|
/>
|
|
13791
|
-
<FallbackPromptsAccordion data={data} onChange={update} />
|
|
13870
|
+
<FallbackPromptsAccordion data={data} onChange={update} disabled={disabled} />
|
|
13792
13871
|
</div>
|
|
13793
13872
|
|
|
13794
13873
|
{/* Right column \u2014 gray panel extending full height */}
|
|
@@ -13797,6 +13876,7 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13797
13876
|
files={data.knowledgeBaseFiles}
|
|
13798
13877
|
onAdd={() => setUploadOpen(true)}
|
|
13799
13878
|
onDownload={onDownloadKnowledgeFile}
|
|
13879
|
+
disabled={disabled}
|
|
13800
13880
|
onDelete={(id) => {
|
|
13801
13881
|
update({
|
|
13802
13882
|
knowledgeBaseFiles: data.knowledgeBaseFiles.filter(
|
|
@@ -13810,6 +13890,8 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13810
13890
|
functions={data.functions}
|
|
13811
13891
|
onAddFunction={() => setCreateFnOpen(true)}
|
|
13812
13892
|
onEditFunction={onEditFunction}
|
|
13893
|
+
infoTooltip={functionsInfoTooltip}
|
|
13894
|
+
disabled={disabled}
|
|
13813
13895
|
onDeleteFunction={(id) => {
|
|
13814
13896
|
update({
|
|
13815
13897
|
functions: data.functions.filter((f) => f.id !== id),
|
|
@@ -13821,6 +13903,7 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13821
13903
|
data={data}
|
|
13822
13904
|
onChange={update}
|
|
13823
13905
|
departmentOptions={escalationDepartmentOptions}
|
|
13906
|
+
disabled={disabled}
|
|
13824
13907
|
/>
|
|
13825
13908
|
<AdvancedSettingsCard
|
|
13826
13909
|
data={data}
|
|
@@ -13829,6 +13912,7 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13829
13912
|
silenceTimeoutMax={silenceTimeoutMax}
|
|
13830
13913
|
callEndThresholdMin={callEndThresholdMin}
|
|
13831
13914
|
callEndThresholdMax={callEndThresholdMax}
|
|
13915
|
+
disabled={disabled}
|
|
13832
13916
|
/>
|
|
13833
13917
|
</div>
|
|
13834
13918
|
</div>
|
|
@@ -13839,6 +13923,8 @@ export const IvrBotConfig = React.forwardRef<HTMLDivElement, IvrBotConfigProps>(
|
|
|
13839
13923
|
onOpenChange={setCreateFnOpen}
|
|
13840
13924
|
onSubmit={handleCreateFunction}
|
|
13841
13925
|
onTestApi={onTestApi}
|
|
13926
|
+
promptMinLength={functionPromptMinLength}
|
|
13927
|
+
promptMaxLength={functionPromptMaxLength}
|
|
13842
13928
|
/>
|
|
13843
13929
|
|
|
13844
13930
|
{/* File Upload Modal */}
|
|
@@ -13878,6 +13964,7 @@ import type {
|
|
|
13878
13964
|
} from "./types";
|
|
13879
13965
|
|
|
13880
13966
|
const HTTP_METHODS: HttpMethod[] = ["GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
13967
|
+
const METHODS_WITH_BODY: HttpMethod[] = ["POST", "PUT", "PATCH"];
|
|
13881
13968
|
const FUNCTION_NAME_MAX = 30;
|
|
13882
13969
|
const BODY_MAX = 4000;
|
|
13883
13970
|
|
|
@@ -14033,6 +14120,8 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14033
14120
|
onOpenChange,
|
|
14034
14121
|
onSubmit,
|
|
14035
14122
|
onTestApi,
|
|
14123
|
+
promptMinLength = 100,
|
|
14124
|
+
promptMaxLength = 5000,
|
|
14036
14125
|
initialStep = 1,
|
|
14037
14126
|
initialTab = "header",
|
|
14038
14127
|
className,
|
|
@@ -14072,8 +14161,17 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14072
14161
|
onOpenChange(false);
|
|
14073
14162
|
}, [reset, onOpenChange]);
|
|
14074
14163
|
|
|
14164
|
+
const supportsBody = METHODS_WITH_BODY.includes(method);
|
|
14165
|
+
|
|
14166
|
+
// When switching to a method without body, reset to header tab if body was active
|
|
14167
|
+
React.useEffect(() => {
|
|
14168
|
+
if (!supportsBody && activeTab === "body") {
|
|
14169
|
+
setActiveTab("header");
|
|
14170
|
+
}
|
|
14171
|
+
}, [supportsBody, activeTab]);
|
|
14172
|
+
|
|
14075
14173
|
const handleNext = () => {
|
|
14076
|
-
if (name.trim() && prompt.trim()) setStep(2);
|
|
14174
|
+
if (name.trim() && prompt.trim().length >= promptMinLength) setStep(2);
|
|
14077
14175
|
};
|
|
14078
14176
|
|
|
14079
14177
|
const handleSubmit = () => {
|
|
@@ -14109,7 +14207,7 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14109
14207
|
};
|
|
14110
14208
|
|
|
14111
14209
|
const isStep1Valid =
|
|
14112
|
-
name.trim().length > 0 && prompt.trim().length
|
|
14210
|
+
name.trim().length > 0 && prompt.trim().length >= promptMinLength;
|
|
14113
14211
|
|
|
14114
14212
|
const tabLabels: Record<FunctionTabType, string> = {
|
|
14115
14213
|
header: \`Header (\${headers.length})\`,
|
|
@@ -14117,6 +14215,10 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14117
14215
|
body: "Body",
|
|
14118
14216
|
};
|
|
14119
14217
|
|
|
14218
|
+
const visibleTabs: FunctionTabType[] = supportsBody
|
|
14219
|
+
? ["header", "queryParams", "body"]
|
|
14220
|
+
: ["header", "queryParams"];
|
|
14221
|
+
|
|
14120
14222
|
return (
|
|
14121
14223
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
14122
14224
|
<DialogContent
|
|
@@ -14181,14 +14283,25 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14181
14283
|
Prompt{" "}
|
|
14182
14284
|
<span className="text-semantic-error-primary">*</span>
|
|
14183
14285
|
</label>
|
|
14184
|
-
<
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
|
|
14286
|
+
<div className="relative">
|
|
14287
|
+
<textarea
|
|
14288
|
+
id="fn-prompt"
|
|
14289
|
+
value={prompt}
|
|
14290
|
+
maxLength={promptMaxLength}
|
|
14291
|
+
onChange={(e) => setPrompt(e.target.value)}
|
|
14292
|
+
placeholder="Enter the description of the function"
|
|
14293
|
+
rows={5}
|
|
14294
|
+
className={cn(textareaCls, "pb-7")}
|
|
14295
|
+
/>
|
|
14296
|
+
<span className="absolute bottom-2 right-3 text-xs italic text-semantic-text-muted pointer-events-none">
|
|
14297
|
+
{prompt.length}/{promptMaxLength}
|
|
14298
|
+
</span>
|
|
14299
|
+
</div>
|
|
14300
|
+
{prompt.length > 0 && prompt.trim().length < promptMinLength && (
|
|
14301
|
+
<p className="m-0 text-xs text-semantic-error-primary">
|
|
14302
|
+
Minimum {promptMinLength} characters required
|
|
14303
|
+
</p>
|
|
14304
|
+
)}
|
|
14192
14305
|
</div>
|
|
14193
14306
|
</div>
|
|
14194
14307
|
)}
|
|
@@ -14250,9 +14363,7 @@ export const CreateFunctionModal = React.forwardRef<
|
|
|
14250
14363
|
"[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"
|
|
14251
14364
|
)}
|
|
14252
14365
|
>
|
|
14253
|
-
{(
|
|
14254
|
-
["header", "queryParams", "body"] as FunctionTabType[]
|
|
14255
|
-
).map((tab) => (
|
|
14366
|
+
{visibleTabs.map((tab) => (
|
|
14256
14367
|
<button
|
|
14257
14368
|
key={tab}
|
|
14258
14369
|
type="button"
|
|
@@ -14452,6 +14563,8 @@ export interface BotIdentityCardProps {
|
|
|
14452
14563
|
onPauseVoice?: (voiceValue: string) => void;
|
|
14453
14564
|
/** The voice value currently being played. Controls play/pause icon state. */
|
|
14454
14565
|
playingVoice?: string;
|
|
14566
|
+
/** Disables all fields in the card (view mode) */
|
|
14567
|
+
disabled?: boolean;
|
|
14455
14568
|
/** Additional className for the card */
|
|
14456
14569
|
className?: string;
|
|
14457
14570
|
}
|
|
@@ -14492,11 +14605,13 @@ function StyledInput({
|
|
|
14492
14605
|
placeholder,
|
|
14493
14606
|
value,
|
|
14494
14607
|
onChange,
|
|
14608
|
+
disabled,
|
|
14495
14609
|
className,
|
|
14496
14610
|
}: {
|
|
14497
14611
|
placeholder?: string;
|
|
14498
14612
|
value?: string;
|
|
14499
14613
|
onChange?: (v: string) => void;
|
|
14614
|
+
disabled?: boolean;
|
|
14500
14615
|
className?: string;
|
|
14501
14616
|
}) {
|
|
14502
14617
|
return (
|
|
@@ -14505,12 +14620,14 @@ function StyledInput({
|
|
|
14505
14620
|
value={value ?? ""}
|
|
14506
14621
|
onChange={(e) => onChange?.(e.target.value)}
|
|
14507
14622
|
placeholder={placeholder}
|
|
14623
|
+
disabled={disabled}
|
|
14508
14624
|
className={cn(
|
|
14509
14625
|
"w-full h-[42px] px-4 text-base rounded border",
|
|
14510
14626
|
"border-semantic-border-input bg-semantic-bg-primary",
|
|
14511
14627
|
"text-semantic-text-primary placeholder:text-semantic-text-muted",
|
|
14512
14628
|
"outline-none hover:border-semantic-border-input-focus",
|
|
14513
14629
|
"focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
14630
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
14514
14631
|
className
|
|
14515
14632
|
)}
|
|
14516
14633
|
/>
|
|
@@ -14573,6 +14690,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14573
14690
|
onPlayVoice,
|
|
14574
14691
|
onPauseVoice,
|
|
14575
14692
|
playingVoice,
|
|
14693
|
+
disabled,
|
|
14576
14694
|
className,
|
|
14577
14695
|
},
|
|
14578
14696
|
ref
|
|
@@ -14603,6 +14721,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14603
14721
|
placeholder="e.g., Rhea from CaratLane"
|
|
14604
14722
|
value={data.botName}
|
|
14605
14723
|
onChange={(v) => onChange({ botName: v })}
|
|
14724
|
+
disabled={disabled}
|
|
14606
14725
|
/>
|
|
14607
14726
|
</Field>
|
|
14608
14727
|
|
|
@@ -14613,6 +14732,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14613
14732
|
options={roleOptions}
|
|
14614
14733
|
placeholder="e.g., Customer Support Agent"
|
|
14615
14734
|
creatableHint="Type to create a custom role"
|
|
14735
|
+
disabled={disabled}
|
|
14616
14736
|
/>
|
|
14617
14737
|
</Field>
|
|
14618
14738
|
|
|
@@ -14623,6 +14743,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14623
14743
|
options={toneOptions}
|
|
14624
14744
|
placeholder="Enter or select tone"
|
|
14625
14745
|
creatableHint="Type to create a custom tone"
|
|
14746
|
+
disabled={disabled}
|
|
14626
14747
|
/>
|
|
14627
14748
|
</Field>
|
|
14628
14749
|
|
|
@@ -14634,6 +14755,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14634
14755
|
onChange({ voice: v });
|
|
14635
14756
|
onPauseVoice?.(v);
|
|
14636
14757
|
}}
|
|
14758
|
+
disabled={disabled}
|
|
14637
14759
|
>
|
|
14638
14760
|
<SelectTrigger>
|
|
14639
14761
|
<SelectValue placeholder="Select voice">
|
|
@@ -14688,6 +14810,7 @@ const BotIdentityCard = React.forwardRef<HTMLDivElement, BotIdentityCardProps>(
|
|
|
14688
14810
|
<Select
|
|
14689
14811
|
value={data.language || undefined}
|
|
14690
14812
|
onValueChange={(v) => onChange({ language: v })}
|
|
14813
|
+
disabled={disabled}
|
|
14691
14814
|
>
|
|
14692
14815
|
<SelectTrigger>
|
|
14693
14816
|
<SelectValue placeholder="Select language" />
|
|
@@ -14733,6 +14856,8 @@ export interface BotBehaviorCardProps {
|
|
|
14733
14856
|
onChange: (patch: Partial<BotBehaviorData>) => void;
|
|
14734
14857
|
/** Session variables shown as insertable chips */
|
|
14735
14858
|
sessionVariables?: string[];
|
|
14859
|
+
/** Disables all fields in the card (view mode) */
|
|
14860
|
+
disabled?: boolean;
|
|
14736
14861
|
/** Additional className for the card */
|
|
14737
14862
|
className?: string;
|
|
14738
14863
|
}
|
|
@@ -14778,12 +14903,14 @@ function StyledTextarea({
|
|
|
14778
14903
|
value,
|
|
14779
14904
|
rows = 3,
|
|
14780
14905
|
onChange,
|
|
14906
|
+
disabled,
|
|
14781
14907
|
className,
|
|
14782
14908
|
}: {
|
|
14783
14909
|
placeholder?: string;
|
|
14784
14910
|
value?: string;
|
|
14785
14911
|
rows?: number;
|
|
14786
14912
|
onChange?: (v: string) => void;
|
|
14913
|
+
disabled?: boolean;
|
|
14787
14914
|
className?: string;
|
|
14788
14915
|
}) {
|
|
14789
14916
|
return (
|
|
@@ -14792,12 +14919,14 @@ function StyledTextarea({
|
|
|
14792
14919
|
rows={rows}
|
|
14793
14920
|
onChange={(e) => onChange?.(e.target.value)}
|
|
14794
14921
|
placeholder={placeholder}
|
|
14922
|
+
disabled={disabled}
|
|
14795
14923
|
className={cn(
|
|
14796
14924
|
"w-full px-4 py-2.5 text-base rounded border resize-none",
|
|
14797
14925
|
"border-semantic-border-input bg-semantic-bg-primary",
|
|
14798
14926
|
"text-semantic-text-primary placeholder:text-semantic-text-muted",
|
|
14799
14927
|
"outline-none hover:border-semantic-border-input-focus",
|
|
14800
14928
|
"focus:border-semantic-border-input-focus focus:shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
14929
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
14801
14930
|
className
|
|
14802
14931
|
)}
|
|
14803
14932
|
/>
|
|
@@ -14812,6 +14941,7 @@ const BotBehaviorCard = React.forwardRef<HTMLDivElement, BotBehaviorCardProps>(
|
|
|
14812
14941
|
data,
|
|
14813
14942
|
onChange,
|
|
14814
14943
|
sessionVariables = DEFAULT_SESSION_VARIABLES,
|
|
14944
|
+
disabled,
|
|
14815
14945
|
className,
|
|
14816
14946
|
},
|
|
14817
14947
|
ref
|
|
@@ -14838,6 +14968,7 @@ const BotBehaviorCard = React.forwardRef<HTMLDivElement, BotBehaviorCardProps>(
|
|
|
14838
14968
|
if (v.length <= MAX) onChange({ systemPrompt: v });
|
|
14839
14969
|
}}
|
|
14840
14970
|
placeholder="You are a helpful assistant. Always start by greeting the user politely: 'Hello! Welcome. How can I assist you today?'"
|
|
14971
|
+
disabled={disabled}
|
|
14841
14972
|
className="pb-8"
|
|
14842
14973
|
/>
|
|
14843
14974
|
<span className="absolute bottom-2.5 right-3 text-sm text-semantic-text-muted">
|
|
@@ -14856,7 +14987,8 @@ const BotBehaviorCard = React.forwardRef<HTMLDivElement, BotBehaviorCardProps>(
|
|
|
14856
14987
|
key={v}
|
|
14857
14988
|
type="button"
|
|
14858
14989
|
onClick={() => insertVariable(v)}
|
|
14859
|
-
|
|
14990
|
+
disabled={disabled}
|
|
14991
|
+
className={cn(tagVariants(), "gap-1.5 cursor-pointer hover:opacity-80 transition-opacity", disabled && "opacity-50 cursor-not-allowed")}
|
|
14860
14992
|
>
|
|
14861
14993
|
<Plus className="size-3 shrink-0" />
|
|
14862
14994
|
{v}
|
|
@@ -14893,6 +15025,8 @@ export interface KnowledgeBaseCardProps {
|
|
|
14893
15025
|
onDownload?: (id: string) => void;
|
|
14894
15026
|
/** Called when user clicks the delete button on a file */
|
|
14895
15027
|
onDelete?: (id: string) => void;
|
|
15028
|
+
/** Disables all interactive elements in the card (view mode) */
|
|
15029
|
+
disabled?: boolean;
|
|
14896
15030
|
/** Additional className */
|
|
14897
15031
|
className?: string;
|
|
14898
15032
|
}
|
|
@@ -14916,6 +15050,7 @@ const KnowledgeBaseCard = React.forwardRef<HTMLDivElement, KnowledgeBaseCardProp
|
|
|
14916
15050
|
onAdd,
|
|
14917
15051
|
onDownload,
|
|
14918
15052
|
onDelete,
|
|
15053
|
+
disabled,
|
|
14919
15054
|
className,
|
|
14920
15055
|
},
|
|
14921
15056
|
ref
|
|
@@ -14939,7 +15074,8 @@ const KnowledgeBaseCard = React.forwardRef<HTMLDivElement, KnowledgeBaseCardProp
|
|
|
14939
15074
|
<button
|
|
14940
15075
|
type="button"
|
|
14941
15076
|
onClick={() => onAdd?.()}
|
|
14942
|
-
|
|
15077
|
+
disabled={disabled}
|
|
15078
|
+
className={cn("inline-flex items-center gap-1.5 px-4 py-1.5 rounded text-xs font-semibold text-semantic-text-secondary bg-semantic-primary-surface hover:bg-semantic-bg-hover transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
14943
15079
|
>
|
|
14944
15080
|
<Plus className="size-3.5" />
|
|
14945
15081
|
Files
|
|
@@ -14976,7 +15112,8 @@ const KnowledgeBaseCard = React.forwardRef<HTMLDivElement, KnowledgeBaseCardProp
|
|
|
14976
15112
|
<button
|
|
14977
15113
|
type="button"
|
|
14978
15114
|
onClick={() => onDownload?.(file.id)}
|
|
14979
|
-
|
|
15115
|
+
disabled={disabled}
|
|
15116
|
+
className={cn("p-2 rounded text-semantic-text-muted hover:text-semantic-text-primary hover:bg-semantic-bg-hover transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
14980
15117
|
aria-label="Download file"
|
|
14981
15118
|
>
|
|
14982
15119
|
<Download className="size-4" />
|
|
@@ -14984,7 +15121,8 @@ const KnowledgeBaseCard = React.forwardRef<HTMLDivElement, KnowledgeBaseCardProp
|
|
|
14984
15121
|
<button
|
|
14985
15122
|
type="button"
|
|
14986
15123
|
onClick={() => onDelete?.(file.id)}
|
|
14987
|
-
|
|
15124
|
+
disabled={disabled}
|
|
15125
|
+
className={cn("p-2 rounded text-semantic-text-muted hover:text-semantic-error-primary hover:bg-semantic-error-surface transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
14988
15126
|
aria-label="Delete file"
|
|
14989
15127
|
>
|
|
14990
15128
|
<Trash2 className="size-4" />
|
|
@@ -15011,6 +15149,12 @@ export { KnowledgeBaseCard };
|
|
|
15011
15149
|
import { Info, Pencil, Plus, Trash2 } from "lucide-react";
|
|
15012
15150
|
import { cn } from "../../../lib/utils";
|
|
15013
15151
|
import { Badge } from "../badge";
|
|
15152
|
+
import {
|
|
15153
|
+
Tooltip,
|
|
15154
|
+
TooltipContent,
|
|
15155
|
+
TooltipProvider,
|
|
15156
|
+
TooltipTrigger,
|
|
15157
|
+
} from "../tooltip";
|
|
15014
15158
|
import type { FunctionItem } from "./types";
|
|
15015
15159
|
|
|
15016
15160
|
// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -15024,6 +15168,10 @@ export interface FunctionsCardProps {
|
|
|
15024
15168
|
onEditFunction?: (id: string) => void;
|
|
15025
15169
|
/** Called when user deletes a custom (non-built-in) function */
|
|
15026
15170
|
onDeleteFunction?: (id: string) => void;
|
|
15171
|
+
/** Hover text shown on the info icon next to the "Functions" title */
|
|
15172
|
+
infoTooltip?: string;
|
|
15173
|
+
/** Disables all interactive elements in the card (view mode) */
|
|
15174
|
+
disabled?: boolean;
|
|
15027
15175
|
/** Additional className */
|
|
15028
15176
|
className?: string;
|
|
15029
15177
|
}
|
|
@@ -15031,7 +15179,7 @@ export interface FunctionsCardProps {
|
|
|
15031
15179
|
// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
15032
15180
|
|
|
15033
15181
|
const FunctionsCard = React.forwardRef<HTMLDivElement, FunctionsCardProps>(
|
|
15034
|
-
({ functions, onAddFunction, onEditFunction, onDeleteFunction, className }, ref) => {
|
|
15182
|
+
({ functions, onAddFunction, onEditFunction, onDeleteFunction, infoTooltip, disabled, className }, ref) => {
|
|
15035
15183
|
return (
|
|
15036
15184
|
<div
|
|
15037
15185
|
ref={ref}
|
|
@@ -15046,12 +15194,24 @@ const FunctionsCard = React.forwardRef<HTMLDivElement, FunctionsCardProps>(
|
|
|
15046
15194
|
<h2 className="m-0 text-base font-semibold text-semantic-text-primary">
|
|
15047
15195
|
Functions
|
|
15048
15196
|
</h2>
|
|
15049
|
-
|
|
15197
|
+
{infoTooltip ? (
|
|
15198
|
+
<TooltipProvider delayDuration={200}>
|
|
15199
|
+
<Tooltip>
|
|
15200
|
+
<TooltipTrigger asChild>
|
|
15201
|
+
<Info className="size-3.5 text-semantic-text-muted shrink-0 cursor-help" />
|
|
15202
|
+
</TooltipTrigger>
|
|
15203
|
+
<TooltipContent>{infoTooltip}</TooltipContent>
|
|
15204
|
+
</Tooltip>
|
|
15205
|
+
</TooltipProvider>
|
|
15206
|
+
) : (
|
|
15207
|
+
<Info className="size-3.5 text-semantic-text-muted shrink-0" />
|
|
15208
|
+
)}
|
|
15050
15209
|
</div>
|
|
15051
15210
|
<button
|
|
15052
15211
|
type="button"
|
|
15053
15212
|
onClick={onAddFunction}
|
|
15054
|
-
|
|
15213
|
+
disabled={disabled}
|
|
15214
|
+
className={cn("inline-flex items-center gap-1.5 px-4 py-1.5 rounded text-xs font-semibold text-semantic-text-secondary bg-semantic-primary-surface hover:bg-semantic-bg-hover transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
15055
15215
|
>
|
|
15056
15216
|
<Plus className="size-3.5" />
|
|
15057
15217
|
Functions
|
|
@@ -15071,7 +15231,18 @@ const FunctionsCard = React.forwardRef<HTMLDivElement, FunctionsCardProps>(
|
|
|
15071
15231
|
className="flex items-center justify-between px-4 py-3 rounded border border-semantic-border-layout bg-semantic-bg-primary"
|
|
15072
15232
|
>
|
|
15073
15233
|
<div className="flex items-center gap-2 min-w-0">
|
|
15074
|
-
|
|
15234
|
+
{fn.tooltip ? (
|
|
15235
|
+
<TooltipProvider delayDuration={200}>
|
|
15236
|
+
<Tooltip>
|
|
15237
|
+
<TooltipTrigger asChild>
|
|
15238
|
+
<Info className="size-4 text-semantic-text-muted shrink-0 cursor-help" />
|
|
15239
|
+
</TooltipTrigger>
|
|
15240
|
+
<TooltipContent>{fn.tooltip}</TooltipContent>
|
|
15241
|
+
</Tooltip>
|
|
15242
|
+
</TooltipProvider>
|
|
15243
|
+
) : (
|
|
15244
|
+
<Info className="size-4 text-semantic-text-muted shrink-0" />
|
|
15245
|
+
)}
|
|
15075
15246
|
<span className="text-sm text-semantic-text-primary truncate">
|
|
15076
15247
|
{fn.name}
|
|
15077
15248
|
</span>
|
|
@@ -15086,7 +15257,8 @@ const FunctionsCard = React.forwardRef<HTMLDivElement, FunctionsCardProps>(
|
|
|
15086
15257
|
<button
|
|
15087
15258
|
type="button"
|
|
15088
15259
|
onClick={() => onEditFunction?.(fn.id)}
|
|
15089
|
-
|
|
15260
|
+
disabled={disabled}
|
|
15261
|
+
className={cn("p-1.5 rounded text-semantic-text-muted hover:text-semantic-text-primary hover:bg-semantic-bg-hover transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
15090
15262
|
aria-label={\`Edit \${fn.name}\`}
|
|
15091
15263
|
>
|
|
15092
15264
|
<Pencil className="size-4" />
|
|
@@ -15094,7 +15266,8 @@ const FunctionsCard = React.forwardRef<HTMLDivElement, FunctionsCardProps>(
|
|
|
15094
15266
|
<button
|
|
15095
15267
|
type="button"
|
|
15096
15268
|
onClick={() => onDeleteFunction?.(fn.id)}
|
|
15097
|
-
|
|
15269
|
+
disabled={disabled}
|
|
15270
|
+
className={cn("p-1.5 rounded text-semantic-text-muted hover:text-semantic-error-primary hover:bg-semantic-error-surface transition-colors", disabled && "opacity-50 cursor-not-allowed")}
|
|
15098
15271
|
aria-label={\`Delete \${fn.name}\`}
|
|
15099
15272
|
>
|
|
15100
15273
|
<Trash2 className="size-4" />
|
|
@@ -15161,6 +15334,8 @@ export interface FrustrationHandoverCardProps {
|
|
|
15161
15334
|
onChange: (patch: Partial<FrustrationHandoverData>) => void;
|
|
15162
15335
|
/** Available escalation department options */
|
|
15163
15336
|
departmentOptions?: DepartmentOption[];
|
|
15337
|
+
/** Disables all fields in the card (view mode) */
|
|
15338
|
+
disabled?: boolean;
|
|
15164
15339
|
/** Additional className */
|
|
15165
15340
|
className?: string;
|
|
15166
15341
|
}
|
|
@@ -15187,7 +15362,7 @@ function Field({
|
|
|
15187
15362
|
// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
15188
15363
|
|
|
15189
15364
|
const FrustrationHandoverCard = React.forwardRef<HTMLDivElement, FrustrationHandoverCardProps>(
|
|
15190
|
-
({ data, onChange, departmentOptions = DEFAULT_DEPARTMENT_OPTIONS, className }, ref) => {
|
|
15365
|
+
({ data, onChange, departmentOptions = DEFAULT_DEPARTMENT_OPTIONS, disabled, className }, ref) => {
|
|
15191
15366
|
return (
|
|
15192
15367
|
<div
|
|
15193
15368
|
ref={ref}
|
|
@@ -15215,6 +15390,7 @@ const FrustrationHandoverCard = React.forwardRef<HTMLDivElement, FrustrationHand
|
|
|
15215
15390
|
onCheckedChange={(v) =>
|
|
15216
15391
|
onChange({ frustrationHandoverEnabled: v })
|
|
15217
15392
|
}
|
|
15393
|
+
disabled={disabled}
|
|
15218
15394
|
/>
|
|
15219
15395
|
</div>
|
|
15220
15396
|
<div className="px-4 pb-2 sm:px-6">
|
|
@@ -15222,7 +15398,7 @@ const FrustrationHandoverCard = React.forwardRef<HTMLDivElement, FrustrationHand
|
|
|
15222
15398
|
<Select
|
|
15223
15399
|
value={data.escalationDepartment || undefined}
|
|
15224
15400
|
onValueChange={(v) => onChange({ escalationDepartment: v })}
|
|
15225
|
-
disabled={!data.frustrationHandoverEnabled}
|
|
15401
|
+
disabled={disabled || !data.frustrationHandoverEnabled}
|
|
15226
15402
|
>
|
|
15227
15403
|
<SelectTrigger>
|
|
15228
15404
|
<SelectValue placeholder="Select a department" />
|
|
@@ -15284,6 +15460,8 @@ export interface AdvancedSettingsCardProps {
|
|
|
15284
15460
|
callEndThresholdMin?: number;
|
|
15285
15461
|
/** Max value for call end threshold spinner (default: 10) */
|
|
15286
15462
|
callEndThresholdMax?: number;
|
|
15463
|
+
/** Disables all fields in the card (view mode) */
|
|
15464
|
+
disabled?: boolean;
|
|
15287
15465
|
/** Additional className */
|
|
15288
15466
|
className?: string;
|
|
15289
15467
|
}
|
|
@@ -15312,27 +15490,31 @@ function NumberSpinner({
|
|
|
15312
15490
|
onChange,
|
|
15313
15491
|
min = 0,
|
|
15314
15492
|
max = 999,
|
|
15493
|
+
disabled,
|
|
15315
15494
|
}: {
|
|
15316
15495
|
value: number;
|
|
15317
15496
|
onChange: (v: number) => void;
|
|
15318
15497
|
min?: number;
|
|
15319
15498
|
max?: number;
|
|
15499
|
+
disabled?: boolean;
|
|
15320
15500
|
}) {
|
|
15321
15501
|
return (
|
|
15322
|
-
<div className="flex w-full items-center gap-2.5 px-4 py-2.5 border border-semantic-border-layout bg-semantic-bg-primary rounded">
|
|
15502
|
+
<div className={cn("flex w-full items-center gap-2.5 px-4 py-2.5 border border-semantic-border-layout bg-semantic-bg-primary rounded", disabled && "opacity-50 cursor-not-allowed")}>
|
|
15323
15503
|
<input
|
|
15324
15504
|
type="number"
|
|
15325
15505
|
value={value}
|
|
15326
15506
|
min={min}
|
|
15327
15507
|
max={max}
|
|
15508
|
+
disabled={disabled}
|
|
15328
15509
|
onChange={(e) => onChange(Number(e.target.value))}
|
|
15329
|
-
className="flex-1 min-w-0 text-base text-semantic-text-primary bg-transparent outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
|
|
15510
|
+
className="flex-1 min-w-0 text-base text-semantic-text-primary bg-transparent outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none disabled:cursor-not-allowed"
|
|
15330
15511
|
/>
|
|
15331
15512
|
<div className="flex flex-col items-center shrink-0 gap-0.5">
|
|
15332
15513
|
<button
|
|
15333
15514
|
type="button"
|
|
15334
15515
|
onClick={() => onChange(Math.min(max, value + 1))}
|
|
15335
|
-
|
|
15516
|
+
disabled={disabled}
|
|
15517
|
+
className="flex items-center justify-center text-semantic-text-muted hover:text-semantic-text-primary transition-colors disabled:cursor-not-allowed"
|
|
15336
15518
|
aria-label="Increase"
|
|
15337
15519
|
>
|
|
15338
15520
|
<ChevronUp className="size-3" />
|
|
@@ -15340,7 +15522,8 @@ function NumberSpinner({
|
|
|
15340
15522
|
<button
|
|
15341
15523
|
type="button"
|
|
15342
15524
|
onClick={() => onChange(Math.max(min, value - 1))}
|
|
15343
|
-
|
|
15525
|
+
disabled={disabled}
|
|
15526
|
+
className="flex items-center justify-center text-semantic-text-muted hover:text-semantic-text-primary transition-colors disabled:cursor-not-allowed"
|
|
15344
15527
|
aria-label="Decrease"
|
|
15345
15528
|
>
|
|
15346
15529
|
<ChevronDown className="size-3" />
|
|
@@ -15361,6 +15544,7 @@ const AdvancedSettingsCard = React.forwardRef<HTMLDivElement, AdvancedSettingsCa
|
|
|
15361
15544
|
silenceTimeoutMax = 60,
|
|
15362
15545
|
callEndThresholdMin = 1,
|
|
15363
15546
|
callEndThresholdMax = 10,
|
|
15547
|
+
disabled,
|
|
15364
15548
|
className,
|
|
15365
15549
|
},
|
|
15366
15550
|
ref
|
|
@@ -15390,6 +15574,7 @@ const AdvancedSettingsCard = React.forwardRef<HTMLDivElement, AdvancedSettingsCa
|
|
|
15390
15574
|
onChange={(v) => onChange({ silenceTimeout: v })}
|
|
15391
15575
|
min={silenceTimeoutMin}
|
|
15392
15576
|
max={silenceTimeoutMax}
|
|
15577
|
+
disabled={disabled}
|
|
15393
15578
|
/>
|
|
15394
15579
|
<p className="m-0 text-xs text-semantic-text-muted">
|
|
15395
15580
|
Default: 15 seconds
|
|
@@ -15402,6 +15587,7 @@ const AdvancedSettingsCard = React.forwardRef<HTMLDivElement, AdvancedSettingsCa
|
|
|
15402
15587
|
onChange={(v) => onChange({ callEndThreshold: v })}
|
|
15403
15588
|
min={callEndThresholdMin}
|
|
15404
15589
|
max={callEndThresholdMax}
|
|
15590
|
+
disabled={disabled}
|
|
15405
15591
|
/>
|
|
15406
15592
|
<p className="m-0 text-xs text-semantic-text-muted">
|
|
15407
15593
|
Drop call after n consecutive silences. Default: 3
|
|
@@ -15424,6 +15610,7 @@ const AdvancedSettingsCard = React.forwardRef<HTMLDivElement, AdvancedSettingsCa
|
|
|
15424
15610
|
onCheckedChange={(v) =>
|
|
15425
15611
|
onChange({ interruptionHandling: v })
|
|
15426
15612
|
}
|
|
15613
|
+
disabled={disabled}
|
|
15427
15614
|
/>
|
|
15428
15615
|
</div>
|
|
15429
15616
|
</div>
|
|
@@ -15459,6 +15646,8 @@ export interface FunctionItem {
|
|
|
15459
15646
|
id: string;
|
|
15460
15647
|
name: string;
|
|
15461
15648
|
isBuiltIn?: boolean;
|
|
15649
|
+
/** Hover text shown on the info icon for this function */
|
|
15650
|
+
tooltip?: string;
|
|
15462
15651
|
}
|
|
15463
15652
|
|
|
15464
15653
|
export interface KnowledgeBaseFile {
|
|
@@ -15489,6 +15678,10 @@ export interface CreateFunctionModalProps {
|
|
|
15489
15678
|
onOpenChange: (open: boolean) => void;
|
|
15490
15679
|
onSubmit?: (data: CreateFunctionData) => void;
|
|
15491
15680
|
onTestApi?: (step2: CreateFunctionStep2Data) => Promise<string>;
|
|
15681
|
+
/** Minimum character length for the prompt field (default: 100) */
|
|
15682
|
+
promptMinLength?: number;
|
|
15683
|
+
/** Maximum character length for the prompt field (default: 5000) */
|
|
15684
|
+
promptMaxLength?: number;
|
|
15492
15685
|
/** Storybook/testing: start at a specific step (1 or 2) */
|
|
15493
15686
|
initialStep?: 1 | 2;
|
|
15494
15687
|
/** Storybook/testing: start on a specific tab when initialStep=2 */
|
|
@@ -15522,6 +15715,8 @@ export interface SelectOption {
|
|
|
15522
15715
|
export interface IvrBotConfigProps {
|
|
15523
15716
|
botTitle?: string;
|
|
15524
15717
|
botType?: string;
|
|
15718
|
+
/** When true, disables all fields in all card components (view mode) */
|
|
15719
|
+
disabled?: boolean;
|
|
15525
15720
|
/** Optional "Last updated at HH:MM AM/PM" text shown in the page header */
|
|
15526
15721
|
lastUpdatedAt?: string;
|
|
15527
15722
|
initialData?: Partial<IvrBotConfigData>;
|
|
@@ -15539,6 +15734,12 @@ export interface IvrBotConfigProps {
|
|
|
15539
15734
|
/** Called when user deletes a custom function */
|
|
15540
15735
|
onDeleteFunction?: (id: string) => void;
|
|
15541
15736
|
onTestApi?: (step2: CreateFunctionStep2Data) => Promise<string>;
|
|
15737
|
+
/** Hover text for the info icon in the Functions card header */
|
|
15738
|
+
functionsInfoTooltip?: string;
|
|
15739
|
+
/** Minimum character length for the function prompt (default: 100) */
|
|
15740
|
+
functionPromptMinLength?: number;
|
|
15741
|
+
/** Maximum character length for the function prompt (default: 5000) */
|
|
15742
|
+
functionPromptMaxLength?: number;
|
|
15542
15743
|
onBack?: () => void;
|
|
15543
15744
|
/** Called when the play icon is clicked on a voice option */
|
|
15544
15745
|
onPlayVoice?: (voiceValue: string) => void;
|