@cossistant/react 0.0.22 → 0.0.24

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/conversation.d.ts CHANGED
@@ -84,8 +84,8 @@ declare const createConversationResponseSchema: ZodObject<{
84
84
  visitorId: ZodString;
85
85
  websiteId: ZodString;
86
86
  status: ZodDefault<ZodEnum<{
87
- resolved: "resolved";
88
87
  open: "open";
88
+ resolved: "resolved";
89
89
  spam: "spam";
90
90
  }>>;
91
91
  deletedAt: ZodDefault<ZodNullable<ZodString>>;
@@ -188,8 +188,8 @@ declare const listConversationsResponseSchema: ZodObject<{
188
188
  visitorId: ZodString;
189
189
  websiteId: ZodString;
190
190
  status: ZodDefault<ZodEnum<{
191
- resolved: "resolved";
192
191
  open: "open";
192
+ resolved: "resolved";
193
193
  spam: "spam";
194
194
  }>>;
195
195
  deletedAt: ZodDefault<ZodNullable<ZodString>>;
@@ -285,8 +285,8 @@ declare const getConversationResponseSchema: ZodObject<{
285
285
  visitorId: ZodString;
286
286
  websiteId: ZodString;
287
287
  status: ZodDefault<ZodEnum<{
288
- resolved: "resolved";
289
288
  open: "open";
289
+ resolved: "resolved";
290
290
  spam: "spam";
291
291
  }>>;
292
292
  deletedAt: ZodDefault<ZodNullable<ZodString>>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-multimodal-input.d.ts","names":[],"sources":["../../../src/hooks/private/use-multimodal-input.ts"],"sourcesContent":[],"mappings":";KAEY,yBAAA;EAAA,QAAA,CAAA,EAAA,CAAA,IAAA,EAAA;IACiC,OAAA,EAAA,MAAA;IAAoB,KAAA,EAApB,IAAoB,EAAA;EAC9C,CAAA,EAAA,GAAA,IAAA,GAD8C,OAC9C,CAAA,IAAA,CAAA;EAAK,OAAA,CAAA,EAAA,CAAA,KAAA,EAAL,KAAK,EAAA,GAAA,IAAA;EAMZ,WAAA,CAAA,EAAA,MAAA;EAGJ,QAAA,CAAA,EAAA,MAAA;EAEA,gBAAA,CAAA,EAAA,MAAA,EAAA;CAIW;AAGJ,KAZH,wBAAA,GAYG;EAAO,OAAA,EAAA,MAAA;EAaT,KAAA,EAtBL,IAsBK,EAAA;EAAsB,YAAA,EAAA,OAAA;EAAA,KAAA,EApB3B,KAoB2B,GAAA,IAAA;EAAA,UAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,EAAA,CAAA,KAAA,EAhBhB,IAgBgB,EAAA,EAAA,GAAA,IAAA;EAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAMhC,UAAA,EAAA,GAAA,GAAA,IAAA;EAAiC,MAAA,EAAA,GAAA,GAnBrB,OAmBqB,CAAA,IAAA,CAAA;EAsJnC,KAAA,EAAA,GAAA,GAAA,IAAA;;;;;;;;;cA5JY;;;;;;IAMV,8BAAiC"}
1
+ {"version":3,"file":"use-multimodal-input.d.ts","names":[],"sources":["../../../src/hooks/private/use-multimodal-input.ts"],"sourcesContent":[],"mappings":";KAEY,yBAAA;EAAA,QAAA,CAAA,EAAA,CAAA,IAAA,EAAA;IACiC,OAAA,EAAA,MAAA;IAAoB,KAAA,EAApB,IAAoB,EAAA;EAC9C,CAAA,EAAA,GAAA,IAAA,GAD8C,OAC9C,CAAA,IAAA,CAAA;EAAK,OAAA,CAAA,EAAA,CAAA,KAAA,EAAL,KAAK,EAAA,GAAA,IAAA;EAMZ,WAAA,CAAA,EAAA,MAAA;EAGJ,QAAA,CAAA,EAAA,MAAA;EAEA,gBAAA,CAAA,EAAA,MAAA,EAAA;CAIW;AAGJ,KAZH,wBAAA,GAYG;EAAO,OAAA,EAAA,MAAA;EAaT,KAAA,EAtBL,IAsBK,EAAA;EAAsB,YAAA,EAAA,OAAA;EAAA,KAAA,EApB3B,KAoB2B,GAAA,IAAA;EAAA,UAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,EAAA,CAAA,KAAA,EAhBhB,IAgBgB,EAAA,EAAA,GAAA,IAAA;EAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAMhC,UAAA,EAAA,GAAA,GAAA,IAAA;EAAiC,MAAA,EAAA,GAAA,GAnBrB,OAmBqB,CAAA,IAAA,CAAA;EAwKnC,KAAA,EAAA,GAAA,GAAA,IAAA;;;;;;;;;cA9KY;;;;;;IAMV,8BAAiC"}
@@ -79,21 +79,34 @@ const useMultimodalInput = ({ onSubmit, onError, maxFileSize = 10 * 1024 * 1024,
79
79
  }, [clearFiles]);
80
80
  const submit = useCallback(async () => {
81
81
  if (!onSubmit) return;
82
- if (!message.trim() && files.length === 0) {
82
+ const trimmedMessage = message.trim();
83
+ if (!trimmedMessage && files.length === 0) {
83
84
  const err = /* @__PURE__ */ new Error("Please provide a message or attach files");
84
85
  setError(err);
85
86
  onError?.(err);
86
87
  return;
87
88
  }
89
+ const previousState = {
90
+ message,
91
+ files,
92
+ fileUrls: [...fileUrlsRef.current]
93
+ };
88
94
  setIsSubmitting(true);
89
95
  setError(null);
96
+ setMessage("");
97
+ setFiles([]);
98
+ fileUrlsRef.current = [];
90
99
  try {
91
100
  await onSubmit({
92
- message: message.trim(),
93
- files
101
+ message: trimmedMessage,
102
+ files: previousState.files
94
103
  });
104
+ for (const url of previousState.fileUrls) URL.revokeObjectURL(url);
95
105
  reset();
96
106
  } catch (err) {
107
+ setMessage(previousState.message);
108
+ setFiles(previousState.files);
109
+ fileUrlsRef.current = previousState.fileUrls;
97
110
  const _error = err instanceof Error ? err : /* @__PURE__ */ new Error("Failed to submit");
98
111
  setError(_error);
99
112
  onError?.(_error);
@@ -1 +1 @@
1
- {"version":3,"file":"use-multimodal-input.js","names":[],"sources":["../../../src/hooks/private/use-multimodal-input.ts"],"sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nexport type UseMultimodalInputOptions = {\n\tonSubmit?: (data: { message: string; files: File[] }) => void | Promise<void>;\n\tonError?: (error: Error) => void;\n\tmaxFileSize?: number; // in bytes\n\tmaxFiles?: number;\n\tallowedFileTypes?: string[]; // MIME types\n};\n\nexport type UseMultimodalInputReturn = {\n\t// State\n\tmessage: string;\n\tfiles: File[];\n\tisSubmitting: boolean;\n\terror: Error | null;\n\n\t// Actions\n\tsetMessage: (message: string) => void;\n\taddFiles: (files: File[]) => void;\n\tremoveFile: (index: number) => void;\n\tclearFiles: () => void;\n\tsubmit: () => Promise<void>;\n\treset: () => void;\n\n\t// Validation\n\tisValid: boolean;\n\tcanSubmit: boolean;\n};\n\n/**\n * Manages message text, file attachments and validation for the multimodal\n * composer component. Provides ergonomic helpers for submit flows and error\n * reporting.\n */\nexport const useMultimodalInput = ({\n\tonSubmit,\n\tonError,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB default\n\tmaxFiles = 5,\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}: UseMultimodalInputOptions = {}): UseMultimodalInputReturn => {\n\tconst [message, setMessage] = useState(\"\");\n\tconst [files, setFiles] = useState<File[]>([]);\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\t// Use ref to prevent re-renders when tracking file URLs\n\tconst fileUrlsRef = useRef<string[]>([]);\n\n\t// Validation helpers\n\tconst validateFile = useCallback(\n\t\t(file: File): string | null => {\n\t\t\tif (file.size > maxFileSize) {\n\t\t\t\treturn `File \"${file.name}\" exceeds maximum size of ${maxFileSize / 1024 / 1024}MB`;\n\t\t\t}\n\n\t\t\tif (allowedFileTypes.length > 0) {\n\t\t\t\tconst isAllowed = allowedFileTypes.some((type) => {\n\t\t\t\t\tif (type.endsWith(\"/*\")) {\n\t\t\t\t\t\tconst baseType = type.slice(0, -2);\n\t\t\t\t\t\treturn file.type.startsWith(baseType);\n\t\t\t\t\t}\n\t\t\t\t\treturn file.type === type;\n\t\t\t\t});\n\n\t\t\t\tif (!isAllowed) {\n\t\t\t\t\treturn `File type \"${file.type}\" is not allowed`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\t\t[maxFileSize, allowedFileTypes]\n\t);\n\n\t// Actions\n\tconst addFiles = useCallback(\n\t\t(newFiles: File[]) => {\n\t\t\tsetError(null);\n\n\t\t\t// Check max files limit\n\t\t\tif (files.length + newFiles.length > maxFiles) {\n\t\t\t\tconst err = new Error(\n\t\t\t\t\t`Cannot add files: maximum ${maxFiles} files allowed`\n\t\t\t\t);\n\t\t\t\tsetError(err);\n\t\t\t\tonError?.(err);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Validate each file\n\t\t\tfor (const file of newFiles) {\n\t\t\t\tconst validationError = validateFile(file);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tconst err = new Error(validationError);\n\t\t\t\t\tsetError(err);\n\t\t\t\t\tonError?.(err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetFiles((prev) => [...prev, ...newFiles]);\n\t\t},\n\t\t[files.length, maxFiles, validateFile, onError]\n\t);\n\n\tconst removeFile = useCallback((index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst newFiles = [...prev];\n\t\t\tnewFiles.splice(index, 1);\n\n\t\t\t// Clean up object URL if it exists\n\t\t\tif (fileUrlsRef.current[index]) {\n\t\t\t\tURL.revokeObjectURL(fileUrlsRef.current[index]);\n\t\t\t\tfileUrlsRef.current.splice(index, 1);\n\t\t\t}\n\n\t\t\treturn newFiles;\n\t\t});\n\t\tsetError(null);\n\t}, []);\n\n\tconst clearFiles = useCallback(() => {\n\t\t// Clean up all object URLs\n\t\tfor (const url of fileUrlsRef.current) {\n\t\t\tURL.revokeObjectURL(url);\n\t\t}\n\t\tfileUrlsRef.current = [];\n\n\t\tsetFiles([]);\n\t\tsetError(null);\n\t}, []);\n\n\tconst reset = useCallback(() => {\n\t\tsetMessage(\"\");\n\t\tclearFiles();\n\t\tsetError(null);\n\t\tsetIsSubmitting(false);\n\t}, [clearFiles]);\n\n\tconst submit = useCallback(async () => {\n\t\tif (!onSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!message.trim() && files.length === 0) {\n\t\t\tconst err = new Error(\"Please provide a message or attach files\");\n\t\t\tsetError(err);\n\t\t\tonError?.(err);\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsSubmitting(true);\n\t\tsetError(null);\n\n\t\ttry {\n\t\t\tawait onSubmit({ message: message.trim(), files });\n\t\t\treset();\n\t\t} catch (err) {\n\t\t\tconst _error = err instanceof Error ? err : new Error(\"Failed to submit\");\n\t\t\tsetError(_error);\n\t\t\tonError?.(_error);\n\t\t} finally {\n\t\t\tsetIsSubmitting(false);\n\t\t}\n\t}, [message, files, onSubmit, onError, reset]);\n\n\t// Computed values\n\tconst isValid = message.trim().length > 0 || files.length > 0;\n\tconst canSubmit = isValid && !isSubmitting && !error;\n\n\treturn {\n\t\t// State\n\t\tmessage,\n\t\tfiles,\n\t\tisSubmitting,\n\t\terror,\n\n\t\t// Actions\n\t\tsetMessage,\n\t\taddFiles,\n\t\tremoveFile,\n\t\tclearFiles,\n\t\tsubmit,\n\t\treset,\n\n\t\t// Validation\n\t\tisValid,\n\t\tcanSubmit,\n\t};\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-multimodal-input.js","names":[],"sources":["../../../src/hooks/private/use-multimodal-input.ts"],"sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nexport type UseMultimodalInputOptions = {\n\tonSubmit?: (data: { message: string; files: File[] }) => void | Promise<void>;\n\tonError?: (error: Error) => void;\n\tmaxFileSize?: number; // in bytes\n\tmaxFiles?: number;\n\tallowedFileTypes?: string[]; // MIME types\n};\n\nexport type UseMultimodalInputReturn = {\n\t// State\n\tmessage: string;\n\tfiles: File[];\n\tisSubmitting: boolean;\n\terror: Error | null;\n\n\t// Actions\n\tsetMessage: (message: string) => void;\n\taddFiles: (files: File[]) => void;\n\tremoveFile: (index: number) => void;\n\tclearFiles: () => void;\n\tsubmit: () => Promise<void>;\n\treset: () => void;\n\n\t// Validation\n\tisValid: boolean;\n\tcanSubmit: boolean;\n};\n\n/**\n * Manages message text, file attachments and validation for the multimodal\n * composer component. Provides ergonomic helpers for submit flows and error\n * reporting.\n */\nexport const useMultimodalInput = ({\n\tonSubmit,\n\tonError,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB default\n\tmaxFiles = 5,\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}: UseMultimodalInputOptions = {}): UseMultimodalInputReturn => {\n\tconst [message, setMessage] = useState(\"\");\n\tconst [files, setFiles] = useState<File[]>([]);\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\t// Use ref to prevent re-renders when tracking file URLs\n\tconst fileUrlsRef = useRef<string[]>([]);\n\n\t// Validation helpers\n\tconst validateFile = useCallback(\n\t\t(file: File): string | null => {\n\t\t\tif (file.size > maxFileSize) {\n\t\t\t\treturn `File \"${file.name}\" exceeds maximum size of ${maxFileSize / 1024 / 1024}MB`;\n\t\t\t}\n\n\t\t\tif (allowedFileTypes.length > 0) {\n\t\t\t\tconst isAllowed = allowedFileTypes.some((type) => {\n\t\t\t\t\tif (type.endsWith(\"/*\")) {\n\t\t\t\t\t\tconst baseType = type.slice(0, -2);\n\t\t\t\t\t\treturn file.type.startsWith(baseType);\n\t\t\t\t\t}\n\t\t\t\t\treturn file.type === type;\n\t\t\t\t});\n\n\t\t\t\tif (!isAllowed) {\n\t\t\t\t\treturn `File type \"${file.type}\" is not allowed`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\t\t[maxFileSize, allowedFileTypes]\n\t);\n\n\t// Actions\n\tconst addFiles = useCallback(\n\t\t(newFiles: File[]) => {\n\t\t\tsetError(null);\n\n\t\t\t// Check max files limit\n\t\t\tif (files.length + newFiles.length > maxFiles) {\n\t\t\t\tconst err = new Error(\n\t\t\t\t\t`Cannot add files: maximum ${maxFiles} files allowed`\n\t\t\t\t);\n\t\t\t\tsetError(err);\n\t\t\t\tonError?.(err);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Validate each file\n\t\t\tfor (const file of newFiles) {\n\t\t\t\tconst validationError = validateFile(file);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tconst err = new Error(validationError);\n\t\t\t\t\tsetError(err);\n\t\t\t\t\tonError?.(err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetFiles((prev) => [...prev, ...newFiles]);\n\t\t},\n\t\t[files.length, maxFiles, validateFile, onError]\n\t);\n\n\tconst removeFile = useCallback((index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst newFiles = [...prev];\n\t\t\tnewFiles.splice(index, 1);\n\n\t\t\t// Clean up object URL if it exists\n\t\t\tif (fileUrlsRef.current[index]) {\n\t\t\t\tURL.revokeObjectURL(fileUrlsRef.current[index]);\n\t\t\t\tfileUrlsRef.current.splice(index, 1);\n\t\t\t}\n\n\t\t\treturn newFiles;\n\t\t});\n\t\tsetError(null);\n\t}, []);\n\n\tconst clearFiles = useCallback(() => {\n\t\t// Clean up all object URLs\n\t\tfor (const url of fileUrlsRef.current) {\n\t\t\tURL.revokeObjectURL(url);\n\t\t}\n\t\tfileUrlsRef.current = [];\n\n\t\tsetFiles([]);\n\t\tsetError(null);\n\t}, []);\n\n\tconst reset = useCallback(() => {\n\t\tsetMessage(\"\");\n\t\tclearFiles();\n\t\tsetError(null);\n\t\tsetIsSubmitting(false);\n\t}, [clearFiles]);\n\n\tconst submit = useCallback(async () => {\n\t\tif (!onSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst trimmedMessage = message.trim();\n\t\tif (!trimmedMessage && files.length === 0) {\n\t\t\tconst err = new Error(\"Please provide a message or attach files\");\n\t\t\tsetError(err);\n\t\t\tonError?.(err);\n\t\t\treturn;\n\t\t}\n\n\t\tconst previousState = {\n\t\t\tmessage,\n\t\t\tfiles,\n\t\t\tfileUrls: [...fileUrlsRef.current],\n\t\t};\n\n\t\tsetIsSubmitting(true);\n\t\tsetError(null);\n\t\tsetMessage(\"\");\n\t\tsetFiles([]);\n\t\tfileUrlsRef.current = [];\n\n\t\ttry {\n\t\t\tawait onSubmit({ message: trimmedMessage, files: previousState.files });\n\n\t\t\tfor (const url of previousState.fileUrls) {\n\t\t\t\tURL.revokeObjectURL(url);\n\t\t\t}\n\t\t\treset();\n\t\t} catch (err) {\n\t\t\tsetMessage(previousState.message);\n\t\t\tsetFiles(previousState.files);\n\t\t\tfileUrlsRef.current = previousState.fileUrls;\n\n\t\t\tconst _error = err instanceof Error ? err : new Error(\"Failed to submit\");\n\t\t\tsetError(_error);\n\t\t\tonError?.(_error);\n\t\t} finally {\n\t\t\tsetIsSubmitting(false);\n\t\t}\n\t}, [message, files, onSubmit, onError, reset]);\n\n\t// Computed values\n\tconst isValid = message.trim().length > 0 || files.length > 0;\n\tconst canSubmit = isValid && !isSubmitting && !error;\n\n\treturn {\n\t\t// State\n\t\tmessage,\n\t\tfiles,\n\t\tisSubmitting,\n\t\terror,\n\n\t\t// Actions\n\t\tsetMessage,\n\t\taddFiles,\n\t\tremoveFile,\n\t\tclearFiles,\n\t\tsubmit,\n\t\treset,\n\n\t\t// Validation\n\t\tisValid,\n\t\tcanSubmit,\n\t};\n};\n"],"mappings":";;;;;;;;AAmCA,MAAa,sBAAsB,EAClC,UACA,SACA,cAAc,KAAK,OAAO,MAC1B,WAAW,GACX,mBAAmB;CAAC;CAAW;CAAmB;CAAS,KAC7B,EAAE,KAA+B;CAC/D,MAAM,CAAC,SAAS,cAAc,SAAS,GAAG;CAC1C,MAAM,CAAC,OAAO,YAAY,SAAiB,EAAE,CAAC;CAC9C,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CACvD,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAGtD,MAAM,cAAc,OAAiB,EAAE,CAAC;CAGxC,MAAM,eAAe,aACnB,SAA8B;AAC9B,MAAI,KAAK,OAAO,YACf,QAAO,SAAS,KAAK,KAAK,4BAA4B,cAAc,OAAO,KAAK;AAGjF,MAAI,iBAAiB,SAAS,GAS7B;OAAI,CARc,iBAAiB,MAAM,SAAS;AACjD,QAAI,KAAK,SAAS,KAAK,EAAE;KACxB,MAAM,WAAW,KAAK,MAAM,GAAG,GAAG;AAClC,YAAO,KAAK,KAAK,WAAW,SAAS;;AAEtC,WAAO,KAAK,SAAS;KACpB,CAGD,QAAO,cAAc,KAAK,KAAK;;AAIjC,SAAO;IAER,CAAC,aAAa,iBAAiB,CAC/B;CAGD,MAAM,WAAW,aACf,aAAqB;AACrB,WAAS,KAAK;AAGd,MAAI,MAAM,SAAS,SAAS,SAAS,UAAU;GAC9C,MAAM,sBAAM,IAAI,MACf,6BAA6B,SAAS,gBACtC;AACD,YAAS,IAAI;AACb,aAAU,IAAI;AACd;;AAID,OAAK,MAAM,QAAQ,UAAU;GAC5B,MAAM,kBAAkB,aAAa,KAAK;AAC1C,OAAI,iBAAiB;IACpB,MAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,aAAS,IAAI;AACb,cAAU,IAAI;AACd;;;AAIF,YAAU,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAE3C;EAAC,MAAM;EAAQ;EAAU;EAAc;EAAQ,CAC/C;CAED,MAAM,aAAa,aAAa,UAAkB;AACjD,YAAU,SAAS;GAClB,MAAM,WAAW,CAAC,GAAG,KAAK;AAC1B,YAAS,OAAO,OAAO,EAAE;AAGzB,OAAI,YAAY,QAAQ,QAAQ;AAC/B,QAAI,gBAAgB,YAAY,QAAQ,OAAO;AAC/C,gBAAY,QAAQ,OAAO,OAAO,EAAE;;AAGrC,UAAO;IACN;AACF,WAAS,KAAK;IACZ,EAAE,CAAC;CAEN,MAAM,aAAa,kBAAkB;AAEpC,OAAK,MAAM,OAAO,YAAY,QAC7B,KAAI,gBAAgB,IAAI;AAEzB,cAAY,UAAU,EAAE;AAExB,WAAS,EAAE,CAAC;AACZ,WAAS,KAAK;IACZ,EAAE,CAAC;CAEN,MAAM,QAAQ,kBAAkB;AAC/B,aAAW,GAAG;AACd,cAAY;AACZ,WAAS,KAAK;AACd,kBAAgB,MAAM;IACpB,CAAC,WAAW,CAAC;CAEhB,MAAM,SAAS,YAAY,YAAY;AACtC,MAAI,CAAC,SACJ;EAGD,MAAM,iBAAiB,QAAQ,MAAM;AACrC,MAAI,CAAC,kBAAkB,MAAM,WAAW,GAAG;GAC1C,MAAM,sBAAM,IAAI,MAAM,2CAA2C;AACjE,YAAS,IAAI;AACb,aAAU,IAAI;AACd;;EAGD,MAAM,gBAAgB;GACrB;GACA;GACA,UAAU,CAAC,GAAG,YAAY,QAAQ;GAClC;AAED,kBAAgB,KAAK;AACrB,WAAS,KAAK;AACd,aAAW,GAAG;AACd,WAAS,EAAE,CAAC;AACZ,cAAY,UAAU,EAAE;AAExB,MAAI;AACH,SAAM,SAAS;IAAE,SAAS;IAAgB,OAAO,cAAc;IAAO,CAAC;AAEvE,QAAK,MAAM,OAAO,cAAc,SAC/B,KAAI,gBAAgB,IAAI;AAEzB,UAAO;WACC,KAAK;AACb,cAAW,cAAc,QAAQ;AACjC,YAAS,cAAc,MAAM;AAC7B,eAAY,UAAU,cAAc;GAEpC,MAAM,SAAS,eAAe,QAAQ,sBAAM,IAAI,MAAM,mBAAmB;AACzE,YAAS,OAAO;AAChB,aAAU,OAAO;YACR;AACT,mBAAgB,MAAM;;IAErB;EAAC;EAAS;EAAO;EAAU;EAAS;EAAM,CAAC;CAG9C,MAAM,UAAU,QAAQ,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;AAG5D,QAAO;EAEN;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA,WAnBiB,WAAW,CAAC,gBAAgB,CAAC;EAoB9C"}
@@ -9,7 +9,7 @@ const useComposerRefocus = ({ disabled, hasContent, isSubmitting }) => {
9
9
  });
10
10
  useEffect(() => {
11
11
  const previous = previousStateRef.current;
12
- if (!(disabled || isSubmitting || hasContent) && (previous.isSubmitting || previous.hadContent)) inputRef.current?.focus();
12
+ if (!(disabled || hasContent) && (previous.isSubmitting || previous.hadContent)) inputRef.current?.focus();
13
13
  previousStateRef.current = {
14
14
  isSubmitting,
15
15
  hadContent: hasContent
@@ -1 +1 @@
1
- {"version":3,"file":"use-composer-refocus.js","names":[],"sources":["../../src/hooks/use-composer-refocus.ts"],"sourcesContent":["import type { MutableRefObject } from \"react\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport type UseComposerRefocusOptions = {\n\tdisabled: boolean;\n\thasContent: boolean;\n\tisSubmitting: boolean;\n};\n\nexport type UseComposerRefocusReturn = {\n\tfocusComposer: () => void;\n\tinputRef: MutableRefObject<HTMLTextAreaElement | null>;\n};\n\nexport const useComposerRefocus = ({\n\tdisabled,\n\thasContent,\n\tisSubmitting,\n}: UseComposerRefocusOptions): UseComposerRefocusReturn => {\n\tconst inputRef = useRef<HTMLTextAreaElement | null>(null);\n\tconst previousStateRef = useRef({\n\t\tisSubmitting,\n\t\thadContent: hasContent,\n\t});\n\n\tuseEffect(() => {\n\t\tconst previous = previousStateRef.current;\n\n\t\tif (\n\t\t\t!(disabled || isSubmitting || hasContent) &&\n\t\t\t(previous.isSubmitting || previous.hadContent)\n\t\t) {\n\t\t\tinputRef.current?.focus();\n\t\t}\n\n\t\tpreviousStateRef.current = {\n\t\t\tisSubmitting,\n\t\t\thadContent: hasContent,\n\t\t};\n\t}, [disabled, hasContent, isSubmitting]);\n\n\tconst focusComposer = useCallback(() => {\n\t\tinputRef.current?.focus();\n\t}, []);\n\n\treturn {\n\t\tfocusComposer,\n\t\tinputRef,\n\t};\n};\n"],"mappings":";;;AAcA,MAAa,sBAAsB,EAClC,UACA,YACA,mBAC0D;CAC1D,MAAM,WAAW,OAAmC,KAAK;CACzD,MAAM,mBAAmB,OAAO;EAC/B;EACA,YAAY;EACZ,CAAC;AAEF,iBAAgB;EACf,MAAM,WAAW,iBAAiB;AAElC,MACC,EAAE,YAAY,gBAAgB,gBAC7B,SAAS,gBAAgB,SAAS,YAEnC,UAAS,SAAS,OAAO;AAG1B,mBAAiB,UAAU;GAC1B;GACA,YAAY;GACZ;IACC;EAAC;EAAU;EAAY;EAAa,CAAC;AAMxC,QAAO;EACN,eALqB,kBAAkB;AACvC,YAAS,SAAS,OAAO;KACvB,EAAE,CAAC;EAIL;EACA"}
1
+ {"version":3,"file":"use-composer-refocus.js","names":[],"sources":["../../src/hooks/use-composer-refocus.ts"],"sourcesContent":["import type { MutableRefObject } from \"react\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport type UseComposerRefocusOptions = {\n\tdisabled: boolean;\n\thasContent: boolean;\n\tisSubmitting: boolean;\n};\n\nexport type UseComposerRefocusReturn = {\n\tfocusComposer: () => void;\n\tinputRef: MutableRefObject<HTMLTextAreaElement | null>;\n};\n\nexport const useComposerRefocus = ({\n\tdisabled,\n\thasContent,\n\tisSubmitting,\n}: UseComposerRefocusOptions): UseComposerRefocusReturn => {\n\tconst inputRef = useRef<HTMLTextAreaElement | null>(null);\n\tconst previousStateRef = useRef({\n\t\tisSubmitting,\n\t\thadContent: hasContent,\n\t});\n\n\tuseEffect(() => {\n\t\tconst previous = previousStateRef.current;\n\n\t\tif (\n\t\t\t!(disabled || hasContent) &&\n\t\t\t(previous.isSubmitting || previous.hadContent)\n\t\t) {\n\t\t\tinputRef.current?.focus();\n\t\t}\n\n\t\tpreviousStateRef.current = {\n\t\t\tisSubmitting,\n\t\t\thadContent: hasContent,\n\t\t};\n\t}, [disabled, hasContent, isSubmitting]);\n\n\tconst focusComposer = useCallback(() => {\n\t\tinputRef.current?.focus();\n\t}, []);\n\n\treturn {\n\t\tfocusComposer,\n\t\tinputRef,\n\t};\n};\n"],"mappings":";;;AAcA,MAAa,sBAAsB,EAClC,UACA,YACA,mBAC0D;CAC1D,MAAM,WAAW,OAAmC,KAAK;CACzD,MAAM,mBAAmB,OAAO;EAC/B;EACA,YAAY;EACZ,CAAC;AAEF,iBAAgB;EACf,MAAM,WAAW,iBAAiB;AAElC,MACC,EAAE,YAAY,gBACb,SAAS,gBAAgB,SAAS,YAEnC,UAAS,SAAS,OAAO;AAG1B,mBAAiB,UAAU;GAC1B;GACA,YAAY;GACZ;IACC;EAAC;EAAU;EAAY;EAAa,CAAC;AAMxC,QAAO;EACN,eALqB,kBAAkB;AACvC,YAAS,SAAS,OAAO;KACvB,EAAE,CAAC;EAIL;EACA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cossistant/react",
3
3
  "type": "module",
4
- "version": "0.0.22",
4
+ "version": "0.0.24",
5
5
  "private": false,
6
6
  "author": "Cossistant team",
7
7
  "description": "Headless React SDK for building AI-powered support/chat widgets. Hooks + primitives, WS-driven, TypeScript-first. Next.js-ready, Tailwind optional.",
@@ -88,8 +88,8 @@
88
88
  "*.css"
89
89
  ],
90
90
  "dependencies": {
91
- "@cossistant/core": "0.0.22",
92
- "@cossistant/types": "0.0.22",
91
+ "@cossistant/core": "0.0.24",
92
+ "@cossistant/types": "0.0.24",
93
93
  "class-variance-authority": "^0.7.1",
94
94
  "clsx": "^2.1.1",
95
95
  "nanoid": "^5.1.5",
@@ -15,7 +15,7 @@ type AvatarImageProps = Omit<React$1.ImgHTMLAttributes<HTMLImageElement>, "src"
15
15
  * Controlled `<img>` that syncs its loading status back to the avatar context
16
16
  * so fallbacks know when to display.
17
17
  */
18
- declare const AvatarImage: React$1.ForwardRefExoticComponent<Omit<React$1.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt"> & {
18
+ declare const AvatarImage: React$1.ForwardRefExoticComponent<Omit<React$1.ImgHTMLAttributes<HTMLImageElement>, "alt" | "src"> & {
19
19
  src: string;
20
20
  alt?: string;
21
21
  asChild?: boolean;
@@ -16,7 +16,7 @@ type MultimodalInputProps = Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElem
16
16
  * clipboard uploads and auto-resizing while remaining composable via
17
17
  * `asChild`.
18
18
  */
19
- declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
19
+ declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "onChange"> & {
20
20
  value: string;
21
21
  onChange: (value: string) => void;
22
22
  onSubmit?: () => void;
@@ -38,7 +38,7 @@ declare const FileInput: React$1.ForwardRefExoticComponent<React$1.InputHTMLAttr
38
38
  onFileSelect?: (files: File[]) => void;
39
39
  asChild?: boolean;
40
40
  } & React$1.RefAttributes<HTMLInputElement>>;
41
- declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
41
+ declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "onChange"> & {
42
42
  value: string;
43
43
  onChange: (value: string) => void;
44
44
  onSubmit?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,UAAA,GAAA,OAAA,CAAA,GAAA;;;EAmKgB,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EAtKD,IAsKC,EAAA,EAAA,GAAA,IAAA;;;UAnKhB"}
1
+ {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,OAAA,GAAA,UAAA,CAAA,GAAA;;;EAmKgB,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EAtKD,IAsKC,EAAA,EAAA,GAAA,IAAA;;;UAnKhB"}
@@ -111,8 +111,8 @@ declare const realtimeSchema: {
111
111
  visitorId: ZodString;
112
112
  websiteId: ZodString;
113
113
  status: ZodDefault<ZodEnum<{
114
- resolved: "resolved";
115
114
  open: "open";
115
+ resolved: "resolved";
116
116
  spam: "spam";
117
117
  }>>;
118
118
  deletedAt: ZodDefault<ZodNullable<ZodString>>;
@@ -189,8 +189,8 @@ declare const realtimeSchema: {
189
189
  header: ZodObject<{
190
190
  id: ZodString;
191
191
  status: ZodEnum<{
192
- resolved: "resolved";
193
192
  open: "open";
193
+ resolved: "resolved";
194
194
  spam: "spam";
195
195
  }>;
196
196
  priority: ZodEnum<{
@@ -229,6 +229,75 @@ declare const realtimeSchema: {
229
229
  deletedAt: ZodNullable<ZodString>;
230
230
  lastMessageAt: ZodNullable<ZodString>;
231
231
  lastSeenAt: ZodNullable<ZodString>;
232
+ lastMessageTimelineItem: ZodNullable<ZodObject<{
233
+ id: ZodOptional<ZodString>;
234
+ conversationId: ZodString;
235
+ organizationId: ZodString;
236
+ visibility: ZodEnum<{
237
+ public: "public";
238
+ private: "private";
239
+ }>;
240
+ type: ZodEnum<{
241
+ message: "message";
242
+ event: "event";
243
+ identification: "identification";
244
+ }>;
245
+ text: ZodNullable<ZodString>;
246
+ tool: ZodOptional<ZodNullable<ZodString>>;
247
+ parts: ZodArray<ZodUnion<readonly [ZodObject<{
248
+ type: ZodLiteral<"text">;
249
+ text: ZodString;
250
+ }, $strip>, ZodObject<{
251
+ type: ZodLiteral<"event">;
252
+ eventType: ZodEnum<{
253
+ assigned: "assigned";
254
+ unassigned: "unassigned";
255
+ participant_requested: "participant_requested";
256
+ participant_joined: "participant_joined";
257
+ participant_left: "participant_left";
258
+ status_changed: "status_changed";
259
+ priority_changed: "priority_changed";
260
+ tag_added: "tag_added";
261
+ tag_removed: "tag_removed";
262
+ resolved: "resolved";
263
+ reopened: "reopened";
264
+ visitor_blocked: "visitor_blocked";
265
+ visitor_unblocked: "visitor_unblocked";
266
+ visitor_identified: "visitor_identified";
267
+ }>;
268
+ actorUserId: ZodNullable<ZodString>;
269
+ actorAiAgentId: ZodNullable<ZodString>;
270
+ targetUserId: ZodNullable<ZodString>;
271
+ targetAiAgentId: ZodNullable<ZodString>;
272
+ message: ZodOptional<ZodNullable<ZodString>>;
273
+ }, $strip>, ZodObject<{
274
+ type: ZodLiteral<"image">;
275
+ url: ZodString;
276
+ mediaType: ZodString;
277
+ fileName: ZodOptional<ZodString>;
278
+ size: ZodOptional<ZodNumber>;
279
+ width: ZodOptional<ZodNumber>;
280
+ height: ZodOptional<ZodNumber>;
281
+ }, $strip>, ZodObject<{
282
+ type: ZodLiteral<"file">;
283
+ url: ZodString;
284
+ mediaType: ZodString;
285
+ fileName: ZodOptional<ZodString>;
286
+ size: ZodOptional<ZodNumber>;
287
+ }, $strip>, ZodObject<{
288
+ type: ZodLiteral<"metadata">;
289
+ source: ZodEnum<{
290
+ email: "email";
291
+ widget: "widget";
292
+ api: "api";
293
+ }>;
294
+ }, $strip>]>>;
295
+ userId: ZodNullable<ZodString>;
296
+ aiAgentId: ZodNullable<ZodString>;
297
+ visitorId: ZodNullable<ZodString>;
298
+ createdAt: ZodString;
299
+ deletedAt: ZodOptional<ZodNullable<ZodString>>;
300
+ }, $strip>>;
232
301
  lastTimelineItem: ZodNullable<ZodObject<{
233
302
  id: ZodOptional<ZodString>;
234
303
  conversationId: ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAiBa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmED,iBAAA,gBAAiC;KAEjC,+BAA+B,qBAAqB,eACvD,gBAAgB;KAGb,wBAAwB;QAC7B;WACG,qBAAqB;;KAGnB,gBAAA,WACL,oBAAoB,cAAc,KACvC;KAEU,4BAA4B,qBACvC,qBAAqB"}
1
+ {"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAiBa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmED,iBAAA,gBAAiC;KAEjC,+BAA+B,qBAAqB,eACvD,gBAAgB;KAGb,wBAAwB;QAC7B;WACG,qBAAqB;;KAGnB,gBAAA,WACL,oBAAoB,cAAc,KACvC;KAEU,4BAA4B,qBACvC,qBAAqB"}
package/schemas3.d.ts CHANGED
@@ -12,8 +12,8 @@ declare const conversationSchema: ZodObject<{
12
12
  visitorId: ZodString;
13
13
  websiteId: ZodString;
14
14
  status: ZodDefault<ZodEnum<{
15
- resolved: "resolved";
16
15
  open: "open";
16
+ resolved: "resolved";
17
17
  spam: "spam";
18
18
  }>>;
19
19
  deletedAt: ZodDefault<ZodNullable<ZodString>>;
@@ -54,7 +54,7 @@ const BubbleContent = ({ isOpen, unreadCount, isTyping }) => {
54
54
  opacity: 0
55
55
  },
56
56
  children: /* @__PURE__ */ jsx(icons_default, {
57
- className: "h-5 w-5",
57
+ className: "size-5",
58
58
  name: "chevron-down"
59
59
  })
60
60
  }, "chevron") : isTyping ? /* @__PURE__ */ jsx(motion.span, {
@@ -106,7 +106,7 @@ const BubbleContent = ({ isOpen, unreadCount, isTyping }) => {
106
106
  opacity: 0
107
107
  },
108
108
  children: /* @__PURE__ */ jsx(icons_default, {
109
- className: "h-6 w-6",
109
+ className: "size-6.5",
110
110
  name: "chat",
111
111
  variant: "filled"
112
112
  })
@@ -128,11 +128,22 @@ const BubbleContent = ({ isOpen, unreadCount, isTyping }) => {
128
128
  })] });
129
129
  };
130
130
  const Bubble = ({ className }) => /* @__PURE__ */ jsx(SupportBubble, {
131
- className: cn("relative flex size-12 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90", className),
132
- children: ({ isOpen, unreadCount, isTyping }) => /* @__PURE__ */ jsx(BubbleContent, {
133
- isOpen,
134
- isTyping,
135
- unreadCount
131
+ asChild: true,
132
+ children: ({ isOpen, unreadCount, isTyping }) => /* @__PURE__ */ jsx(motion.button, {
133
+ className: cn("relative flex size-14 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90", className),
134
+ "data-open": isOpen,
135
+ transition: {
136
+ type: "spring",
137
+ stiffness: 800,
138
+ damping: 17
139
+ },
140
+ type: "button",
141
+ whileTap: { scale: .95 },
142
+ children: /* @__PURE__ */ jsx(BubbleContent, {
143
+ isOpen,
144
+ isTyping,
145
+ unreadCount
146
+ })
136
147
  })
137
148
  });
138
149
 
@@ -1 +1 @@
1
- {"version":3,"file":"bubble.js","names":["BubbleContent: React.FC<BubbleContentProps>","Icon","Bubble: React.FC<BubbleProps>","Primitive.Bubble"],"sources":["../../../src/support/components/bubble.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useEffect, useRef } from \"react\";\nimport { useNewMessageSound } from \"../../hooks/use-new-message-sound\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport * as Primitive from \"../../primitives\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\ntype BubbleContentProps = {\n\tisOpen: boolean;\n\tunreadCount: number;\n\tisTyping: boolean;\n};\n\nconst BubbleContent: React.FC<BubbleContentProps> = ({\n\tisOpen,\n\tunreadCount,\n\tisTyping,\n}) => {\n\t// Customize playback settings here:\n\t// - volume: 0.0 to 1.0+ (default varies by sound)\n\t// - playbackRate: 0.5 to 2.0 (1.0 is normal speed, higher = faster)\n\tconst playNewMessageSound = useNewMessageSound({\n\t\tvolume: 0.7,\n\t\tplaybackRate: 1.0,\n\t});\n\tconst previousUnreadCountRef = useRef(0);\n\n\t// Play typing sound when widget is closed and someone is typing\n\tuseTypingSound(!isOpen && isTyping, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\t// Play new message sound when unread count increases\n\tuseEffect(() => {\n\t\tif (unreadCount > previousUnreadCountRef.current) {\n\t\t\tplayNewMessageSound();\n\t\t}\n\t\tpreviousUnreadCountRef.current = unreadCount;\n\t}, [unreadCount, playNewMessageSound]);\n\n\treturn (\n\t\t<>\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{isOpen ? (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: -45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: 45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chevron\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"h-5 w-5\" name=\"chevron-down\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t) : isTyping ? (\n\t\t\t\t\t<motion.span\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.2,\n\t\t\t\t\t\t\t\tease: \"easeOut\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"pointer-events-none flex items-center rounded-full text-co-primary\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.1,\n\t\t\t\t\t\t\t\tease: \"easeIn\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\tkey=\"typing-indicator\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<BouncingDots className=\"bg-co-primary-foreground\" />\n\t\t\t\t\t</motion.span>\n\t\t\t\t) : (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: 45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: -45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chat\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"h-6 w-6\" name=\"chat\" variant=\"filled\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{unreadCount > 0 && (\n\t\t\t\t<motion.div\n\t\t\t\t\tanimate={{ scale: 1, opacity: 1 }}\n\t\t\t\t\tclassName=\"absolute top-0.5 right-0.5 flex size-2 items-center justify-center rounded-full bg-co-destructive font-medium text-[10px] text-co-destructive-foreground text-white text-xs\"\n\t\t\t\t\texit={{ scale: 0, opacity: 0 }}\n\t\t\t\t\tinitial={{ scale: 0, opacity: 0 }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n\nexport type BubbleProps = {\n\tclassName?: string;\n};\n\nexport const Bubble: React.FC<BubbleProps> = ({ className }) => (\n\t<Primitive.Bubble\n\t\tclassName={cn(\n\t\t\t\"relative flex size-12 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90\",\n\t\t\tclassName\n\t\t)}\n\t>\n\t\t{({ isOpen, unreadCount, isTyping }) => (\n\t\t\t<BubbleContent\n\t\t\t\tisOpen={isOpen}\n\t\t\t\tisTyping={isTyping}\n\t\t\t\tunreadCount={unreadCount}\n\t\t\t/>\n\t\t)}\n\t</Primitive.Bubble>\n);\n"],"mappings":";;;;;;;;;;;;;;AAkBA,MAAMA,iBAA+C,EACpD,QACA,aACA,eACK;CAIL,MAAM,sBAAsB,mBAAmB;EAC9C,QAAQ;EACR,cAAc;EACd,CAAC;CACF,MAAM,yBAAyB,OAAO,EAAE;AAGxC,gBAAe,CAAC,UAAU,UAAU;EACnC,QAAQ;EACR,cAAc;EACd,CAAC;AAGF,iBAAgB;AACf,MAAI,cAAc,uBAAuB,QACxC,sBAAqB;AAEtB,yBAAuB,UAAU;IAC/B,CAAC,aAAa,oBAAoB,CAAC;AAEtC,QACC,4CACC,oBAAC;EAAgB,MAAK;YACpB,SACA,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAI,SAAS;IAAG;aAG/C,oBAACC;IAAK,WAAU;IAAU,MAAK;KAAiB;KAF5C,UAGQ,GACV,WACH,oBAAC,OAAO;GACP,SAAS;IACR,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,WAAU;GACV,MAAM;IACL,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,SAAS;IAAE,SAAS;IAAG,OAAO;IAAK;aAGnC,oBAAC,gBAAa,WAAU,6BAA6B;KAFjD,mBAGS,GAEd,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAK,SAAS;IAAG;aAGhD,oBAACA;IAAK,WAAU;IAAU,MAAK;IAAO,SAAQ;KAAW;KAFrD,OAGQ;GAEG,EAEjB,cAAc,KACd,oBAAC,OAAO;EACP,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;EACjC,WAAU;EACV,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC9B,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;GAChC,IAED;;AAQL,MAAaC,UAAiC,EAAE,gBAC/C,oBAACC;CACA,WAAW,GACV,qMACA,UACA;YAEC,EAAE,QAAQ,aAAa,eACxB,oBAAC;EACQ;EACE;EACG;GACZ;EAEe"}
1
+ {"version":3,"file":"bubble.js","names":["BubbleContent: React.FC<BubbleContentProps>","Icon","Bubble: React.FC<BubbleProps>","Primitive.Bubble"],"sources":["../../../src/support/components/bubble.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useEffect, useRef } from \"react\";\nimport { useNewMessageSound } from \"../../hooks/use-new-message-sound\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport * as Primitive from \"../../primitives\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\ntype BubbleContentProps = {\n\tisOpen: boolean;\n\tunreadCount: number;\n\tisTyping: boolean;\n};\n\nconst BubbleContent: React.FC<BubbleContentProps> = ({\n\tisOpen,\n\tunreadCount,\n\tisTyping,\n}) => {\n\t// Customize playback settings here:\n\t// - volume: 0.0 to 1.0+ (default varies by sound)\n\t// - playbackRate: 0.5 to 2.0 (1.0 is normal speed, higher = faster)\n\tconst playNewMessageSound = useNewMessageSound({\n\t\tvolume: 0.7,\n\t\tplaybackRate: 1.0,\n\t});\n\tconst previousUnreadCountRef = useRef(0);\n\n\t// Play typing sound when widget is closed and someone is typing\n\tuseTypingSound(!isOpen && isTyping, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\t// Play new message sound when unread count increases\n\tuseEffect(() => {\n\t\tif (unreadCount > previousUnreadCountRef.current) {\n\t\t\tplayNewMessageSound();\n\t\t}\n\t\tpreviousUnreadCountRef.current = unreadCount;\n\t}, [unreadCount, playNewMessageSound]);\n\n\treturn (\n\t\t<>\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{isOpen ? (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: -45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: 45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chevron\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-5\" name=\"chevron-down\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t) : isTyping ? (\n\t\t\t\t\t<motion.span\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.2,\n\t\t\t\t\t\t\t\tease: \"easeOut\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"pointer-events-none flex items-center rounded-full text-co-primary\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.1,\n\t\t\t\t\t\t\t\tease: \"easeIn\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\tkey=\"typing-indicator\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<BouncingDots className=\"bg-co-primary-foreground\" />\n\t\t\t\t\t</motion.span>\n\t\t\t\t) : (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: 45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: -45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chat\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-6.5\" name=\"chat\" variant=\"filled\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{unreadCount > 0 && (\n\t\t\t\t<motion.div\n\t\t\t\t\tanimate={{ scale: 1, opacity: 1 }}\n\t\t\t\t\tclassName=\"absolute top-0.5 right-0.5 flex size-2 items-center justify-center rounded-full bg-co-destructive font-medium text-[10px] text-co-destructive-foreground text-white text-xs\"\n\t\t\t\t\texit={{ scale: 0, opacity: 0 }}\n\t\t\t\t\tinitial={{ scale: 0, opacity: 0 }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n\nexport type BubbleProps = {\n\tclassName?: string;\n};\n\nexport const Bubble: React.FC<BubbleProps> = ({ className }) => (\n\t<Primitive.Bubble asChild>\n\t\t{({ isOpen, unreadCount, isTyping }) => (\n\t\t\t<motion.button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"relative flex size-14 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tdata-open={isOpen}\n\t\t\t\ttransition={{\n\t\t\t\t\ttype: \"spring\",\n\t\t\t\t\tstiffness: 800,\n\t\t\t\t\tdamping: 17,\n\t\t\t\t}}\n\t\t\t\ttype=\"button\"\n\t\t\t\twhileTap={{ scale: 0.95 }}\n\t\t\t>\n\t\t\t\t<BubbleContent\n\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\tisTyping={isTyping}\n\t\t\t\t\tunreadCount={unreadCount}\n\t\t\t\t/>\n\t\t\t</motion.button>\n\t\t)}\n\t</Primitive.Bubble>\n);\n"],"mappings":";;;;;;;;;;;;;;AAkBA,MAAMA,iBAA+C,EACpD,QACA,aACA,eACK;CAIL,MAAM,sBAAsB,mBAAmB;EAC9C,QAAQ;EACR,cAAc;EACd,CAAC;CACF,MAAM,yBAAyB,OAAO,EAAE;AAGxC,gBAAe,CAAC,UAAU,UAAU;EACnC,QAAQ;EACR,cAAc;EACd,CAAC;AAGF,iBAAgB;AACf,MAAI,cAAc,uBAAuB,QACxC,sBAAqB;AAEtB,yBAAuB,UAAU;IAC/B,CAAC,aAAa,oBAAoB,CAAC;AAEtC,QACC,4CACC,oBAAC;EAAgB,MAAK;YACpB,SACA,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAI,SAAS;IAAG;aAG/C,oBAACC;IAAK,WAAU;IAAS,MAAK;KAAiB;KAF3C,UAGQ,GACV,WACH,oBAAC,OAAO;GACP,SAAS;IACR,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,WAAU;GACV,MAAM;IACL,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,SAAS;IAAE,SAAS;IAAG,OAAO;IAAK;aAGnC,oBAAC,gBAAa,WAAU,6BAA6B;KAFjD,mBAGS,GAEd,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAK,SAAS;IAAG;aAGhD,oBAACA;IAAK,WAAU;IAAW,MAAK;IAAO,SAAQ;KAAW;KAFtD,OAGQ;GAEG,EAEjB,cAAc,KACd,oBAAC,OAAO;EACP,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;EACjC,WAAU;EACV,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC9B,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;GAChC,IAED;;AAQL,MAAaC,UAAiC,EAAE,gBAC/C,oBAACC;CAAiB;YACf,EAAE,QAAQ,aAAa,eACxB,oBAAC,OAAO;EACP,WAAW,GACV,qMACA,UACA;EACD,aAAW;EACX,YAAY;GACX,MAAM;GACN,WAAW;GACX,SAAS;GACT;EACD,MAAK;EACL,UAAU,EAAE,OAAO,KAAM;YAEzB,oBAAC;GACQ;GACE;GACG;IACZ;GACa;EAEC"}
@@ -4,7 +4,7 @@ import * as class_variance_authority_dist_types0 from "class-variance-authority/
4
4
 
5
5
  //#region src/support/components/button.d.ts
6
6
  declare const coButtonVariants: (props?: ({
7
- variant?: "default" | "tab" | "secondary" | "ghost" | "outline" | "tab-selected" | null | undefined;
7
+ variant?: "tab" | "default" | "secondary" | "ghost" | "outline" | "tab-selected" | null | undefined;
8
8
  size?: "default" | "large" | "icon" | null | undefined;
9
9
  } & class_variance_authority_dist_types0.ClassProp) | undefined) => string;
10
10
  type CossistantButtonProps = React$1.ComponentProps<"button"> & VariantProps<typeof coButtonVariants>;
@@ -49,7 +49,7 @@ const Container = ({ className, children, position = "bottom", align = "right" }
49
49
  asChild: true,
50
50
  children: /* @__PURE__ */ jsx(motion.div, {
51
51
  animate: "visible",
52
- className: cn("flex flex-col overflow-hidden overscroll-none bg-co-background max-md:fixed max-md:inset-0", "z-[9999] md:absolute md:z-[9900] md:aspect-[9/18] md:max-h-[calc(100vh-6rem)] md:w-[400px] md:rounded-lg md:border md:border-co-border md:shadow md:dark:shadow-co-background-600/50", position === "bottom" && "md:bottom-16", position === "top" && "md:top-16", align === "right" && "md:right-0", align === "left" && "md:left-0", className),
52
+ className: cn("flex flex-col overflow-hidden overscroll-none bg-co-background max-md:fixed max-md:inset-0", "z-[9999] md:absolute md:z-[9900] md:aspect-[9/17] md:max-h-[calc(100vh-6rem)] md:w-[400px] md:rounded-md md:border md:border-co-border md:shadow md:dark:shadow-co-background-600/50", position === "bottom" && "md:bottom-16", position === "top" && "md:top-16", align === "right" && "md:right-0", align === "left" && "md:left-0", className),
53
53
  exit: "exit",
54
54
  initial: "hidden",
55
55
  transition: {
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","names":["Container: React.FC<ContainerProps>","Primitive.Window"],"sources":["../../../src/support/components/container.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport * as Primitive from \"../../primitives\";\nimport { cn } from \"../utils\";\n\nexport type ContainerProps = {\n\tclassName?: string;\n\tchildren: React.ReactNode;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n};\n\nexport const Container: React.FC<ContainerProps> = ({\n\tclassName,\n\tchildren,\n\tposition = \"bottom\",\n\talign = \"right\",\n}) => {\n\tconst [showScrollIndicator, setShowScrollIndicator] = useState(false);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\n\tconst checkScroll = useCallback(() => {\n\t\tconst container = containerRef.current;\n\t\tif (!container) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { scrollTop, scrollHeight, clientHeight } = container;\n\t\tconst isScrollable = scrollHeight > clientHeight;\n\t\tconst isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 5; // 5px threshold\n\n\t\tsetShowScrollIndicator(isScrollable && !isAtBottom);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst container = containerRef.current;\n\t\tif (!container) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Instant initial check\n\t\tcheckScroll();\n\n\t\t// Direct scroll listener on the container\n\t\tconst handleScroll = () => {\n\t\t\tcheckScroll();\n\t\t};\n\n\t\tcontainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n\t\t// Use ResizeObserver to detect content changes instantly\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tcheckScroll();\n\t\t});\n\n\t\tresizeObserver.observe(container);\n\n\t\t// Also observe all child elements for dynamic content\n\t\tconst mutationObserver = new MutationObserver(() => {\n\t\t\tcheckScroll();\n\t\t});\n\n\t\tmutationObserver.observe(container, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tcharacterData: true,\n\t\t});\n\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener(\"scroll\", handleScroll);\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [checkScroll]);\n\n\treturn (\n\t\t<Primitive.Window asChild>\n\t\t\t<motion.div\n\t\t\t\tanimate=\"visible\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t// Common base styles\n\t\t\t\t\t\"flex flex-col overflow-hidden overscroll-none bg-co-background max-md:fixed max-md:inset-0\",\n\n\t\t\t\t\t// Desktop floating mode\n\t\t\t\t\t\"z-[9999] md:absolute md:z-[9900] md:aspect-[9/18] md:max-h-[calc(100vh-6rem)] md:w-[400px] md:rounded-lg md:border md:border-co-border md:shadow md:dark:shadow-co-background-600/50\",\n\t\t\t\t\tposition === \"bottom\" && \"md:bottom-16\",\n\t\t\t\t\tposition === \"top\" && \"md:top-16\",\n\t\t\t\t\talign === \"right\" && \"md:right-0\",\n\t\t\t\t\talign === \"left\" && \"md:left-0\",\n\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\texit=\"exit\"\n\t\t\t\tinitial=\"hidden\"\n\t\t\t\ttransition={{\n\t\t\t\t\tdefault: { ease: \"anticipate\" },\n\t\t\t\t\tlayout: { duration: 0.3 },\n\t\t\t\t}}\n\t\t\t\tvariants={{\n\t\t\t\t\thidden: { opacity: 0, y: 10, filter: \"blur(6px)\" },\n\t\t\t\t\tvisible: { opacity: 1, y: 0, filter: \"blur(0px)\" },\n\t\t\t\t\texit: { opacity: 0, y: 10, filter: \"blur(6px)\" },\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"relative flex h-full w-full flex-col\">\n\t\t\t\t\t{/* Scrollable content area */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"flex flex-1 flex-col overflow-y-auto pt-18\"\n\t\t\t\t\t\tref={containerRef}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<AnimatePresence>\n\t\t\t\t\t\t{showScrollIndicator && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 bottom-0 z-5 h-32 bg-gradient-to-t from-co-background via-co-background/70 to-transparent\"\n\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.3, ease: \"easeInOut\" }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\tanimate={{ opacity: 0.6 }}\n\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 bottom-0 z-5 h-48 bg-gradient-to-t from-co-background/80 via-co-background/30 to-transparent\"\n\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.4, ease: \"easeInOut\", delay: 0.05 }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</AnimatePresence>\n\t\t\t\t</div>\n\t\t\t</motion.div>\n\t\t</Primitive.Window>\n\t);\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAaA,aAAuC,EACnD,WACA,UACA,WAAW,UACX,QAAQ,cACH;CACL,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,MAAM;CACrE,MAAM,eAAe,OAAuB,KAAK;CAEjD,MAAM,cAAc,kBAAkB;EACrC,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UACJ;EAGD,MAAM,EAAE,WAAW,cAAc,iBAAiB;EAClD,MAAM,eAAe,eAAe;EACpC,MAAM,aAAa,KAAK,IAAI,eAAe,YAAY,aAAa,GAAG;AAEvE,yBAAuB,gBAAgB,CAAC,WAAW;IACjD,EAAE,CAAC;AAEN,iBAAgB;EACf,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UACJ;AAID,eAAa;EAGb,MAAM,qBAAqB;AAC1B,gBAAa;;AAGd,YAAU,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM,CAAC;EAGrE,MAAM,iBAAiB,IAAI,qBAAqB;AAC/C,gBAAa;IACZ;AAEF,iBAAe,QAAQ,UAAU;EAGjC,MAAM,mBAAmB,IAAI,uBAAuB;AACnD,gBAAa;IACZ;AAEF,mBAAiB,QAAQ,WAAW;GACnC,WAAW;GACX,SAAS;GACT,eAAe;GACf,CAAC;AAEF,eAAa;AACZ,aAAU,oBAAoB,UAAU,aAAa;AACrD,kBAAe,YAAY;AAC3B,oBAAiB,YAAY;;IAE5B,CAAC,YAAY,CAAC;AAEjB,QACC,oBAACC;EAAiB;YACjB,oBAAC,OAAO;GACP,SAAQ;GACR,WAAW,GAEV,8FAGA,wLACA,aAAa,YAAY,gBACzB,aAAa,SAAS,aACtB,UAAU,WAAW,cACrB,UAAU,UAAU,aAEpB,UACA;GACD,MAAK;GACL,SAAQ;GACR,YAAY;IACX,SAAS,EAAE,MAAM,cAAc;IAC/B,QAAQ,EAAE,UAAU,IAAK;IACzB;GACD,UAAU;IACT,QAAQ;KAAE,SAAS;KAAG,GAAG;KAAI,QAAQ;KAAa;IAClD,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG,QAAQ;KAAa;IAClD,MAAM;KAAE,SAAS;KAAG,GAAG;KAAI,QAAQ;KAAa;IAChD;aAED,qBAAC;IAAI,WAAU;eAEd,oBAAC;KACA,WAAU;KACV,KAAK;KAEJ;MACI,EAEN,oBAAC,6BACC,uBACA,4CACC,oBAAC,OAAO;KACP,SAAS,EAAE,SAAS,GAAG;KACvB,WAAU;KACV,MAAM,EAAE,SAAS,GAAG;KACpB,SAAS,EAAE,SAAS,GAAG;KACvB,YAAY;MAAE,UAAU;MAAK,MAAM;MAAa;MAC/C,EACF,oBAAC,OAAO;KACP,SAAS,EAAE,SAAS,IAAK;KACzB,WAAU;KACV,MAAM,EAAE,SAAS,GAAG;KACpB,SAAS,EAAE,SAAS,GAAG;KACvB,YAAY;MAAE,UAAU;MAAK,MAAM;MAAa,OAAO;MAAM;MAC5D,IACA,GAEa;KACb;IACM;GACK"}
1
+ {"version":3,"file":"container.js","names":["Container: React.FC<ContainerProps>","Primitive.Window"],"sources":["../../../src/support/components/container.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport * as Primitive from \"../../primitives\";\nimport { cn } from \"../utils\";\n\nexport type ContainerProps = {\n\tclassName?: string;\n\tchildren: React.ReactNode;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n};\n\nexport const Container: React.FC<ContainerProps> = ({\n\tclassName,\n\tchildren,\n\tposition = \"bottom\",\n\talign = \"right\",\n}) => {\n\tconst [showScrollIndicator, setShowScrollIndicator] = useState(false);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\n\tconst checkScroll = useCallback(() => {\n\t\tconst container = containerRef.current;\n\t\tif (!container) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { scrollTop, scrollHeight, clientHeight } = container;\n\t\tconst isScrollable = scrollHeight > clientHeight;\n\t\tconst isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 5; // 5px threshold\n\n\t\tsetShowScrollIndicator(isScrollable && !isAtBottom);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst container = containerRef.current;\n\t\tif (!container) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Instant initial check\n\t\tcheckScroll();\n\n\t\t// Direct scroll listener on the container\n\t\tconst handleScroll = () => {\n\t\t\tcheckScroll();\n\t\t};\n\n\t\tcontainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n\t\t// Use ResizeObserver to detect content changes instantly\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tcheckScroll();\n\t\t});\n\n\t\tresizeObserver.observe(container);\n\n\t\t// Also observe all child elements for dynamic content\n\t\tconst mutationObserver = new MutationObserver(() => {\n\t\t\tcheckScroll();\n\t\t});\n\n\t\tmutationObserver.observe(container, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tcharacterData: true,\n\t\t});\n\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener(\"scroll\", handleScroll);\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [checkScroll]);\n\n\treturn (\n\t\t<Primitive.Window asChild>\n\t\t\t<motion.div\n\t\t\t\tanimate=\"visible\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t// Common base styles\n\t\t\t\t\t\"flex flex-col overflow-hidden overscroll-none bg-co-background max-md:fixed max-md:inset-0\",\n\n\t\t\t\t\t// Desktop floating mode\n\t\t\t\t\t\"z-[9999] md:absolute md:z-[9900] md:aspect-[9/17] md:max-h-[calc(100vh-6rem)] md:w-[400px] md:rounded-md md:border md:border-co-border md:shadow md:dark:shadow-co-background-600/50\",\n\t\t\t\t\tposition === \"bottom\" && \"md:bottom-16\",\n\t\t\t\t\tposition === \"top\" && \"md:top-16\",\n\t\t\t\t\talign === \"right\" && \"md:right-0\",\n\t\t\t\t\talign === \"left\" && \"md:left-0\",\n\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\texit=\"exit\"\n\t\t\t\tinitial=\"hidden\"\n\t\t\t\ttransition={{\n\t\t\t\t\tdefault: { ease: \"anticipate\" },\n\t\t\t\t\tlayout: { duration: 0.3 },\n\t\t\t\t}}\n\t\t\t\tvariants={{\n\t\t\t\t\thidden: { opacity: 0, y: 10, filter: \"blur(6px)\" },\n\t\t\t\t\tvisible: { opacity: 1, y: 0, filter: \"blur(0px)\" },\n\t\t\t\t\texit: { opacity: 0, y: 10, filter: \"blur(6px)\" },\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"relative flex h-full w-full flex-col\">\n\t\t\t\t\t{/* Scrollable content area */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"flex flex-1 flex-col overflow-y-auto pt-18\"\n\t\t\t\t\t\tref={containerRef}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<AnimatePresence>\n\t\t\t\t\t\t{showScrollIndicator && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 bottom-0 z-5 h-32 bg-gradient-to-t from-co-background via-co-background/70 to-transparent\"\n\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.3, ease: \"easeInOut\" }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\tanimate={{ opacity: 0.6 }}\n\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 bottom-0 z-5 h-48 bg-gradient-to-t from-co-background/80 via-co-background/30 to-transparent\"\n\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.4, ease: \"easeInOut\", delay: 0.05 }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</AnimatePresence>\n\t\t\t\t</div>\n\t\t\t</motion.div>\n\t\t</Primitive.Window>\n\t);\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAaA,aAAuC,EACnD,WACA,UACA,WAAW,UACX,QAAQ,cACH;CACL,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,MAAM;CACrE,MAAM,eAAe,OAAuB,KAAK;CAEjD,MAAM,cAAc,kBAAkB;EACrC,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UACJ;EAGD,MAAM,EAAE,WAAW,cAAc,iBAAiB;EAClD,MAAM,eAAe,eAAe;EACpC,MAAM,aAAa,KAAK,IAAI,eAAe,YAAY,aAAa,GAAG;AAEvE,yBAAuB,gBAAgB,CAAC,WAAW;IACjD,EAAE,CAAC;AAEN,iBAAgB;EACf,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UACJ;AAID,eAAa;EAGb,MAAM,qBAAqB;AAC1B,gBAAa;;AAGd,YAAU,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM,CAAC;EAGrE,MAAM,iBAAiB,IAAI,qBAAqB;AAC/C,gBAAa;IACZ;AAEF,iBAAe,QAAQ,UAAU;EAGjC,MAAM,mBAAmB,IAAI,uBAAuB;AACnD,gBAAa;IACZ;AAEF,mBAAiB,QAAQ,WAAW;GACnC,WAAW;GACX,SAAS;GACT,eAAe;GACf,CAAC;AAEF,eAAa;AACZ,aAAU,oBAAoB,UAAU,aAAa;AACrD,kBAAe,YAAY;AAC3B,oBAAiB,YAAY;;IAE5B,CAAC,YAAY,CAAC;AAEjB,QACC,oBAACC;EAAiB;YACjB,oBAAC,OAAO;GACP,SAAQ;GACR,WAAW,GAEV,8FAGA,wLACA,aAAa,YAAY,gBACzB,aAAa,SAAS,aACtB,UAAU,WAAW,cACrB,UAAU,UAAU,aAEpB,UACA;GACD,MAAK;GACL,SAAQ;GACR,YAAY;IACX,SAAS,EAAE,MAAM,cAAc;IAC/B,QAAQ,EAAE,UAAU,IAAK;IACzB;GACD,UAAU;IACT,QAAQ;KAAE,SAAS;KAAG,GAAG;KAAI,QAAQ;KAAa;IAClD,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG,QAAQ;KAAa;IAClD,MAAM;KAAE,SAAS;KAAG,GAAG;KAAI,QAAQ;KAAa;IAChD;aAED,qBAAC;IAAI,WAAU;eAEd,oBAAC;KACA,WAAU;KACV,KAAK;KAEJ;MACI,EAEN,oBAAC,6BACC,uBACA,4CACC,oBAAC,OAAO;KACP,SAAS,EAAE,SAAS,GAAG;KACvB,WAAU;KACV,MAAM,EAAE,SAAS,GAAG;KACpB,SAAS,EAAE,SAAS,GAAG;KACvB,YAAY;MAAE,UAAU;MAAK,MAAM;MAAa;MAC/C,EACF,oBAAC,OAAO;KACP,SAAS,EAAE,SAAS,IAAK;KACzB,WAAU;KACV,MAAM,EAAE,SAAS,GAAG;KACpB,SAAS,EAAE,SAAS,GAAG;KACvB,YAAY;MAAE,UAAU;MAAK,MAAM;MAAa,OAAO;MAAM;MAC5D,IACA,GAEa;KACb;IACM;GACK"}
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAWY,oBAAA;;EAAA,KAAA,EAAA,MAAA;EAKY,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAIf,QAAA,EAAA,GAAA,GAAA,IAAA;EACA,YAAA,CAAA,EAAA,CAAA,KAAA,EALe,IAKf,EAAA,EAAA,GAAA,IAAA;EAAI,WAAA,CAAA,EAAA,MAAA;EAOA,QAAA,CAAA,EAAA,OA8JZ;EAEW,YAAA,CAAA,EAAA,OAAe;EAKd,KAAA,CAAA,EA7KJ,KA2LR,GAAA,IAAA;UA1LQ;;;;;;cAOI,iBAAiB,KAAA,CAAM,GAAG;KAgK3B,eAAA;;;;cAKC,YAAY,KAAA,CAAM,GAAG"}
1
+ {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAWY,oBAAA;;EAAA,KAAA,EAAA,MAAA;EAKY,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAIf,QAAA,EAAA,GAAA,GAAA,IAAA;EACA,YAAA,CAAA,EAAA,CAAA,KAAA,EALe,IAKf,EAAA,EAAA,GAAA,IAAA;EAAI,WAAA,CAAA,EAAA,MAAA;EAOA,QAAA,CAAA,EAAA,OAoKZ;EAEW,YAAA,CAAA,EAAA,OAAe;EAKd,KAAA,CAAA,EAnLJ,KAiMR,GAAA,IAAA;UAhMQ;;;;;;cAOI,iBAAiB,KAAA,CAAM,GAAG;KAsK3B,eAAA;;;;cAKC,YAAY,KAAA,CAAM,GAAG"}
@@ -24,13 +24,16 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
24
24
  hasContent,
25
25
  isSubmitting
26
26
  });
27
- const canSubmit = !(disabled || isSubmitting) && hasContent;
27
+ const canSubmit = !disabled && hasContent;
28
28
  const text = useSupportText();
29
29
  const resolvedPlaceholder = placeholder ?? text("component.multimodalInput.placeholder");
30
30
  const handleSubmit = () => {
31
31
  if (!canSubmit) return;
32
32
  onSubmit();
33
33
  focusComposer();
34
+ requestAnimationFrame(() => {
35
+ focusComposer();
36
+ });
34
37
  };
35
38
  const handleFormSubmit = (e) => {
36
39
  e.preventDefault();
@@ -83,8 +86,9 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
83
86
  /* @__PURE__ */ jsxs("div", {
84
87
  className: "group/multimodal-input flex flex-col rounded border border-co-border bg-co-background ring-offset-2 focus-within:ring-1 focus-within:ring-co-primary/10 dark:bg-co-background-200",
85
88
  children: [/* @__PURE__ */ jsx(MultimodalInput$1, {
89
+ autoFocus: true,
86
90
  className: cn("flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/50 focus-visible:outline-none", className),
87
- disabled: disabled || isSubmitting,
91
+ disabled,
88
92
  error,
89
93
  onChange,
90
94
  onFileSelect,
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !(disabled || isSubmitting) && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\tfocusComposer();\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"group/multimodal-input flex flex-col rounded border border-co-border bg-co-background ring-offset-2 focus-within:ring-1 focus-within:ring-co-primary/10 dark:bg-co-background-200\">\n\t\t\t\t<Primitive.MultimodalInput\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/50 focus-visible:outline-none\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\terror={error}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tplaceholder={resolvedPlaceholder}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tvalue={value}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex items-center justify-between py-1 pr-1 pl-3\">\n\t\t\t\t\t<Watermark />\n\n\t\t\t\t\t<div className=\"flex items-center gap-0.5\">\n\t\t\t\t\t\t{/* File attachment button */}\n\t\t\t\t\t\t{/* {onFileSelect && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.attachFiles\")}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t\t\t\tfiles.length >= maxFiles && \"opacity-50\"\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonClick={handleAttachClick}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" name=\"attachment\" />\n\t\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t\t<Primitive.FileInput\n\t\t\t\t\t\t\t\t\taccept={allowedFileTypes.join(\",\")}\n\t\t\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)} */}\n\n\t\t\t\t\t\t{/* Send button */}\n\t\t\t\t\t\t<SendButton disabled={!canSubmit} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t);\n};\n\nexport type SendButtonProps = {\n\tclassName?: string;\n\tdisabled?: boolean;\n};\n\nexport const SendButton: React.FC<SendButtonProps> = ({\n\tclassName,\n\tdisabled = false,\n}) => (\n\t<Primitive.Button\n\t\tclassName={cn(\n\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-primary hover:bg-co-muted disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tclassName\n\t\t)}\n\t\tdisabled={disabled}\n\t\ttype=\"submit\"\n\t>\n\t\t<Icon className=\"h-4 w-4\" filledOnHover name=\"send\" />\n\t</Primitive.Button>\n);\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAaA,mBAAmD,EAC/D,WACA,OACA,UACA,UACA,cACA,aACA,WAAW,OACX,eAAe,OACf,OACA,QAAQ,EAAE,EACV,cACA,WAAW,GACX,cAAc,KAAK,OAAO,MAC1B,mBAAmB;CAAC;CAAW;CAAmB;CAAS,OACtD;AACgB,QAAyB,KAAK;CACnD,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;CAC7D,MAAM,EAAE,eAAe,aAAa,mBAAmB;EACtD;EACA;EACA;EACA,CAAC;CACF,MAAM,YAAY,EAAE,YAAY,iBAAiB;CACjD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBACL,eAAe,KAAK,wCAAwC;CAE7D,MAAM,qBAAqB;AAC1B,MAAI,CAAC,UACJ;AAGD,YAAU;AACV,iBAAe;;CAGhB,MAAM,oBAAoB,MAAuB;AAChD,IAAE,gBAAgB;AAClB,gBAAc;;CASf,MAAM,kBAAkB,UAAkB;AACzC,MAAI,QAAQ,KACX,QAAO,GAAG,MAAM;AAEjB,MAAI,QAAQ,OAAO,KAClB,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAErC,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,QACC,qBAAC;EAAK,WAAU;EAAsB,UAAU;;GAE9C,SACA,oBAAC;IACA,WAAU;IACV,IAAG;cAEF,MAAM;KACF;GAIN,MAAM,SAAS,KACf,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,MAAM,UACjB,qBAAC;KACA,WAAU;;MAGV,oBAACC;OAAK,WAAU;OAAU,MAAK;QAAe;MAC9C,oBAAC;OAAK,WAAU;iBAA0B,KAAK;QAAY;MAC3D,oBAAC;OAAK,WAAU;iBACd,eAAe,KAAK,KAAK;QACpB;MACN,gBACA,oBAAC;OACA,cAAY,KAAK,6BAA6B,EAC7C,UAAU,KAAK,MACf,CAAC;OACF,WAAU;OACV,eAAe,aAAa,MAAM;OAClC,MAAK;iBAEL,oBAACA;QAAK,WAAU;QAAU,MAAK;SAAU;QACjC;;OAjBL,GAAG,KAAK,KAAK,GAAG,QAmBhB,CACL;KACG;GAIP,qBAAC;IAAI,WAAU;eACd,oBAACC;KACA,WAAW,GACV,+HACA,UACA;KACD,UAAU,YAAY;KACf;KACG;KACI;KACd,UAAU;KACV,aAAa;KACb,KAAK;KACE;MACN,EAEF,qBAAC;KAAI,WAAU;gBACd,oBAAC,cAAY,EAEb,oBAAC;MAAI,WAAU;gBAgCd,oBAAC,cAAW,UAAU,CAAC,YAAa;OAC/B;MACD;KACD;;GACA;;AAST,MAAaC,cAAyC,EACrD,WACA,WAAW,YAEX,oBAACC;CACA,WAAW,GACV,+IACA,UACA;CACS;CACV,MAAK;WAEL,oBAACH;EAAK,WAAU;EAAU;EAAc,MAAK;GAAS;EACpC"}
1
+ {"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !disabled && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\t// Try focusing immediately for optimistic submission UX, then ensure focus\n\t\t// sticks after the submit button handles the click.\n\t\tfocusComposer();\n\t\trequestAnimationFrame(() => {\n\t\t\tfocusComposer();\n\t\t});\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"group/multimodal-input flex flex-col rounded border border-co-border bg-co-background ring-offset-2 focus-within:ring-1 focus-within:ring-co-primary/10 dark:bg-co-background-200\">\n\t\t\t\t<Primitive.MultimodalInput\n\t\t\t\t\tautoFocus\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/50 focus-visible:outline-none\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\terror={error}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tplaceholder={resolvedPlaceholder}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tvalue={value}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex items-center justify-between py-1 pr-1 pl-3\">\n\t\t\t\t\t<Watermark />\n\n\t\t\t\t\t<div className=\"flex items-center gap-0.5\">\n\t\t\t\t\t\t{/* File attachment button */}\n\t\t\t\t\t\t{/* {onFileSelect && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.attachFiles\")}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t\t\t\tfiles.length >= maxFiles && \"opacity-50\"\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonClick={handleAttachClick}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" name=\"attachment\" />\n\t\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t\t<Primitive.FileInput\n\t\t\t\t\t\t\t\t\taccept={allowedFileTypes.join(\",\")}\n\t\t\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)} */}\n\n\t\t\t\t\t\t{/* Send button */}\n\t\t\t\t\t\t<SendButton disabled={!canSubmit} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t);\n};\n\nexport type SendButtonProps = {\n\tclassName?: string;\n\tdisabled?: boolean;\n};\n\nexport const SendButton: React.FC<SendButtonProps> = ({\n\tclassName,\n\tdisabled = false,\n}) => (\n\t<Primitive.Button\n\t\tclassName={cn(\n\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-primary hover:bg-co-muted disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tclassName\n\t\t)}\n\t\tdisabled={disabled}\n\t\ttype=\"submit\"\n\t>\n\t\t<Icon className=\"h-4 w-4\" filledOnHover name=\"send\" />\n\t</Primitive.Button>\n);\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAaA,mBAAmD,EAC/D,WACA,OACA,UACA,UACA,cACA,aACA,WAAW,OACX,eAAe,OACf,OACA,QAAQ,EAAE,EACV,cACA,WAAW,GACX,cAAc,KAAK,OAAO,MAC1B,mBAAmB;CAAC;CAAW;CAAmB;CAAS,OACtD;AACgB,QAAyB,KAAK;CACnD,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;CAC7D,MAAM,EAAE,eAAe,aAAa,mBAAmB;EACtD;EACA;EACA;EACA,CAAC;CACF,MAAM,YAAY,CAAC,YAAY;CAC/B,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBACL,eAAe,KAAK,wCAAwC;CAE7D,MAAM,qBAAqB;AAC1B,MAAI,CAAC,UACJ;AAGD,YAAU;AAGV,iBAAe;AACf,8BAA4B;AAC3B,kBAAe;IACd;;CAGH,MAAM,oBAAoB,MAAuB;AAChD,IAAE,gBAAgB;AAClB,gBAAc;;CASf,MAAM,kBAAkB,UAAkB;AACzC,MAAI,QAAQ,KACX,QAAO,GAAG,MAAM;AAEjB,MAAI,QAAQ,OAAO,KAClB,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAErC,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,QACC,qBAAC;EAAK,WAAU;EAAsB,UAAU;;GAE9C,SACA,oBAAC;IACA,WAAU;IACV,IAAG;cAEF,MAAM;KACF;GAIN,MAAM,SAAS,KACf,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,MAAM,UACjB,qBAAC;KACA,WAAU;;MAGV,oBAACC;OAAK,WAAU;OAAU,MAAK;QAAe;MAC9C,oBAAC;OAAK,WAAU;iBAA0B,KAAK;QAAY;MAC3D,oBAAC;OAAK,WAAU;iBACd,eAAe,KAAK,KAAK;QACpB;MACN,gBACA,oBAAC;OACA,cAAY,KAAK,6BAA6B,EAC7C,UAAU,KAAK,MACf,CAAC;OACF,WAAU;OACV,eAAe,aAAa,MAAM;OAClC,MAAK;iBAEL,oBAACA;QAAK,WAAU;QAAU,MAAK;SAAU;QACjC;;OAjBL,GAAG,KAAK,KAAK,GAAG,QAmBhB,CACL;KACG;GAIP,qBAAC;IAAI,WAAU;eACd,oBAACC;KACA;KACA,WAAW,GACV,+HACA,UACA;KACS;KACH;KACG;KACI;KACd,UAAU;KACV,aAAa;KACb,KAAK;KACE;MACN,EAEF,qBAAC;KAAI,WAAU;gBACd,oBAAC,cAAY,EAEb,oBAAC;MAAI,WAAU;gBAgCd,oBAAC,cAAW,UAAU,CAAC,YAAa;OAC/B;MACD;KACD;;GACA;;AAST,MAAaC,cAAyC,EACrD,WACA,WAAW,YAEX,oBAACC;CACA,WAAW,GACV,+IACA,UACA;CACS;CACV,MAAK;WAEL,oBAACH;EAAK,WAAU;EAAU;EAAc,MAAK;GAAS;EACpC"}
@@ -19,7 +19,7 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
19
19
  children: /* @__PURE__ */ jsxs("div", {
20
20
  className: cn("flex w-full min-w-0 flex-1 flex-col gap-1", isSentByViewerFinal && "items-end"),
21
21
  children: [/* @__PURE__ */ jsx(TimelineItemContent, {
22
- className: cn("block min-w-0 max-w-[300px] break-all rounded-lg px-3.5 py-2.5 text-sm", {
22
+ className: cn("block min-w-0 max-w-[300px] whitespace-pre-wrap break-words rounded-lg px-3.5 py-2.5 text-sm", {
23
23
  "bg-co-background-300 text-co-foreground dark:bg-co-background-600": !isSentByViewerFinal,
24
24
  "bg-co-primary text-co-primary-foreground": isSentByViewerFinal,
25
25
  "rounded-br-sm": isLast && isSentByViewerFinal,
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\treturn (\n\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"block min-w-0 max-w-[300px] break-all rounded-lg px-3.5 py-2.5 text-sm\",\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground dark:bg-co-background-600\":\n\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"bg-co-primary text-co-primary-foreground\":\n\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"rounded-br-sm\": isLast && isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"rounded-bl-sm\": isLast && !isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\trenderMarkdown\n\t\t\t\t\t\t\t\ttext={item.text}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{isLast && (\n\t\t\t\t\t\t\t\t<TimelineItemTimestamp\n\t\t\t\t\t\t\t\t\tclassName=\"px-1 text-co-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\ttimestamp={timestamp}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{() => (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t{timestamp.toLocaleTimeString([], {\n\t\t\t\t\t\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t{isAI &&\n\t\t\t\t\t\t\t\t\t\t\t\t` ${text(\"component.message.timestamp.aiIndicator\")}`}\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</TimelineItemTimestamp>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}}\n\t\t</PrimitiveTimelineItem>\n\t);\n}\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,oBAAoB,EACnC,MACA,SAAS,OACT,iBAAiB,SAC+B;CAChD,MAAM,OAAO,gBAAgB;AAC7B,QACC,oBAACA;EAA4B;aAC1B,EAAE,MAAM,gBAAgB;GAGzB,MAAM,sBAAsB;AAE5B,UACC,oBAAC;IACA,WAAW,GACV,qBACA,uBAAuB,oBACvB,CAAC,uBAAuB,WACxB;cAED,qBAAC;KACA,WAAW,GACV,6CACA,uBAAuB,YACvB;gBAED,oBAAC;MACA,WAAW,GACV,0EACA;OACC,qEACC,CAAC;OACF,4CACC;OACD,iBAAiB,UAAU;OAC3B,iBAAiB,UAAU,CAAC;OAC5B,CACD;MACD;MACA,MAAM,KAAK;OACV,EACD,UACA,oBAAC;MACA,WAAU;MACC;sBAGV,4CACE,UAAU,mBAAmB,EAAE,EAAE;OACjC,MAAM;OACN,QAAQ;OACR,CAAC,EACD,QACA,IAAI,KAAK,0CAA0C,MAClD;OAEmB;MAEpB;KACD;;GAGe"}
1
+ {"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\treturn (\n\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"block min-w-0 max-w-[300px] whitespace-pre-wrap break-words rounded-lg px-3.5 py-2.5 text-sm\",\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground dark:bg-co-background-600\":\n\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"bg-co-primary text-co-primary-foreground\":\n\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"rounded-br-sm\": isLast && isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\"rounded-bl-sm\": isLast && !isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\trenderMarkdown\n\t\t\t\t\t\t\t\ttext={item.text}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{isLast && (\n\t\t\t\t\t\t\t\t<TimelineItemTimestamp\n\t\t\t\t\t\t\t\t\tclassName=\"px-1 text-co-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\ttimestamp={timestamp}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{() => (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t{timestamp.toLocaleTimeString([], {\n\t\t\t\t\t\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t{isAI &&\n\t\t\t\t\t\t\t\t\t\t\t\t` ${text(\"component.message.timestamp.aiIndicator\")}`}\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</TimelineItemTimestamp>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}}\n\t\t</PrimitiveTimelineItem>\n\t);\n}\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,oBAAoB,EACnC,MACA,SAAS,OACT,iBAAiB,SAC+B;CAChD,MAAM,OAAO,gBAAgB;AAC7B,QACC,oBAACA;EAA4B;aAC1B,EAAE,MAAM,gBAAgB;GAGzB,MAAM,sBAAsB;AAE5B,UACC,oBAAC;IACA,WAAW,GACV,qBACA,uBAAuB,oBACvB,CAAC,uBAAuB,WACxB;cAED,qBAAC;KACA,WAAW,GACV,6CACA,uBAAuB,YACvB;gBAED,oBAAC;MACA,WAAW,GACV,gGACA;OACC,qEACC,CAAC;OACF,4CACC;OACD,iBAAiB,UAAU;OAC3B,iBAAiB,UAAU,CAAC;OAC5B,CACD;MACD;MACA,MAAM,KAAK;OACV,EACD,UACA,oBAAC;MACA,WAAU;MACC;sBAGV,4CACE,UAAU,mBAAmB,EAAE,EAAE;OACjC,MAAM;OACN,QAAQ;OACR,CAAC,EACD,QACA,IAAI,KAAK,0CAA0C,MAClD;OAEmB;MAEpB;KACD;;GAGe"}
@@ -1 +1 @@
1
- {"version":3,"file":"typing-indicator.d.ts","names":[],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,qBAAA;KAEA,iBAAA;EAFA,EAAA,EAAA,MAAA;EAEA,IAAA,EAEL,qBAFsB;AAK7B,CAAA;AAAwD,KAA5C,oBAAA,GAAuB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,GAAA;EAArB,YAAM,EAC1B,iBAD0B,EAAA;EAC1B,iBAAA,CAAA,EACM,gBADN,EAAA;EACM,oBAAA,CAAA,EACG,mBADH,EAAA;EACG,WAAA,CAAA,EAAA,OAAA;CAAmB;AAI9B,cAAA,YAAgB,EAAA,CAAA;EAAA;CAInB,EAAA;EAuBG,SAAA,CAAA,EAAA,MAuDZ;CAvD2B,EAAA,GAvBxB,OAAA,CAAM,YAuBkB;AAAA,cAAf,eAAe,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,GAAA;EAjCb,YAAA,EAAA,iBAAA,EAAA;EACM,iBAAA,CAAA,EAAA,gBAAA,EAAA;EACG,oBAAA,CAAA,EAAA,mBAAA,EAAA"}
1
+ {"version":3,"file":"typing-indicator.d.ts","names":[],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,qBAAA;KAEA,iBAAA;EAFA,EAAA,EAAA,MAAA;EAEA,IAAA,EAEL,qBAFsB;AAK7B,CAAA;AAAwD,KAA5C,oBAAA,GAAuB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,GAAA;EAArB,YAAM,EAC1B,iBAD0B,EAAA;EAC1B,iBAAA,CAAA,EACM,gBADN,EAAA;EACM,oBAAA,CAAA,EACG,mBADH,EAAA;EACG,WAAA,CAAA,EAAA,OAAA;CAAmB;AAI9B,cAAA,YAAgB,EAAA,CAAA;EAAA;CAIzB,EAAM;EAuBG,SAAA,CAAA,EAAA,MAuDZ;CAvD2B,EAAA,GAvBxB,OAAA,CAAM,YAuBkB;AAAA,cAAf,eAAe,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,GAAA;EAjCb,YAAA,EAAA,iBAAA,EAAA;EACM,iBAAA,CAAA,EAAA,gBAAA,EAAA;EACG,oBAAA,CAAA,EAAA,mBAAA,EAAA"}
@@ -62,7 +62,7 @@ const ConversationHistoryPage = (_props = {}) => {
62
62
  }), /* @__PURE__ */ jsxs("div", {
63
63
  className: "flex flex-1 flex-col items-center justify-between gap-2 px-6 pb-4",
64
64
  children: [history.conversations.length > 0 && /* @__PURE__ */ jsxs("div", {
65
- className: "flex flex-col items-center justify-between gap-2 pt-10",
65
+ className: "flex w-full flex-col items-center justify-between gap-2 pt-4",
66
66
  children: [/* @__PURE__ */ jsx("div", {
67
67
  className: "flex w-full flex-col overflow-clip rounded-md border border-co-border/80",
68
68
  children: history.visibleConversations.map((conversation) => /* @__PURE__ */ jsx(ConversationButtonLink, {
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-history.js","names":["ConversationHistoryPage: React.FC<ConversationHistoryPageProps>","Icon"],"sources":["../../../src/support/pages/conversation-history.tsx"],"sourcesContent":["import { useSupport } from \"@cossistant/react\";\nimport { PENDING_CONVERSATION_ID } from \"@cossistant/react/utils/id\";\nimport type React from \"react\";\nimport { useConversationHistoryPage } from \"../../hooks/use-conversation-history-page\";\nimport { AvatarStack } from \"../components/avatar-stack\";\nimport { CoButton } from \"../components/button\";\nimport { ConversationButtonLink } from \"../components/conversation-button-link\";\nimport { Header } from \"../components/header\";\nimport Icon from \"../components/icons\";\nimport { Watermark } from \"../components/watermark\";\nimport { useSupportNavigation } from \"../store/support-store\";\nimport { Text, useSupportText } from \"../text\";\n\ntype ConversationHistoryPageProps = {\n\tparams?: undefined;\n};\n\n/**\n * Conversation history page with list of past conversations and pagination.\n */\nexport const ConversationHistoryPage: React.FC<ConversationHistoryPageProps> = (\n\t_props = {}\n) => {\n\tconst { goBack, canGoBack, navigate } = useSupportNavigation();\n\tconst { availableAIAgents, availableHumanAgents } = useSupport();\n\tconst text = useSupportText();\n\n\tconst history = useConversationHistoryPage({\n\t\tinitialVisibleCount: 4,\n\t\tonOpenConversation: (conversationId) => {\n\t\t\tnavigate({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: {\n\t\t\t\t\tconversationId,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tonStartConversation: (initialMessage) => {\n\t\t\tnavigate({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: {\n\t\t\t\t\tconversationId: PENDING_CONVERSATION_ID,\n\t\t\t\t\tinitialMessage,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst handleGoBack = () => {\n\t\tif (canGoBack) {\n\t\t\tgoBack();\n\t\t} else {\n\t\t\tnavigate({\n\t\t\t\tpage: \"HOME\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<Header onGoBack={handleGoBack}>\n\t\t\t\t<div className=\"flex w-full items-center justify-between gap-2 py-3\">\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t<h2 className=\"max-w-xs text-balance font-co-sans text-md leading-normal\">\n\t\t\t\t\t\t\t{text(\"page.conversationHistory.title\")}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={availableAIAgents}\n\t\t\t\t\t\tgapWidth={2}\n\t\t\t\t\t\thumanAgents={availableHumanAgents}\n\t\t\t\t\t\tsize={32}\n\t\t\t\t\t\tspacing={28}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</Header>\n\n\t\t\t<div className=\"flex flex-1 flex-col items-center justify-between gap-2 px-6 pb-4\">\n\t\t\t\t{history.conversations.length > 0 && (\n\t\t\t\t\t<div className=\"flex flex-col items-center justify-between gap-2 pt-10\">\n\t\t\t\t\t\t<div className=\"flex w-full flex-col overflow-clip rounded-md border border-co-border/80\">\n\t\t\t\t\t\t\t{history.visibleConversations.map((conversation) => (\n\t\t\t\t\t\t\t\t<ConversationButtonLink\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\t\t\tconversation={conversation}\n\t\t\t\t\t\t\t\t\tkey={conversation.id}\n\t\t\t\t\t\t\t\t\tonClick={() => history.openConversation(conversation.id)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{history.hasMore && (\n\t\t\t\t\t\t\t<CoButton\n\t\t\t\t\t\t\t\tclassName=\"relative mt-6 w-full text-co-primary/40 text-xs hover:text-co-primary\"\n\t\t\t\t\t\t\t\tonClick={history.showAll}\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\tas=\"span\"\n\t\t\t\t\t\t\t\t\ttextKey=\"page.conversationHistory.showMore\"\n\t\t\t\t\t\t\t\t\tvariables={{ count: history.remainingCount }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<div className=\"sticky bottom-4 z-10 flex w-full flex-col items-center gap-2\">\n\t\t\t\t\t<CoButton\n\t\t\t\t\t\tclassName=\"relative w-full justify-between\"\n\t\t\t\t\t\tonClick={() => history.startConversation()}\n\t\t\t\t\t\tsize=\"large\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\tclassName=\"-translate-y-1/2 absolute top-1/2 right-4 size-3 text-co-primary/60 transition-transform duration-200 group-hover/btn:translate-x-0.5 group-hover/btn:text-co-primary\"\n\t\t\t\t\t\t\tname=\"arrow-right\"\n\t\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<Text as=\"span\" textKey=\"common.actions.askQuestion\" />\n\t\t\t\t\t</CoButton>\n\t\t\t\t\t<Watermark className=\"mt-4 mb-2\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,MAAaA,2BACZ,SAAS,EAAE,KACP;CACJ,MAAM,EAAE,QAAQ,WAAW,aAAa,sBAAsB;CAC9D,MAAM,EAAE,mBAAmB,yBAAyB,YAAY;CAChE,MAAM,OAAO,gBAAgB;CAE7B,MAAM,UAAU,2BAA2B;EAC1C,qBAAqB;EACrB,qBAAqB,mBAAmB;AACvC,YAAS;IACR,MAAM;IACN,QAAQ,EACP,gBACA;IACD,CAAC;;EAEH,sBAAsB,mBAAmB;AACxC,YAAS;IACR,MAAM;IACN,QAAQ;KACP,gBAAgB;KAChB;KACA;IACD,CAAC;;EAEH,CAAC;CAEF,MAAM,qBAAqB;AAC1B,MAAI,UACH,SAAQ;MAER,UAAS,EACR,MAAM,QACN,CAAC;;AAIJ,QACC,4CACC,oBAAC;EAAO,UAAU;YACjB,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAI,WAAU;cACd,oBAAC;KAAG,WAAU;eACZ,KAAK,iCAAiC;MACnC;KACA,EACN,oBAAC;IACA,UAAU;IACV,UAAU;IACV,aAAa;IACb,MAAM;IACN,SAAS;KACR;IACG;GACE,EAET,qBAAC;EAAI,WAAU;aACb,QAAQ,cAAc,SAAS,KAC/B,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAI,WAAU;cACb,QAAQ,qBAAqB,KAAK,iBAClC,oBAAC;KACA,WAAU;KACI;KAEd,eAAe,QAAQ,iBAAiB,aAAa,GAAG;OADnD,aAAa,GAEjB,CACD;KACG,EACL,QAAQ,WACR,oBAAC;IACA,WAAU;IACV,SAAS,QAAQ;IACjB,SAAQ;cAER,oBAAC;KACA,IAAG;KACH,SAAQ;KACR,WAAW,EAAE,OAAO,QAAQ,gBAAgB;MAC3C;KACQ;IAEP,EAGP,qBAAC;GAAI,WAAU;cACd,qBAAC;IACA,WAAU;IACV,eAAe,QAAQ,mBAAmB;IAC1C,MAAK;IACL,SAAQ;eAER,oBAACC;KACA,WAAU;KACV,MAAK;KACL,SAAQ;MACP,EACF,oBAAC;KAAK,IAAG;KAAO,SAAQ;MAA+B;KAC7C,EACX,oBAAC,aAAU,WAAU,cAAc;IAC9B;GACD,IACJ"}
1
+ {"version":3,"file":"conversation-history.js","names":["ConversationHistoryPage: React.FC<ConversationHistoryPageProps>","Icon"],"sources":["../../../src/support/pages/conversation-history.tsx"],"sourcesContent":["import { useSupport } from \"@cossistant/react\";\nimport { PENDING_CONVERSATION_ID } from \"@cossistant/react/utils/id\";\nimport type React from \"react\";\nimport { useConversationHistoryPage } from \"../../hooks/use-conversation-history-page\";\nimport { AvatarStack } from \"../components/avatar-stack\";\nimport { CoButton } from \"../components/button\";\nimport { ConversationButtonLink } from \"../components/conversation-button-link\";\nimport { Header } from \"../components/header\";\nimport Icon from \"../components/icons\";\nimport { Watermark } from \"../components/watermark\";\nimport { useSupportNavigation } from \"../store/support-store\";\nimport { Text, useSupportText } from \"../text\";\n\ntype ConversationHistoryPageProps = {\n\tparams?: undefined;\n};\n\n/**\n * Conversation history page with list of past conversations and pagination.\n */\nexport const ConversationHistoryPage: React.FC<ConversationHistoryPageProps> = (\n\t_props = {}\n) => {\n\tconst { goBack, canGoBack, navigate } = useSupportNavigation();\n\tconst { availableAIAgents, availableHumanAgents } = useSupport();\n\tconst text = useSupportText();\n\n\tconst history = useConversationHistoryPage({\n\t\tinitialVisibleCount: 4,\n\t\tonOpenConversation: (conversationId) => {\n\t\t\tnavigate({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: {\n\t\t\t\t\tconversationId,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tonStartConversation: (initialMessage) => {\n\t\t\tnavigate({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: {\n\t\t\t\t\tconversationId: PENDING_CONVERSATION_ID,\n\t\t\t\t\tinitialMessage,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst handleGoBack = () => {\n\t\tif (canGoBack) {\n\t\t\tgoBack();\n\t\t} else {\n\t\t\tnavigate({\n\t\t\t\tpage: \"HOME\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<Header onGoBack={handleGoBack}>\n\t\t\t\t<div className=\"flex w-full items-center justify-between gap-2 py-3\">\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t<h2 className=\"max-w-xs text-balance font-co-sans text-md leading-normal\">\n\t\t\t\t\t\t\t{text(\"page.conversationHistory.title\")}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={availableAIAgents}\n\t\t\t\t\t\tgapWidth={2}\n\t\t\t\t\t\thumanAgents={availableHumanAgents}\n\t\t\t\t\t\tsize={32}\n\t\t\t\t\t\tspacing={28}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</Header>\n\n\t\t\t<div className=\"flex flex-1 flex-col items-center justify-between gap-2 px-6 pb-4\">\n\t\t\t\t{history.conversations.length > 0 && (\n\t\t\t\t\t<div className=\"flex w-full flex-col items-center justify-between gap-2 pt-4\">\n\t\t\t\t\t\t<div className=\"flex w-full flex-col overflow-clip rounded-md border border-co-border/80\">\n\t\t\t\t\t\t\t{history.visibleConversations.map((conversation) => (\n\t\t\t\t\t\t\t\t<ConversationButtonLink\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\t\t\tconversation={conversation}\n\t\t\t\t\t\t\t\t\tkey={conversation.id}\n\t\t\t\t\t\t\t\t\tonClick={() => history.openConversation(conversation.id)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{history.hasMore && (\n\t\t\t\t\t\t\t<CoButton\n\t\t\t\t\t\t\t\tclassName=\"relative mt-6 w-full text-co-primary/40 text-xs hover:text-co-primary\"\n\t\t\t\t\t\t\t\tonClick={history.showAll}\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\tas=\"span\"\n\t\t\t\t\t\t\t\t\ttextKey=\"page.conversationHistory.showMore\"\n\t\t\t\t\t\t\t\t\tvariables={{ count: history.remainingCount }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<div className=\"sticky bottom-4 z-10 flex w-full flex-col items-center gap-2\">\n\t\t\t\t\t<CoButton\n\t\t\t\t\t\tclassName=\"relative w-full justify-between\"\n\t\t\t\t\t\tonClick={() => history.startConversation()}\n\t\t\t\t\t\tsize=\"large\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\tclassName=\"-translate-y-1/2 absolute top-1/2 right-4 size-3 text-co-primary/60 transition-transform duration-200 group-hover/btn:translate-x-0.5 group-hover/btn:text-co-primary\"\n\t\t\t\t\t\t\tname=\"arrow-right\"\n\t\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<Text as=\"span\" textKey=\"common.actions.askQuestion\" />\n\t\t\t\t\t</CoButton>\n\t\t\t\t\t<Watermark className=\"mt-4 mb-2\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,MAAaA,2BACZ,SAAS,EAAE,KACP;CACJ,MAAM,EAAE,QAAQ,WAAW,aAAa,sBAAsB;CAC9D,MAAM,EAAE,mBAAmB,yBAAyB,YAAY;CAChE,MAAM,OAAO,gBAAgB;CAE7B,MAAM,UAAU,2BAA2B;EAC1C,qBAAqB;EACrB,qBAAqB,mBAAmB;AACvC,YAAS;IACR,MAAM;IACN,QAAQ,EACP,gBACA;IACD,CAAC;;EAEH,sBAAsB,mBAAmB;AACxC,YAAS;IACR,MAAM;IACN,QAAQ;KACP,gBAAgB;KAChB;KACA;IACD,CAAC;;EAEH,CAAC;CAEF,MAAM,qBAAqB;AAC1B,MAAI,UACH,SAAQ;MAER,UAAS,EACR,MAAM,QACN,CAAC;;AAIJ,QACC,4CACC,oBAAC;EAAO,UAAU;YACjB,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAI,WAAU;cACd,oBAAC;KAAG,WAAU;eACZ,KAAK,iCAAiC;MACnC;KACA,EACN,oBAAC;IACA,UAAU;IACV,UAAU;IACV,aAAa;IACb,MAAM;IACN,SAAS;KACR;IACG;GACE,EAET,qBAAC;EAAI,WAAU;aACb,QAAQ,cAAc,SAAS,KAC/B,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAI,WAAU;cACb,QAAQ,qBAAqB,KAAK,iBAClC,oBAAC;KACA,WAAU;KACI;KAEd,eAAe,QAAQ,iBAAiB,aAAa,GAAG;OADnD,aAAa,GAEjB,CACD;KACG,EACL,QAAQ,WACR,oBAAC;IACA,WAAU;IACV,SAAS,QAAQ;IACjB,SAAQ;cAER,oBAAC;KACA,IAAG;KACH,SAAQ;KACR,WAAW,EAAE,OAAO,QAAQ,gBAAgB;MAC3C;KACQ;IAEP,EAGP,qBAAC;GAAI,WAAU;cACd,qBAAC;IACA,WAAU;IACV,eAAe,QAAQ,mBAAmB;IAC1C,MAAK;IACL,SAAQ;eAER,oBAACC;KACA,WAAU;KACV,MAAK;KACL,SAAQ;MACP,EACF,oBAAC;KAAK,IAAG;KAAO,SAAQ;MAA+B;KAC7C,EACX,oBAAC,aAAU,WAAU,cAAc;IAC9B;GACD,IACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-render-element.d.ts","names":[],"sources":["../../src/utils/use-render-element.tsx"],"sourcesContent":[],"mappings":";;;;AAI+B,KAE1B,YAAA,GAAY,MAAS,GAAA,CAAI,iBAAA;AAAiB,KAE1C,SAAA,CAAA,KAAS,CAAA,GAAA,MAAA,GAAA,CAA4B,CAAA,KAAK,EAAL,KAAK,EAAA,GAAA,MAAA,CAAA;AAAA,KAE1C,QAAA,CAAA,KAAQ,EAAA,KAAA,CAAA,GAAA,CAAA,KAAA,EACL,KADK,EAAA,KAAA,EAEL,KAFK,EAAA,GAGR,OAAA,CAAM,YAHE;KAKR,WAJG,CAAA,KAAA,EAAA,YAI4B,YAJ5B,CAAA,GAAA;EACA,MAAA,CAAA,EAIE,OAAA,CAAM,YAJR,GAIuB,QAJvB,CAIgC,GAAA,CAAI,iBAJpC,CAIsD,GAJtD,CAAA,EAI4D,KAJ5D,CAAA;EACH,SAAM,CAAA,EAIE,SAJF,CAIY,KAJZ,CAAA;EAAY,OAAA,CAAA,EAAA,OAAA;AAAA,CAAA;KAQlB,YAN+B,CAAA,KAAA,EAAA,YAMC,YAND,CAAA,GAAA;EAC1B,KAAM,CAAA,EAMP,KANO;EAAwB,GAAI,CAAA,EAOrC,OAAA,CAAM,GAP+B,CAAA,GAAA,CAAA;EAAkB,KAAA,CAAA,EAQrD,OARqD,CAQ7C,GAAA,CAAI,iBARyC,CAQvB,GARuB,CAAA,CAAA;EAAM,OAAA,CAAA,EAAA,OAAA;CAArC;;;;AAK1B,iBAyBW,gBAzBC,CAAA,cA0BF,MA1BE,CAAA,MAAA,EAAA,GAAA,CAAA,EAAA,YA2BJ,YA3BI,CAAA,CAAA,GAAA,EA6BX,GA7BW,EAAA,cAAA,EA8BA,WA9BA,CA8BY,KA9BZ,EA8BmB,GA9BnB,CAAA,EAAA,MAAA,CAAA,EA+BP,YA/BO,CA+BM,KA/BN,EA+Ba,GA/Bb,CAAA,CAAA,EAgCd,OAAA,CAAM,YAhCQ,GAAA,IAAA"}
1
+ {"version":3,"file":"use-render-element.d.ts","names":[],"sources":["../../src/utils/use-render-element.tsx"],"sourcesContent":[],"mappings":";;;;AAI+B,KAE1B,YAAA,GAAY,MAAS,GAAA,CAAI,iBAAA;AAAiB,KAE1C,SAAA,CAAA,KAAS,CAAA,GAAA,MAAA,GAA4B,CAAA,CAAA,KAAK,EAAL,KAAK,EAAA,GAAA,MAAA,CAAA;AAAA,KAE1C,QAAA,CAAA,KAAQ,EAAA,KAAA,CAAA,GAAA,CAAA,KAAA,EACL,KADK,EAAA,KAAA,EAEL,KAFK,EAAA,GAGR,OAAA,CAAM,YAHE;KAKR,WAJG,CAAA,KAAA,EAAA,YAI4B,YAJ5B,CAAA,GAAA;EACA,MAAA,CAAA,EAIE,OAAA,CAAM,YAJR,GAIuB,QAJvB,CAIgC,GAAA,CAAI,iBAJpC,CAIsD,GAJtD,CAAA,EAI4D,KAJ5D,CAAA;EACH,SAAM,CAAA,EAIE,SAJF,CAIY,KAJZ,CAAA;EAAY,OAAA,CAAA,EAAA,OAAA;AAAA,CAAA;KAQlB,YAN+B,CAAA,KAAA,EAAA,YAMC,YAND,CAAA,GAAA;EAC1B,KAAM,CAAA,EAMP,KANO;EAAwB,GAAI,CAAA,EAOrC,OAAA,CAAM,GAP+B,CAAA,GAAA,CAAA;EAAkB,KAAA,CAAA,EAQrD,OARqD,CAQ7C,GAAA,CAAI,iBARyC,CAQvB,GARuB,CAAA,CAAA;EAAM,OAAA,CAAA,EAAA,OAAA;CAArC;;;;AAK1B,iBAyBW,gBAzBC,CAAA,cA0BF,MA1BE,CAAA,MAAA,EAAA,GAAA,CAAA,EAAA,YA2BJ,YA3BI,CAAA,CAAA,GAAA,EA6BX,GA7BW,EAAA,cAAA,EA8BA,WA9BA,CA8BY,KA9BZ,EA8BmB,GA9BnB,CAAA,EAAA,MAAA,CAAA,EA+BP,YA/BO,CA+BM,KA/BN,EA+Ba,GA/Bb,CAAA,CAAA,EAgCd,OAAA,CAAM,YAhCQ,GAAA,IAAA"}