@gendive/chatllm 0.6.8 → 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/index.js +131 -119
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +131 -119
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -2065,97 +2065,80 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
|
2065
2065
|
const [isHovered, setIsHovered] = import_react5.default.useState(false);
|
|
2066
2066
|
const [copyState, setCopyState] = import_react5.default.useState("idle");
|
|
2067
2067
|
const imgRef = import_react5.default.useRef(null);
|
|
2068
|
-
const
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
canvas.height = img.naturalHeight;
|
|
2083
|
-
const ctx = canvas.getContext("2d");
|
|
2084
|
-
if (ctx) {
|
|
2085
|
-
ctx.drawImage(img, 0, 0);
|
|
2086
|
-
const blob = await new Promise((resolve) => {
|
|
2087
|
-
canvas.toBlob(resolve, "image/png");
|
|
2088
|
-
});
|
|
2089
|
-
if (blob) {
|
|
2090
|
-
await navigator.clipboard.write([
|
|
2091
|
-
new ClipboardItem({ "image/png": blob })
|
|
2092
|
-
]);
|
|
2093
|
-
setCopyState("copied");
|
|
2094
|
-
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2095
|
-
return;
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
} catch {
|
|
2099
|
-
console.log("Canvas method failed (CORS), trying fetch...");
|
|
2068
|
+
const getImageBlob = async () => {
|
|
2069
|
+
const img = imgRef.current;
|
|
2070
|
+
if (img && img.complete && img.naturalWidth > 0) {
|
|
2071
|
+
try {
|
|
2072
|
+
const canvas = document.createElement("canvas");
|
|
2073
|
+
canvas.width = img.naturalWidth;
|
|
2074
|
+
canvas.height = img.naturalHeight;
|
|
2075
|
+
const ctx = canvas.getContext("2d");
|
|
2076
|
+
if (ctx) {
|
|
2077
|
+
ctx.drawImage(img, 0, 0);
|
|
2078
|
+
const blob = await new Promise((resolve) => {
|
|
2079
|
+
canvas.toBlob(resolve, "image/png");
|
|
2080
|
+
});
|
|
2081
|
+
if (blob) return blob;
|
|
2100
2082
|
}
|
|
2083
|
+
} catch {
|
|
2084
|
+
console.log("Canvas method failed (CORS), trying fetch...");
|
|
2101
2085
|
}
|
|
2086
|
+
}
|
|
2087
|
+
if (!src.startsWith("data:")) {
|
|
2102
2088
|
try {
|
|
2103
2089
|
const response = await fetch(src, { mode: "cors" });
|
|
2104
2090
|
if (response.ok) {
|
|
2105
2091
|
const blob = await response.blob();
|
|
2106
|
-
if (blob.type === "image/png")
|
|
2107
|
-
await navigator.clipboard.write([
|
|
2108
|
-
new ClipboardItem({ "image/png": blob })
|
|
2109
|
-
]);
|
|
2110
|
-
setCopyState("copied");
|
|
2111
|
-
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2112
|
-
return;
|
|
2113
|
-
}
|
|
2092
|
+
if (blob.type === "image/png") return blob;
|
|
2114
2093
|
const tempImg = new Image();
|
|
2115
2094
|
const blobUrl = URL.createObjectURL(blob);
|
|
2116
|
-
|
|
2117
|
-
tempImg.onload =
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
if (!ctx) {
|
|
2124
|
-
reject(new Error("Failed to get canvas context"));
|
|
2125
|
-
return;
|
|
2126
|
-
}
|
|
2095
|
+
return new Promise((resolve) => {
|
|
2096
|
+
tempImg.onload = () => {
|
|
2097
|
+
const canvas = document.createElement("canvas");
|
|
2098
|
+
canvas.width = tempImg.naturalWidth;
|
|
2099
|
+
canvas.height = tempImg.naturalHeight;
|
|
2100
|
+
const ctx = canvas.getContext("2d");
|
|
2101
|
+
if (ctx) {
|
|
2127
2102
|
ctx.drawImage(tempImg, 0, 0);
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2103
|
+
canvas.toBlob((pngBlob) => {
|
|
2104
|
+
URL.revokeObjectURL(blobUrl);
|
|
2105
|
+
resolve(pngBlob);
|
|
2106
|
+
}, "image/png");
|
|
2107
|
+
} else {
|
|
2131
2108
|
URL.revokeObjectURL(blobUrl);
|
|
2132
|
-
|
|
2133
|
-
await navigator.clipboard.write([
|
|
2134
|
-
new ClipboardItem({ "image/png": pngBlob })
|
|
2135
|
-
]);
|
|
2136
|
-
setCopyState("copied");
|
|
2137
|
-
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2138
|
-
resolve();
|
|
2139
|
-
} else {
|
|
2140
|
-
reject(new Error("Failed to create PNG blob"));
|
|
2141
|
-
}
|
|
2142
|
-
} catch (err) {
|
|
2143
|
-
reject(err);
|
|
2109
|
+
resolve(null);
|
|
2144
2110
|
}
|
|
2145
2111
|
};
|
|
2146
2112
|
tempImg.onerror = () => {
|
|
2147
2113
|
URL.revokeObjectURL(blobUrl);
|
|
2148
|
-
|
|
2114
|
+
resolve(null);
|
|
2149
2115
|
};
|
|
2150
2116
|
tempImg.src = blobUrl;
|
|
2151
2117
|
});
|
|
2152
|
-
return;
|
|
2153
2118
|
}
|
|
2154
2119
|
} catch {
|
|
2155
|
-
console.log("Fetch method failed
|
|
2120
|
+
console.log("Fetch method failed");
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
return null;
|
|
2124
|
+
};
|
|
2125
|
+
const handleCopy = async () => {
|
|
2126
|
+
setCopyState("copying");
|
|
2127
|
+
try {
|
|
2128
|
+
if (!navigator.clipboard?.write) {
|
|
2129
|
+
await navigator.clipboard.writeText(src);
|
|
2130
|
+
setCopyState("copied");
|
|
2131
|
+
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
const blob = await getImageBlob();
|
|
2135
|
+
if (blob) {
|
|
2136
|
+
await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
|
|
2137
|
+
setCopyState("copied");
|
|
2138
|
+
} else {
|
|
2139
|
+
await navigator.clipboard.writeText(src);
|
|
2140
|
+
setCopyState("copied");
|
|
2156
2141
|
}
|
|
2157
|
-
await navigator.clipboard.writeText(src);
|
|
2158
|
-
setCopyState("copied");
|
|
2159
2142
|
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2160
2143
|
} catch (error) {
|
|
2161
2144
|
console.error("Failed to copy image:", error);
|
|
@@ -2163,27 +2146,34 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
|
2163
2146
|
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2164
2147
|
}
|
|
2165
2148
|
};
|
|
2166
|
-
const
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2149
|
+
const handleDownload = async () => {
|
|
2150
|
+
try {
|
|
2151
|
+
const blob = await getImageBlob();
|
|
2152
|
+
const url = blob ? URL.createObjectURL(blob) : src;
|
|
2153
|
+
const link = document.createElement("a");
|
|
2154
|
+
link.href = url;
|
|
2155
|
+
link.download = alt || `image-${Date.now()}.png`;
|
|
2156
|
+
document.body.appendChild(link);
|
|
2157
|
+
link.click();
|
|
2158
|
+
document.body.removeChild(link);
|
|
2159
|
+
if (blob) URL.revokeObjectURL(url);
|
|
2160
|
+
} catch (error) {
|
|
2161
|
+
console.error("Failed to download image:", error);
|
|
2162
|
+
window.open(src, "_blank");
|
|
2176
2163
|
}
|
|
2177
2164
|
};
|
|
2178
|
-
const
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2165
|
+
const toolbarButtonStyle = {
|
|
2166
|
+
display: "flex",
|
|
2167
|
+
alignItems: "center",
|
|
2168
|
+
justifyContent: "center",
|
|
2169
|
+
width: "36px",
|
|
2170
|
+
height: "36px",
|
|
2171
|
+
backgroundColor: "transparent",
|
|
2172
|
+
border: "none",
|
|
2173
|
+
borderRadius: "8px",
|
|
2174
|
+
cursor: "pointer",
|
|
2175
|
+
color: "var(--chatllm-text-muted, #9ca3af)",
|
|
2176
|
+
transition: "background-color 0.2s, color 0.2s"
|
|
2187
2177
|
};
|
|
2188
2178
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2189
2179
|
"div",
|
|
@@ -2213,50 +2203,72 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
|
2213
2203
|
}
|
|
2214
2204
|
),
|
|
2215
2205
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2216
|
-
"
|
|
2206
|
+
"div",
|
|
2217
2207
|
{
|
|
2218
|
-
onClick: handleCopyImage,
|
|
2219
|
-
disabled: copyState === "copying",
|
|
2220
2208
|
style: {
|
|
2221
2209
|
position: "absolute",
|
|
2222
|
-
|
|
2210
|
+
bottom: "8px",
|
|
2211
|
+
left: "8px",
|
|
2223
2212
|
right: "8px",
|
|
2224
2213
|
display: "flex",
|
|
2225
2214
|
alignItems: "center",
|
|
2226
|
-
gap: "
|
|
2227
|
-
padding: "
|
|
2228
|
-
backgroundColor: "rgba(
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
cursor: copyState === "copying" ? "wait" : "pointer",
|
|
2235
|
-
opacity: isHovered || copyState !== "idle" ? 1 : 0,
|
|
2236
|
-
transform: isHovered || copyState !== "idle" ? "translateY(0)" : "translateY(-4px)",
|
|
2215
|
+
gap: "4px",
|
|
2216
|
+
padding: "8px 12px",
|
|
2217
|
+
backgroundColor: "rgba(255, 255, 255, 0.95)",
|
|
2218
|
+
backdropFilter: "blur(8px)",
|
|
2219
|
+
borderRadius: "8px",
|
|
2220
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
2221
|
+
opacity: isHovered ? 1 : 0,
|
|
2222
|
+
transform: isHovered ? "translateY(0)" : "translateY(4px)",
|
|
2237
2223
|
transition: "opacity 0.2s ease, transform 0.2s ease",
|
|
2238
|
-
|
|
2239
|
-
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)"
|
|
2224
|
+
pointerEvents: isHovered ? "auto" : "none"
|
|
2240
2225
|
},
|
|
2241
2226
|
children: [
|
|
2242
2227
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2243
|
-
"
|
|
2228
|
+
"button",
|
|
2244
2229
|
{
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2230
|
+
onClick: handleCopy,
|
|
2231
|
+
disabled: copyState === "copying",
|
|
2232
|
+
style: {
|
|
2233
|
+
...toolbarButtonStyle,
|
|
2234
|
+
color: copyState === "copied" ? "var(--chatllm-success, #22c55e)" : copyState === "error" ? "var(--chatllm-error, #ef4444)" : "var(--chatllm-text-muted, #9ca3af)"
|
|
2235
|
+
},
|
|
2236
|
+
title: copyState === "copied" ? "\uBCF5\uC0AC\uB428!" : copyState === "error" ? "\uBCF5\uC0AC \uC2E4\uD328" : "\uBCF5\uC0AC\uD558\uAE30",
|
|
2237
|
+
onMouseOver: (e) => {
|
|
2238
|
+
e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover, #f3f4f6)";
|
|
2239
|
+
e.currentTarget.style.color = "var(--chatllm-text, #1f2937)";
|
|
2240
|
+
},
|
|
2241
|
+
onMouseOut: (e) => {
|
|
2242
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
2243
|
+
e.currentTarget.style.color = copyState === "copied" ? "var(--chatllm-success, #22c55e)" : "var(--chatllm-text-muted, #9ca3af)";
|
|
2244
|
+
},
|
|
2245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: copyState === "copied" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "20 6 9 17 4 12" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2254
2246
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
2255
2247
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
2256
|
-
] })
|
|
2248
|
+
] }) })
|
|
2257
2249
|
}
|
|
2258
2250
|
),
|
|
2259
|
-
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2252
|
+
"button",
|
|
2253
|
+
{
|
|
2254
|
+
onClick: handleDownload,
|
|
2255
|
+
style: toolbarButtonStyle,
|
|
2256
|
+
title: "\uB2E4\uC6B4\uB85C\uB4DC",
|
|
2257
|
+
onMouseOver: (e) => {
|
|
2258
|
+
e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover, #f3f4f6)";
|
|
2259
|
+
e.currentTarget.style.color = "var(--chatllm-text, #1f2937)";
|
|
2260
|
+
},
|
|
2261
|
+
onMouseOut: (e) => {
|
|
2262
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
2263
|
+
e.currentTarget.style.color = "var(--chatllm-text-muted, #9ca3af)";
|
|
2264
|
+
},
|
|
2265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
2267
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "7 10 12 15 17 10" }),
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
|
|
2269
|
+
] })
|
|
2270
|
+
}
|
|
2271
|
+
)
|
|
2260
2272
|
]
|
|
2261
2273
|
}
|
|
2262
2274
|
)
|