@solhun/feedback-kit-web 0.9.0 → 0.10.0
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 +199 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +199 -39
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1214,7 +1214,7 @@ var import_feedback_kit_core4 = require("@solhun/feedback-kit-core");
|
|
|
1214
1214
|
var import_react = require("react");
|
|
1215
1215
|
|
|
1216
1216
|
// src/version.ts
|
|
1217
|
-
var VERSION = true ? "0.
|
|
1217
|
+
var VERSION = true ? "0.10.0" : "dev";
|
|
1218
1218
|
|
|
1219
1219
|
// src/dev-clipboard.ts
|
|
1220
1220
|
var import_feedback_kit_core3 = require("@solhun/feedback-kit-core");
|
|
@@ -1262,6 +1262,37 @@ async function writeToClipboard(text) {
|
|
|
1262
1262
|
}
|
|
1263
1263
|
}
|
|
1264
1264
|
|
|
1265
|
+
// src/dev-preference.ts
|
|
1266
|
+
var STORAGE_KEY = "feedback-kit:dev-mode";
|
|
1267
|
+
function isDevSettingsHost(hostname) {
|
|
1268
|
+
const host = hostname.trim().toLowerCase();
|
|
1269
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]") return true;
|
|
1270
|
+
return host.endsWith(".localhost") || host.endsWith(".local");
|
|
1271
|
+
}
|
|
1272
|
+
function readDevPreference() {
|
|
1273
|
+
try {
|
|
1274
|
+
const raw = globalThis.localStorage?.getItem(STORAGE_KEY);
|
|
1275
|
+
if (raw === "on") return true;
|
|
1276
|
+
if (raw === "off") return false;
|
|
1277
|
+
return null;
|
|
1278
|
+
} catch {
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function writeDevPreference(value) {
|
|
1283
|
+
try {
|
|
1284
|
+
const storage = globalThis.localStorage;
|
|
1285
|
+
if (!storage) return;
|
|
1286
|
+
if (value === null) storage.removeItem(STORAGE_KEY);
|
|
1287
|
+
else storage.setItem(STORAGE_KEY, value ? "on" : "off");
|
|
1288
|
+
} catch {
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
function resolveDevMode(propValue, stored) {
|
|
1292
|
+
if (stored !== null) return stored;
|
|
1293
|
+
return propValue === true;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1265
1296
|
// src/feedback-kit.tsx
|
|
1266
1297
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1267
1298
|
var TOKENS = {
|
|
@@ -1757,7 +1788,11 @@ function FeedbackKit(props) {
|
|
|
1757
1788
|
const [widgetState, setWidgetState] = (0, import_react.useState)(null);
|
|
1758
1789
|
const [pickingState, setPickingState] = (0, import_react.useState)(INITIAL_PICKING_STATE);
|
|
1759
1790
|
const [announcement, setAnnouncement] = (0, import_react.useState)(null);
|
|
1760
|
-
const [devMode] = (0, import_react.useState)(() => props.devMode
|
|
1791
|
+
const [devMode, setDevMode] = (0, import_react.useState)(() => resolveDevMode(props.devMode, readDevPreference()));
|
|
1792
|
+
const [devSettingsAvailable] = (0, import_react.useState)(
|
|
1793
|
+
() => props.devMode === true || isDevSettingsHost(globalThis.location?.hostname ?? "")
|
|
1794
|
+
);
|
|
1795
|
+
const [devSettingsOpen, setDevSettingsOpen] = (0, import_react.useState)(false);
|
|
1761
1796
|
const devClipsRef = (0, import_react.useRef)([]);
|
|
1762
1797
|
const [devClipCount, setDevClipCount] = (0, import_react.useState)(0);
|
|
1763
1798
|
const [devFallbackText, setDevFallbackText] = (0, import_react.useState)(null);
|
|
@@ -1898,6 +1933,13 @@ function FeedbackKit(props) {
|
|
|
1898
1933
|
const ok = await writeToClipboard(text);
|
|
1899
1934
|
setDevFallbackText(ok ? null : text);
|
|
1900
1935
|
}
|
|
1936
|
+
function commitPopup() {
|
|
1937
|
+
if (devMode) {
|
|
1938
|
+
void copyOne();
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
void activeKit.picking.saveAnnotation();
|
|
1942
|
+
}
|
|
1901
1943
|
async function copyOne() {
|
|
1902
1944
|
const clip = currentClip();
|
|
1903
1945
|
if (!clip || clip.comment.trim() === "") return;
|
|
@@ -1910,6 +1952,16 @@ function FeedbackKit(props) {
|
|
|
1910
1952
|
if (devClipsRef.current.length === 0) return;
|
|
1911
1953
|
await putOnClipboard(renderDevClipList(devClipsRef.current));
|
|
1912
1954
|
}
|
|
1955
|
+
function toggleDevMode(next) {
|
|
1956
|
+
writeDevPreference(next);
|
|
1957
|
+
setDevMode(next);
|
|
1958
|
+
devClipsRef.current = [];
|
|
1959
|
+
setDevClipCount(0);
|
|
1960
|
+
setDevFallbackText(null);
|
|
1961
|
+
setAnnouncement(
|
|
1962
|
+
next ? "\uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uB97C \uCF30\uC2B5\uB2C8\uB2E4. \uC774\uC81C \uC81C\uBCF4\uB294 \uC218\uC9D1\uCC98\uB85C \uAC00\uC9C0 \uC54A\uACE0 \uD074\uB9BD\uBCF4\uB4DC\uB85C \uBCF5\uC0AC\uB429\uB2C8\uB2E4." : "\uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uB97C \uAED0\uC2B5\uB2C8\uB2E4. \uC774\uC81C \uC81C\uBCF4\uAC00 \uC218\uC9D1\uCC98\uB85C \uAC11\uB2C8\uB2E4."
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1913
1965
|
async function pressFloatingButton() {
|
|
1914
1966
|
if (props.defaultMode !== "report" && !pickingActive) {
|
|
1915
1967
|
setAnnouncement(null);
|
|
@@ -1967,8 +2019,26 @@ function FeedbackKit(props) {
|
|
|
1967
2019
|
}
|
|
1968
2020
|
function submitReport(event) {
|
|
1969
2021
|
event.preventDefault();
|
|
2022
|
+
if (devMode) {
|
|
2023
|
+
void copyFromModal();
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
1970
2026
|
void activeKit.widget.submitReport();
|
|
1971
2027
|
}
|
|
2028
|
+
async function copyFromModal() {
|
|
2029
|
+
const modalState = activeKit.widget.getState().modal;
|
|
2030
|
+
if (modalState.comment.trim() === "") return;
|
|
2031
|
+
const clip = {
|
|
2032
|
+
comment: modalState.comment,
|
|
2033
|
+
element: modalState.element ?? null,
|
|
2034
|
+
screen: typeof location === "undefined" ? null : location.pathname,
|
|
2035
|
+
priority: modalState.priority
|
|
2036
|
+
};
|
|
2037
|
+
devClipsRef.current = [...devClipsRef.current, clip];
|
|
2038
|
+
setDevClipCount(devClipsRef.current.length);
|
|
2039
|
+
activeKit.widget.confirmCloseReport();
|
|
2040
|
+
await putOnClipboard(renderDevClipItem(clip));
|
|
2041
|
+
}
|
|
1972
2042
|
const floating = screen === "button" || screen === "picking";
|
|
1973
2043
|
const hoverBox = pickingState.hovered?.boundingBox;
|
|
1974
2044
|
const popup = pickingState.popup;
|
|
@@ -1980,27 +2050,64 @@ function FeedbackKit(props) {
|
|
|
1980
2050
|
style: { fontFamily: FONT_STACK, color: TOKENS.ink, fontSize: 14, lineHeight: 1.45 },
|
|
1981
2051
|
children: [
|
|
1982
2052
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `@keyframes feedback-kit-spin{to{transform:rotate(360deg)}}` }),
|
|
1983
|
-
floating ?
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2053
|
+
floating ? (
|
|
2054
|
+
// 톱니와 피드백 버튼을 한 상자에 넣는다. 각각 fixed 로 두면 버튼 글자 길이가
|
|
2055
|
+
// 바뀔 때마다 좌표를 다시 맞춰야 하고, 그러다 겹친다.
|
|
2056
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2057
|
+
"div",
|
|
2058
|
+
{
|
|
2059
|
+
style: {
|
|
2060
|
+
position: "fixed",
|
|
2061
|
+
right: 24,
|
|
2062
|
+
bottom: 24,
|
|
2063
|
+
zIndex: 2147483600,
|
|
2064
|
+
display: "flex",
|
|
2065
|
+
alignItems: "center",
|
|
2066
|
+
gap: 8
|
|
2067
|
+
},
|
|
2068
|
+
children: [
|
|
2069
|
+
devSettingsAvailable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2070
|
+
"button",
|
|
2071
|
+
{
|
|
2072
|
+
type: "button",
|
|
2073
|
+
"data-fk-dev-settings-toggle": "",
|
|
2074
|
+
"aria-label": "\uD53C\uB4DC\uBC31 \uC124\uC815",
|
|
2075
|
+
"aria-expanded": devSettingsOpen,
|
|
2076
|
+
onClick: () => setDevSettingsOpen((open) => !open),
|
|
2077
|
+
style: {
|
|
2078
|
+
...baseButton,
|
|
2079
|
+
width: 46,
|
|
2080
|
+
minHeight: 46,
|
|
2081
|
+
padding: 0,
|
|
2082
|
+
borderRadius: 23,
|
|
2083
|
+
boxShadow: TOKENS.shadow,
|
|
2084
|
+
fontSize: 17,
|
|
2085
|
+
lineHeight: 1
|
|
2086
|
+
},
|
|
2087
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u2699" })
|
|
2088
|
+
}
|
|
2089
|
+
) : null,
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2091
|
+
"button",
|
|
2092
|
+
{
|
|
2093
|
+
ref: floatingButtonRef,
|
|
2094
|
+
id: import_feedback_kit_core4.FLOATING_BUTTON_ID,
|
|
2095
|
+
type: "button",
|
|
2096
|
+
"aria-label": "\uD53C\uB4DC\uBC31 \uBCF4\uB0B4\uAE30",
|
|
2097
|
+
onClick: () => void pressFloatingButton(),
|
|
2098
|
+
style: {
|
|
2099
|
+
...primaryButton,
|
|
2100
|
+
minWidth: 112,
|
|
2101
|
+
minHeight: 46,
|
|
2102
|
+
borderRadius: 24,
|
|
2103
|
+
boxShadow: TOKENS.shadow
|
|
2104
|
+
},
|
|
2105
|
+
children: "\uD53C\uB4DC\uBC31"
|
|
2106
|
+
}
|
|
2107
|
+
)
|
|
2108
|
+
]
|
|
2109
|
+
}
|
|
2110
|
+
)
|
|
2004
2111
|
) : null,
|
|
2005
2112
|
floating && devMode ? (
|
|
2006
2113
|
// 켠 줄 모르고 제보하면 "보냈다"고 믿는데 수집처엔 아무것도 안 남는다.
|
|
@@ -2062,23 +2169,80 @@ function FeedbackKit(props) {
|
|
|
2062
2169
|
]
|
|
2063
2170
|
}
|
|
2064
2171
|
) : null,
|
|
2065
|
-
announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.
|
|
2172
|
+
devSettingsOpen || announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2066
2173
|
"div",
|
|
2067
2174
|
{
|
|
2068
|
-
role: "status",
|
|
2069
|
-
"aria-live": "polite",
|
|
2070
2175
|
style: {
|
|
2071
2176
|
position: "fixed",
|
|
2072
2177
|
right: 24,
|
|
2073
2178
|
bottom: 82,
|
|
2074
2179
|
zIndex: 2147483601,
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
boxShadow: TOKENS.shadow
|
|
2180
|
+
display: "flex",
|
|
2181
|
+
flexDirection: "column",
|
|
2182
|
+
alignItems: "flex-end",
|
|
2183
|
+
gap: 8
|
|
2080
2184
|
},
|
|
2081
|
-
children:
|
|
2185
|
+
children: [
|
|
2186
|
+
devSettingsOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2187
|
+
"div",
|
|
2188
|
+
{
|
|
2189
|
+
role: "dialog",
|
|
2190
|
+
"aria-label": "\uD53C\uB4DC\uBC31 \uC124\uC815",
|
|
2191
|
+
"data-fk-dev-settings": "",
|
|
2192
|
+
style: {
|
|
2193
|
+
width: 292,
|
|
2194
|
+
maxWidth: "calc(100vw - 48px)",
|
|
2195
|
+
padding: 14,
|
|
2196
|
+
borderRadius: 12,
|
|
2197
|
+
border: `1px solid ${TOKENS.line}`,
|
|
2198
|
+
background: TOKENS.surface,
|
|
2199
|
+
boxShadow: TOKENS.shadow
|
|
2200
|
+
},
|
|
2201
|
+
children: [
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", alignItems: "flex-start", gap: 9, cursor: "pointer" }, children: [
|
|
2203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2204
|
+
"input",
|
|
2205
|
+
{
|
|
2206
|
+
type: "checkbox",
|
|
2207
|
+
checked: devMode,
|
|
2208
|
+
onChange: (event) => toggleDevMode(event.currentTarget.checked),
|
|
2209
|
+
style: { marginTop: 3 }
|
|
2210
|
+
}
|
|
2211
|
+
),
|
|
2212
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontWeight: 700 }, children: "\uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC" }),
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "block", marginTop: 4, color: TOKENS.muted, fontSize: 12.5 }, children: [
|
|
2215
|
+
"\uCF1C\uBA74 \uC81C\uBCF4\uB97C \uC218\uC9D1\uCC98\uB85C \uBCF4\uB0B4\uC9C0 \uC54A\uACE0 ",
|
|
2216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: "\uD074\uB9BD\uBCF4\uB4DC\uB85C \uBCF5\uC0AC" }),
|
|
2217
|
+
"\uD569\uB2C8\uB2E4. \uBD99\uC5EC\uB123\uC73C\uBA74 \uD654\uBA74\xB7\uC694\uC18C\xB7 \uCEF4\uD3EC\uB10C\uD2B8\xB7\uC18C\uC2A4 \uACBD\uB85C\uAC00 \uAC19\uC774 \uB098\uC635\uB2C8\uB2E4."
|
|
2218
|
+
] })
|
|
2219
|
+
] })
|
|
2220
|
+
] }),
|
|
2221
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { margin: "12px 0 0", color: TOKENS.muted, fontSize: 12 }, children: [
|
|
2222
|
+
"\uC774 \uC124\uC815\uC740 \uB85C\uCEEC(",
|
|
2223
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: "localhost" }),
|
|
2224
|
+
")\uC5D0\uC11C\uB9CC \uBCF4\uC785\uB2C8\uB2E4. \uBC30\uD3EC\uB41C \uD654\uBA74\uC5D0\uC11C\uB294 \uC2E4\uC0AC\uC6A9\uC790\uAC00 \uCF24 \uC218 \uC5C6\uC5B4\uC57C \uD574\uC11C \uC544\uC608 \uB744\uC6B0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
|
|
2225
|
+
] }),
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: baseButton, onClick: () => setDevSettingsOpen(false), children: "\uB2EB\uAE30" }) })
|
|
2227
|
+
]
|
|
2228
|
+
}
|
|
2229
|
+
) : null,
|
|
2230
|
+
announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2231
|
+
"div",
|
|
2232
|
+
{
|
|
2233
|
+
role: "status",
|
|
2234
|
+
"aria-live": "polite",
|
|
2235
|
+
style: {
|
|
2236
|
+
padding: "10px 14px",
|
|
2237
|
+
borderRadius: 10,
|
|
2238
|
+
background: TOKENS.ink,
|
|
2239
|
+
color: TOKENS.surface,
|
|
2240
|
+
boxShadow: TOKENS.shadow
|
|
2241
|
+
},
|
|
2242
|
+
children: announcement
|
|
2243
|
+
}
|
|
2244
|
+
) : null
|
|
2245
|
+
]
|
|
2082
2246
|
}
|
|
2083
2247
|
) : null,
|
|
2084
2248
|
screen === "modal" && modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -2337,7 +2501,7 @@ function FeedbackKit(props) {
|
|
|
2337
2501
|
opacity: modal.canSubmit ? 1 : 0.5,
|
|
2338
2502
|
cursor: modal.canSubmit ? "pointer" : "not-allowed"
|
|
2339
2503
|
},
|
|
2340
|
-
children: modal.submitStatus === "sending" ? "\uC804\uC1A1 \uC911\u2026" : "\uBCF4\uB0B4\uAE30"
|
|
2504
|
+
children: modal.submitStatus === "sending" ? "\uC804\uC1A1 \uC911\u2026" : devMode ? "\uBCF5\uC0AC" : "\uBCF4\uB0B4\uAE30"
|
|
2341
2505
|
}
|
|
2342
2506
|
)
|
|
2343
2507
|
] })
|
|
@@ -2456,11 +2620,7 @@ function FeedbackKit(props) {
|
|
|
2456
2620
|
"aria-label": "\uC694\uC18C \uC8FC\uC11D",
|
|
2457
2621
|
onSubmit: (event) => {
|
|
2458
2622
|
event.preventDefault();
|
|
2459
|
-
|
|
2460
|
-
void copyOne();
|
|
2461
|
-
return;
|
|
2462
|
-
}
|
|
2463
|
-
void kit.picking.saveAnnotation();
|
|
2623
|
+
commitPopup();
|
|
2464
2624
|
},
|
|
2465
2625
|
onPaste: (event) => {
|
|
2466
2626
|
if (!firstImageOf(event.clipboardData)) return;
|
|
@@ -2542,7 +2702,7 @@ function FeedbackKit(props) {
|
|
|
2542
2702
|
const native = event.nativeEvent;
|
|
2543
2703
|
if (native.isComposing) return;
|
|
2544
2704
|
event.preventDefault();
|
|
2545
|
-
|
|
2705
|
+
commitPopup();
|
|
2546
2706
|
},
|
|
2547
2707
|
rows: 2,
|
|
2548
2708
|
placeholder: "\uBB34\uC5C7\uC774 \uBB38\uC81C\uC778\uAC00\uC694? (Enter \uB85C \uBCF4\uB0B4\uAE30)",
|