@gendive/chatllm 0.6.6 → 0.6.7

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.
@@ -1024,7 +1024,9 @@ var ChatHeader = ({
1024
1024
  onModelChange,
1025
1025
  onSettingsOpen,
1026
1026
  onSidebarToggle,
1027
- sidebarOpen
1027
+ sidebarOpen,
1028
+ showModelSelector = true,
1029
+ showSettings = true
1028
1030
  }) => {
1029
1031
  const [modelDropdownOpen, setModelDropdownOpen] = useState2(false);
1030
1032
  const currentModel = models.find((m) => m.id === model);
@@ -1081,7 +1083,7 @@ var ChatHeader = ({
1081
1083
  )
1082
1084
  ] }),
1083
1085
  /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
1084
- /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
1086
+ showModelSelector && /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
1085
1087
  /* @__PURE__ */ jsxs2(
1086
1088
  "button",
1087
1089
  {
@@ -1248,7 +1250,7 @@ var ChatHeader = ({
1248
1250
  )
1249
1251
  ] })
1250
1252
  ] }),
1251
- /* @__PURE__ */ jsx3(
1253
+ showSettings && /* @__PURE__ */ jsx3(
1252
1254
  "button",
1253
1255
  {
1254
1256
  onClick: onSettingsOpen,
@@ -2013,53 +2015,99 @@ var CodeBlock = ({ language, code }) => {
2013
2015
  var ImageWithCopyButton = ({ src, alt, imageKey }) => {
2014
2016
  const [isHovered, setIsHovered] = React4.useState(false);
2015
2017
  const [copyState, setCopyState] = React4.useState("idle");
2018
+ const imgRef = React4.useRef(null);
2016
2019
  const handleCopyImage = async () => {
2017
2020
  setCopyState("copying");
2018
2021
  try {
2019
- const response = await fetch(src);
2020
- if (!response.ok) throw new Error("Failed to fetch image");
2021
- const blob = await response.blob();
2022
- if (navigator.clipboard && navigator.clipboard.write) {
2023
- let imageBlob = blob;
2024
- if (blob.type !== "image/png") {
2025
- const img = new Image();
2026
- img.crossOrigin = "anonymous";
2022
+ if (!navigator.clipboard || !navigator.clipboard.write) {
2023
+ await navigator.clipboard.writeText(src);
2024
+ setCopyState("copied");
2025
+ setTimeout(() => setCopyState("idle"), 2e3);
2026
+ return;
2027
+ }
2028
+ const img = imgRef.current;
2029
+ if (img && img.complete && img.naturalWidth > 0) {
2030
+ try {
2031
+ const canvas = document.createElement("canvas");
2032
+ canvas.width = img.naturalWidth;
2033
+ canvas.height = img.naturalHeight;
2034
+ const ctx = canvas.getContext("2d");
2035
+ if (ctx) {
2036
+ ctx.drawImage(img, 0, 0);
2037
+ const blob = await new Promise((resolve) => {
2038
+ canvas.toBlob(resolve, "image/png");
2039
+ });
2040
+ if (blob) {
2041
+ await navigator.clipboard.write([
2042
+ new ClipboardItem({ "image/png": blob })
2043
+ ]);
2044
+ setCopyState("copied");
2045
+ setTimeout(() => setCopyState("idle"), 2e3);
2046
+ return;
2047
+ }
2048
+ }
2049
+ } catch {
2050
+ console.log("Canvas method failed (CORS), trying fetch...");
2051
+ }
2052
+ }
2053
+ try {
2054
+ const response = await fetch(src, { mode: "cors" });
2055
+ if (response.ok) {
2056
+ const blob = await response.blob();
2057
+ if (blob.type === "image/png") {
2058
+ await navigator.clipboard.write([
2059
+ new ClipboardItem({ "image/png": blob })
2060
+ ]);
2061
+ setCopyState("copied");
2062
+ setTimeout(() => setCopyState("idle"), 2e3);
2063
+ return;
2064
+ }
2065
+ const tempImg = new Image();
2066
+ const blobUrl = URL.createObjectURL(blob);
2027
2067
  await new Promise((resolve, reject) => {
2028
- img.onload = () => {
2029
- const canvas = document.createElement("canvas");
2030
- canvas.width = img.naturalWidth;
2031
- canvas.height = img.naturalHeight;
2032
- const ctx = canvas.getContext("2d");
2033
- if (!ctx) {
2034
- reject(new Error("Failed to get canvas context"));
2035
- return;
2036
- }
2037
- ctx.drawImage(img, 0, 0);
2038
- canvas.toBlob((pngBlob) => {
2068
+ tempImg.onload = async () => {
2069
+ try {
2070
+ const canvas = document.createElement("canvas");
2071
+ canvas.width = tempImg.naturalWidth;
2072
+ canvas.height = tempImg.naturalHeight;
2073
+ const ctx = canvas.getContext("2d");
2074
+ if (!ctx) {
2075
+ reject(new Error("Failed to get canvas context"));
2076
+ return;
2077
+ }
2078
+ ctx.drawImage(tempImg, 0, 0);
2079
+ const pngBlob = await new Promise((res) => {
2080
+ canvas.toBlob(res, "image/png");
2081
+ });
2082
+ URL.revokeObjectURL(blobUrl);
2039
2083
  if (pngBlob) {
2040
- imageBlob = pngBlob;
2084
+ await navigator.clipboard.write([
2085
+ new ClipboardItem({ "image/png": pngBlob })
2086
+ ]);
2087
+ setCopyState("copied");
2088
+ setTimeout(() => setCopyState("idle"), 2e3);
2041
2089
  resolve();
2042
2090
  } else {
2043
- reject(new Error("Failed to convert to PNG"));
2091
+ reject(new Error("Failed to create PNG blob"));
2044
2092
  }
2045
- }, "image/png");
2093
+ } catch (err) {
2094
+ reject(err);
2095
+ }
2096
+ };
2097
+ tempImg.onerror = () => {
2098
+ URL.revokeObjectURL(blobUrl);
2099
+ reject(new Error("Failed to load image"));
2046
2100
  };
2047
- img.onerror = () => reject(new Error("Failed to load image"));
2048
- img.src = URL.createObjectURL(blob);
2101
+ tempImg.src = blobUrl;
2049
2102
  });
2103
+ return;
2050
2104
  }
2051
- await navigator.clipboard.write([
2052
- new ClipboardItem({
2053
- [imageBlob.type]: imageBlob
2054
- })
2055
- ]);
2056
- setCopyState("copied");
2057
- setTimeout(() => setCopyState("idle"), 2e3);
2058
- } else {
2059
- await navigator.clipboard.writeText(src);
2060
- setCopyState("copied");
2061
- setTimeout(() => setCopyState("idle"), 2e3);
2105
+ } catch {
2106
+ console.log("Fetch method failed, using URL fallback");
2062
2107
  }
2108
+ await navigator.clipboard.writeText(src);
2109
+ setCopyState("copied");
2110
+ setTimeout(() => setCopyState("idle"), 2e3);
2063
2111
  } catch (error) {
2064
2112
  console.error("Failed to copy image:", error);
2065
2113
  setCopyState("error");
@@ -2102,9 +2150,11 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
2102
2150
  /* @__PURE__ */ jsx6(
2103
2151
  "img",
2104
2152
  {
2153
+ ref: imgRef,
2105
2154
  src,
2106
2155
  alt,
2107
2156
  className: "chatllm-image",
2157
+ crossOrigin: "anonymous",
2108
2158
  style: {
2109
2159
  maxWidth: "100%",
2110
2160
  borderRadius: "8px",
@@ -4472,7 +4522,9 @@ var ChatUI = ({
4472
4522
  onModelChange: setModel,
4473
4523
  onSettingsOpen: openSettings,
4474
4524
  onSidebarToggle: toggleSidebar,
4475
- sidebarOpen
4525
+ sidebarOpen,
4526
+ showModelSelector,
4527
+ showSettings
4476
4528
  }
4477
4529
  ),
4478
4530
  messages.length === 0 ? /* @__PURE__ */ jsx12(