@solhun/feedback-kit-web 0.6.0 → 0.6.1
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/index.cjs +57 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +57 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -973,7 +973,7 @@ import {
|
|
|
973
973
|
} from "react";
|
|
974
974
|
|
|
975
975
|
// src/version.ts
|
|
976
|
-
var VERSION = true ? "0.6.
|
|
976
|
+
var VERSION = true ? "0.6.1" : "dev";
|
|
977
977
|
|
|
978
978
|
// src/feedback-kit.tsx
|
|
979
979
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1036,26 +1036,41 @@ async function transcodeToJpeg(dataUrl) {
|
|
|
1036
1036
|
return null;
|
|
1037
1037
|
}
|
|
1038
1038
|
}
|
|
1039
|
+
function looksLikeImageName(name) {
|
|
1040
|
+
return /\.(png|jpe?g|gif|webp|bmp|avif|heic|heif)$/i.test(name);
|
|
1041
|
+
}
|
|
1042
|
+
function isImageFile(file) {
|
|
1043
|
+
if (file.type.startsWith("image/")) return true;
|
|
1044
|
+
return (file.type === "" || file.type === "application/octet-stream") && looksLikeImageName(file.name);
|
|
1045
|
+
}
|
|
1046
|
+
function contentTypeOf(file) {
|
|
1047
|
+
if (file.type !== "") return file.type;
|
|
1048
|
+
const name = file instanceof File ? file.name : "";
|
|
1049
|
+
if (/\.png$/i.test(name)) return "image/png";
|
|
1050
|
+
if (/\.jpe?g$/i.test(name)) return "image/jpeg";
|
|
1051
|
+
return "";
|
|
1052
|
+
}
|
|
1039
1053
|
async function readImageFile(file) {
|
|
1040
|
-
|
|
1054
|
+
const named = file instanceof File ? file : null;
|
|
1055
|
+
if (!file.type.startsWith("image/") && !(named !== null && isImageFile(named))) return null;
|
|
1041
1056
|
const dataUrl = await readDataUrl(file);
|
|
1042
1057
|
if (!dataUrl) return null;
|
|
1043
|
-
|
|
1058
|
+
const type = contentTypeOf(file);
|
|
1059
|
+
if (type === "image/png" || type === "image/jpeg") {
|
|
1044
1060
|
const base64 = base64Of(dataUrl);
|
|
1045
|
-
return base64 ? { base64, contentType:
|
|
1061
|
+
return base64 ? { base64, contentType: type } : null;
|
|
1046
1062
|
}
|
|
1047
1063
|
return transcodeToJpeg(dataUrl);
|
|
1048
1064
|
}
|
|
1049
1065
|
function firstImageOf(transfer) {
|
|
1050
1066
|
if (!transfer) return null;
|
|
1051
1067
|
for (const item of Array.from(transfer.items ?? [])) {
|
|
1052
|
-
if (item.kind
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
}
|
|
1068
|
+
if (item.kind !== "file") continue;
|
|
1069
|
+
const file = item.getAsFile();
|
|
1070
|
+
if (file && isImageFile(file)) return file;
|
|
1056
1071
|
}
|
|
1057
1072
|
for (const file of Array.from(transfer.files ?? [])) {
|
|
1058
|
-
if (file
|
|
1073
|
+
if (isImageFile(file)) return file;
|
|
1059
1074
|
}
|
|
1060
1075
|
return null;
|
|
1061
1076
|
}
|
|
@@ -1397,6 +1412,23 @@ function FeedbackKit(props) {
|
|
|
1397
1412
|
document.addEventListener("keydown", onKeyDownCapture, true);
|
|
1398
1413
|
return () => document.removeEventListener("keydown", onKeyDownCapture, true);
|
|
1399
1414
|
}, [kit, widgetState, pickingState.popup]);
|
|
1415
|
+
useEffect(() => {
|
|
1416
|
+
if (!kit || !widgetState?.modal.open) return;
|
|
1417
|
+
if (pickingState.popup) return;
|
|
1418
|
+
const locked = widgetState.modal.submitStatus === "sending" || widgetState.modal.submitStatus === "pending";
|
|
1419
|
+
if (locked) return;
|
|
1420
|
+
const controller = kit;
|
|
1421
|
+
async function onPaste(event) {
|
|
1422
|
+
const file = firstImageOf(event.clipboardData);
|
|
1423
|
+
if (!file) return;
|
|
1424
|
+
event.preventDefault();
|
|
1425
|
+
const shot = await readImageFile(file);
|
|
1426
|
+
if (shot) await controller.widget.modal.attachFile(shot);
|
|
1427
|
+
}
|
|
1428
|
+
const handler = (event) => void onPaste(event);
|
|
1429
|
+
document.addEventListener("paste", handler);
|
|
1430
|
+
return () => document.removeEventListener("paste", handler);
|
|
1431
|
+
}, [kit, widgetState, pickingState.popup]);
|
|
1400
1432
|
if (!kit || !widgetState) {
|
|
1401
1433
|
return /* @__PURE__ */ jsx("div", { ...OWN_UI_PROPS, "data-feedback-kit-loading": "true" });
|
|
1402
1434
|
}
|
|
@@ -1434,6 +1466,14 @@ function FeedbackKit(props) {
|
|
|
1434
1466
|
}
|
|
1435
1467
|
input.value = "";
|
|
1436
1468
|
}
|
|
1469
|
+
async function attachToModal(transfer) {
|
|
1470
|
+
const file = firstImageOf(transfer);
|
|
1471
|
+
if (!file) return false;
|
|
1472
|
+
const screenshot = await readImageFile(file);
|
|
1473
|
+
if (!screenshot) return false;
|
|
1474
|
+
await activeKit.widget.modal.attachFile(screenshot);
|
|
1475
|
+
return true;
|
|
1476
|
+
}
|
|
1437
1477
|
async function attachToPopup(transfer) {
|
|
1438
1478
|
const file = firstImageOf(transfer);
|
|
1439
1479
|
if (!file) return false;
|
|
@@ -1534,6 +1574,14 @@ function FeedbackKit(props) {
|
|
|
1534
1574
|
"aria-modal": "true",
|
|
1535
1575
|
"aria-labelledby": "feedback-kit-dialog-title",
|
|
1536
1576
|
onKeyDown: handleModalKeyDown,
|
|
1577
|
+
onDragOver: (event) => {
|
|
1578
|
+
if (!draftLocked && firstImageOf(event.dataTransfer)) event.preventDefault();
|
|
1579
|
+
},
|
|
1580
|
+
onDrop: (event) => {
|
|
1581
|
+
if (draftLocked || !firstImageOf(event.dataTransfer)) return;
|
|
1582
|
+
event.preventDefault();
|
|
1583
|
+
void attachToModal(event.dataTransfer);
|
|
1584
|
+
},
|
|
1537
1585
|
style: {
|
|
1538
1586
|
width: "min(520px, 100%)",
|
|
1539
1587
|
maxHeight: "min(760px, calc(100vh - 40px))",
|