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.
Files changed (2) hide show
  1. package/dist/index.js +264 -63
  2. 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
- <SelectPrimitive.Portal>
1135
- <SelectPrimitive.Content
1136
- ref={ref}
1137
- className={cn(
1138
- "relative z-[9999] max-h-96 min-w-[8rem] overflow-hidden rounded bg-semantic-bg-primary border border-semantic-border-layout shadow-md",
1139
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
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
- "p-1",
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
- "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
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
- {children}
1160
- </SelectPrimitive.Viewport>
1161
- <SelectScrollDownButton />
1162
- </SelectPrimitive.Content>
1163
- </SelectPrimitive.Portal>
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
- saving = false,
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={saving}
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
- saving?: boolean;
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 > 0;
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
- <textarea
14185
- id="fn-prompt"
14186
- value={prompt}
14187
- onChange={(e) => setPrompt(e.target.value)}
14188
- placeholder="Enter the description of the function"
14189
- rows={5}
14190
- className={textareaCls}
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
- className={cn(tagVariants(), "gap-1.5 cursor-pointer hover:opacity-80 transition-opacity")}
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
- className="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"
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
- className="p-2 rounded text-semantic-text-muted hover:text-semantic-text-primary hover:bg-semantic-bg-hover transition-colors"
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
- className="p-2 rounded text-semantic-text-muted hover:text-semantic-error-primary hover:bg-semantic-error-surface transition-colors"
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
- <Info className="size-3.5 text-semantic-text-muted shrink-0" />
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
- className="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"
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
- <Info className="size-4 text-semantic-text-muted shrink-0" />
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
- className="p-1.5 rounded text-semantic-text-muted hover:text-semantic-text-primary hover:bg-semantic-bg-hover transition-colors"
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
- className="p-1.5 rounded text-semantic-text-muted hover:text-semantic-error-primary hover:bg-semantic-error-surface transition-colors"
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
- className="flex items-center justify-center text-semantic-text-muted hover:text-semantic-text-primary transition-colors"
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
- className="flex items-center justify-center text-semantic-text-muted hover:text-semantic-text-primary transition-colors"
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myoperator-ui",
3
- "version": "0.0.208",
3
+ "version": "0.0.209",
4
4
  "description": "CLI for adding myOperator UI components to your project",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",