@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.
- package/dist/react/index.d.mts +4 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.js +91 -39
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +91 -39
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.d.mts
CHANGED
|
@@ -273,6 +273,10 @@ interface HeaderProps {
|
|
|
273
273
|
onSettingsOpen: () => void;
|
|
274
274
|
onSidebarToggle: () => void;
|
|
275
275
|
sidebarOpen: boolean;
|
|
276
|
+
/** 모델 선택기 표시 여부 */
|
|
277
|
+
showModelSelector?: boolean;
|
|
278
|
+
/** 설정 버튼 표시 여부 */
|
|
279
|
+
showSettings?: boolean;
|
|
276
280
|
}
|
|
277
281
|
interface EmptyStateProps {
|
|
278
282
|
greeting: string;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -273,6 +273,10 @@ interface HeaderProps {
|
|
|
273
273
|
onSettingsOpen: () => void;
|
|
274
274
|
onSidebarToggle: () => void;
|
|
275
275
|
sidebarOpen: boolean;
|
|
276
|
+
/** 모델 선택기 표시 여부 */
|
|
277
|
+
showModelSelector?: boolean;
|
|
278
|
+
/** 설정 버튼 표시 여부 */
|
|
279
|
+
showSettings?: boolean;
|
|
276
280
|
}
|
|
277
281
|
interface EmptyStateProps {
|
|
278
282
|
greeting: string;
|
package/dist/react/index.js
CHANGED
|
@@ -1073,7 +1073,9 @@ var ChatHeader = ({
|
|
|
1073
1073
|
onModelChange,
|
|
1074
1074
|
onSettingsOpen,
|
|
1075
1075
|
onSidebarToggle,
|
|
1076
|
-
sidebarOpen
|
|
1076
|
+
sidebarOpen,
|
|
1077
|
+
showModelSelector = true,
|
|
1078
|
+
showSettings = true
|
|
1077
1079
|
}) => {
|
|
1078
1080
|
const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react2.useState)(false);
|
|
1079
1081
|
const currentModel = models.find((m) => m.id === model);
|
|
@@ -1130,7 +1132,7 @@ var ChatHeader = ({
|
|
|
1130
1132
|
)
|
|
1131
1133
|
] }),
|
|
1132
1134
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
1133
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative" }, children: [
|
|
1135
|
+
showModelSelector && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative" }, children: [
|
|
1134
1136
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1135
1137
|
"button",
|
|
1136
1138
|
{
|
|
@@ -1297,7 +1299,7 @@ var ChatHeader = ({
|
|
|
1297
1299
|
)
|
|
1298
1300
|
] })
|
|
1299
1301
|
] }),
|
|
1300
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1302
|
+
showSettings && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1301
1303
|
"button",
|
|
1302
1304
|
{
|
|
1303
1305
|
onClick: onSettingsOpen,
|
|
@@ -2062,53 +2064,99 @@ var CodeBlock = ({ language, code }) => {
|
|
|
2062
2064
|
var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
2063
2065
|
const [isHovered, setIsHovered] = import_react5.default.useState(false);
|
|
2064
2066
|
const [copyState, setCopyState] = import_react5.default.useState("idle");
|
|
2067
|
+
const imgRef = import_react5.default.useRef(null);
|
|
2065
2068
|
const handleCopyImage = async () => {
|
|
2066
2069
|
setCopyState("copying");
|
|
2067
2070
|
try {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2071
|
+
if (!navigator.clipboard || !navigator.clipboard.write) {
|
|
2072
|
+
await navigator.clipboard.writeText(src);
|
|
2073
|
+
setCopyState("copied");
|
|
2074
|
+
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
const img = imgRef.current;
|
|
2078
|
+
if (img && img.complete && img.naturalWidth > 0) {
|
|
2079
|
+
try {
|
|
2080
|
+
const canvas = document.createElement("canvas");
|
|
2081
|
+
canvas.width = img.naturalWidth;
|
|
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...");
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
try {
|
|
2103
|
+
const response = await fetch(src, { mode: "cors" });
|
|
2104
|
+
if (response.ok) {
|
|
2105
|
+
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
|
+
}
|
|
2114
|
+
const tempImg = new Image();
|
|
2115
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
2076
2116
|
await new Promise((resolve, reject) => {
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2117
|
+
tempImg.onload = async () => {
|
|
2118
|
+
try {
|
|
2119
|
+
const canvas = document.createElement("canvas");
|
|
2120
|
+
canvas.width = tempImg.naturalWidth;
|
|
2121
|
+
canvas.height = tempImg.naturalHeight;
|
|
2122
|
+
const ctx = canvas.getContext("2d");
|
|
2123
|
+
if (!ctx) {
|
|
2124
|
+
reject(new Error("Failed to get canvas context"));
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
ctx.drawImage(tempImg, 0, 0);
|
|
2128
|
+
const pngBlob = await new Promise((res) => {
|
|
2129
|
+
canvas.toBlob(res, "image/png");
|
|
2130
|
+
});
|
|
2131
|
+
URL.revokeObjectURL(blobUrl);
|
|
2088
2132
|
if (pngBlob) {
|
|
2089
|
-
|
|
2133
|
+
await navigator.clipboard.write([
|
|
2134
|
+
new ClipboardItem({ "image/png": pngBlob })
|
|
2135
|
+
]);
|
|
2136
|
+
setCopyState("copied");
|
|
2137
|
+
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2090
2138
|
resolve();
|
|
2091
2139
|
} else {
|
|
2092
|
-
reject(new Error("Failed to
|
|
2140
|
+
reject(new Error("Failed to create PNG blob"));
|
|
2093
2141
|
}
|
|
2094
|
-
}
|
|
2142
|
+
} catch (err) {
|
|
2143
|
+
reject(err);
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
tempImg.onerror = () => {
|
|
2147
|
+
URL.revokeObjectURL(blobUrl);
|
|
2148
|
+
reject(new Error("Failed to load image"));
|
|
2095
2149
|
};
|
|
2096
|
-
|
|
2097
|
-
img.src = URL.createObjectURL(blob);
|
|
2150
|
+
tempImg.src = blobUrl;
|
|
2098
2151
|
});
|
|
2152
|
+
return;
|
|
2099
2153
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
[imageBlob.type]: imageBlob
|
|
2103
|
-
})
|
|
2104
|
-
]);
|
|
2105
|
-
setCopyState("copied");
|
|
2106
|
-
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2107
|
-
} else {
|
|
2108
|
-
await navigator.clipboard.writeText(src);
|
|
2109
|
-
setCopyState("copied");
|
|
2110
|
-
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2154
|
+
} catch {
|
|
2155
|
+
console.log("Fetch method failed, using URL fallback");
|
|
2111
2156
|
}
|
|
2157
|
+
await navigator.clipboard.writeText(src);
|
|
2158
|
+
setCopyState("copied");
|
|
2159
|
+
setTimeout(() => setCopyState("idle"), 2e3);
|
|
2112
2160
|
} catch (error) {
|
|
2113
2161
|
console.error("Failed to copy image:", error);
|
|
2114
2162
|
setCopyState("error");
|
|
@@ -2151,9 +2199,11 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
|
2151
2199
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2152
2200
|
"img",
|
|
2153
2201
|
{
|
|
2202
|
+
ref: imgRef,
|
|
2154
2203
|
src,
|
|
2155
2204
|
alt,
|
|
2156
2205
|
className: "chatllm-image",
|
|
2206
|
+
crossOrigin: "anonymous",
|
|
2157
2207
|
style: {
|
|
2158
2208
|
maxWidth: "100%",
|
|
2159
2209
|
borderRadius: "8px",
|
|
@@ -4521,7 +4571,9 @@ var ChatUI = ({
|
|
|
4521
4571
|
onModelChange: setModel,
|
|
4522
4572
|
onSettingsOpen: openSettings,
|
|
4523
4573
|
onSidebarToggle: toggleSidebar,
|
|
4524
|
-
sidebarOpen
|
|
4574
|
+
sidebarOpen,
|
|
4575
|
+
showModelSelector,
|
|
4576
|
+
showSettings
|
|
4525
4577
|
}
|
|
4526
4578
|
),
|
|
4527
4579
|
messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|