@solhun/feedback-kit-web 0.8.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 +418 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +388 -33
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -30,45 +30,45 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
COMMENT_MAX_CHARS: () =>
|
|
34
|
-
COMMENT_REQUIRED_MESSAGE: () =>
|
|
35
|
-
COMMENT_TOO_LONG_MESSAGE: () =>
|
|
33
|
+
COMMENT_MAX_CHARS: () => import_feedback_kit_core7.COMMENT_MAX_CHARS,
|
|
34
|
+
COMMENT_REQUIRED_MESSAGE: () => import_feedback_kit_core7.COMMENT_REQUIRED_MESSAGE,
|
|
35
|
+
COMMENT_TOO_LONG_MESSAGE: () => import_feedback_kit_core7.COMMENT_TOO_LONG_MESSAGE,
|
|
36
36
|
ELEMENT_TEXT_MAX_CHARS: () => ELEMENT_TEXT_MAX_CHARS,
|
|
37
37
|
ElementPickingController: () => ElementPickingController,
|
|
38
|
-
FLOATING_BUTTON_ID: () =>
|
|
38
|
+
FLOATING_BUTTON_ID: () => import_feedback_kit_core7.FLOATING_BUTTON_ID,
|
|
39
39
|
FeedbackKit: () => FeedbackKit,
|
|
40
|
-
HintProvider: () =>
|
|
40
|
+
HintProvider: () => import_feedback_kit_core8.HintProvider,
|
|
41
41
|
MARKER_KEY_PREFIX: () => MARKER_KEY_PREFIX,
|
|
42
42
|
MAX_MARKERS_PER_PATH: () => MAX_MARKERS_PER_PATH,
|
|
43
|
-
MODAL_ACTION_HINT_TOGGLE: () =>
|
|
44
|
-
MODAL_ACTION_PICK: () =>
|
|
43
|
+
MODAL_ACTION_HINT_TOGGLE: () => import_feedback_kit_core7.MODAL_ACTION_HINT_TOGGLE,
|
|
44
|
+
MODAL_ACTION_PICK: () => import_feedback_kit_core7.MODAL_ACTION_PICK,
|
|
45
45
|
MarkerStore: () => MarkerStore,
|
|
46
46
|
OWN_UI_ATTR: () => OWN_UI_ATTR,
|
|
47
47
|
PICKING_MODE_KEY: () => PICKING_MODE_KEY,
|
|
48
|
-
ReportModalController: () =>
|
|
49
|
-
SCREENSHOT_FAILED_MESSAGE: () =>
|
|
48
|
+
ReportModalController: () => import_feedback_kit_core7.ReportModalController,
|
|
49
|
+
SCREENSHOT_FAILED_MESSAGE: () => import_feedback_kit_core7.SCREENSHOT_FAILED_MESSAGE,
|
|
50
50
|
SELECTOR_MAX_DEPTH: () => SELECTOR_MAX_DEPTH,
|
|
51
|
-
SOURCE_ATTR: () =>
|
|
52
|
-
SUBMIT_DONE_MESSAGE: () =>
|
|
53
|
-
SUBMIT_PENDING_MESSAGE: () =>
|
|
54
|
-
WidgetController: () =>
|
|
51
|
+
SOURCE_ATTR: () => import_feedback_kit_core6.SOURCE_ATTR,
|
|
52
|
+
SUBMIT_DONE_MESSAGE: () => import_feedback_kit_core7.SUBMIT_DONE_MESSAGE,
|
|
53
|
+
SUBMIT_PENDING_MESSAGE: () => import_feedback_kit_core7.SUBMIT_PENDING_MESSAGE,
|
|
54
|
+
WidgetController: () => import_feedback_kit_core7.WidgetController,
|
|
55
55
|
captureWebScreenshot: () => captureWebScreenshot,
|
|
56
56
|
createRouteWatcher: () => createRouteWatcher,
|
|
57
57
|
createWebStorage: () => createWebStorage,
|
|
58
58
|
createWebWidget: () => createWebWidget,
|
|
59
59
|
cssSelectorPath: () => cssSelectorPath,
|
|
60
|
-
denormalizePin: () =>
|
|
60
|
+
denormalizePin: () => import_feedback_kit_core7.denormalizePin,
|
|
61
61
|
describeElement: () => describeElement,
|
|
62
62
|
isOwnUi: () => isOwnUi2,
|
|
63
|
-
normalizePin: () =>
|
|
64
|
-
parseSourceAttr: () =>
|
|
65
|
-
rankHints: () =>
|
|
63
|
+
normalizePin: () => import_feedback_kit_core7.normalizePin,
|
|
64
|
+
parseSourceAttr: () => import_feedback_kit_core6.parseSourceAttr,
|
|
65
|
+
rankHints: () => import_feedback_kit_core8.rankHints,
|
|
66
66
|
reactComponentPath: () => reactComponentPath,
|
|
67
67
|
reactComponentSummary: () => reactComponentSummary,
|
|
68
68
|
reencodeWebScreenshot: () => reencodeWebScreenshot,
|
|
69
|
-
resolveConfig: () =>
|
|
70
|
-
shouldShowWidget: () =>
|
|
71
|
-
sourceFromElement: () =>
|
|
69
|
+
resolveConfig: () => import_feedback_kit_core5.resolveConfig,
|
|
70
|
+
shouldShowWidget: () => import_feedback_kit_core5.shouldShowWidget,
|
|
71
|
+
sourceFromElement: () => import_feedback_kit_core6.sourceFromElement,
|
|
72
72
|
visibleText: () => visibleText,
|
|
73
73
|
webContextProviders: () => webContextProviders,
|
|
74
74
|
webDiagnosticsOptions: () => webDiagnosticsOptions,
|
|
@@ -76,10 +76,10 @@ __export(index_exports, {
|
|
|
76
76
|
webRouteWatcher: () => webRouteWatcher
|
|
77
77
|
});
|
|
78
78
|
module.exports = __toCommonJS(index_exports);
|
|
79
|
-
var import_feedback_kit_core4 = require("@solhun/feedback-kit-core");
|
|
80
79
|
var import_feedback_kit_core5 = require("@solhun/feedback-kit-core");
|
|
81
80
|
var import_feedback_kit_core6 = require("@solhun/feedback-kit-core");
|
|
82
81
|
var import_feedback_kit_core7 = require("@solhun/feedback-kit-core");
|
|
82
|
+
var import_feedback_kit_core8 = require("@solhun/feedback-kit-core");
|
|
83
83
|
|
|
84
84
|
// src/react-tree.ts
|
|
85
85
|
var FRAMEWORK_INTERNALS = /* @__PURE__ */ new Set([
|
|
@@ -1210,11 +1210,88 @@ function createWebWidget(opts) {
|
|
|
1210
1210
|
}
|
|
1211
1211
|
|
|
1212
1212
|
// src/feedback-kit.tsx
|
|
1213
|
-
var
|
|
1213
|
+
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
|
+
|
|
1219
|
+
// src/dev-clipboard.ts
|
|
1220
|
+
var import_feedback_kit_core3 = require("@solhun/feedback-kit-core");
|
|
1221
|
+
function sourceLine(item) {
|
|
1222
|
+
const mapping = (0, import_feedback_kit_core3.sourceFromElement)(item.element ?? void 0);
|
|
1223
|
+
if (!mapping.sourceFile) return null;
|
|
1224
|
+
return mapping.sourceLine === null ? `\uC18C\uC2A4: ${mapping.sourceFile}` : `\uC18C\uC2A4: ${mapping.sourceFile}:${mapping.sourceLine}`;
|
|
1225
|
+
}
|
|
1226
|
+
function elementLine(element) {
|
|
1227
|
+
if (!element) return null;
|
|
1228
|
+
const selector = element.selector ?? element.tag;
|
|
1229
|
+
const text = element.text?.trim();
|
|
1230
|
+
return text ? `\uC694\uC18C: ${selector} "${text}"` : `\uC694\uC18C: ${selector}`;
|
|
1231
|
+
}
|
|
1232
|
+
function componentLine(element) {
|
|
1233
|
+
const summary = element?.attributes?.["react-components"];
|
|
1234
|
+
return summary ? `\uCEF4\uD3EC\uB10C\uD2B8: ${summary}` : null;
|
|
1235
|
+
}
|
|
1236
|
+
function renderDevClipItem(item) {
|
|
1237
|
+
const lines = [`[\uD53C\uB4DC\uBC31] ${item.comment.trim()}`];
|
|
1238
|
+
const screen = item.screen?.trim();
|
|
1239
|
+
if (screen) lines.push(`\uD654\uBA74: ${screen}`);
|
|
1240
|
+
const element = elementLine(item.element);
|
|
1241
|
+
if (element) lines.push(element);
|
|
1242
|
+
const component = componentLine(item.element);
|
|
1243
|
+
if (component) lines.push(component);
|
|
1244
|
+
const source = sourceLine(item);
|
|
1245
|
+
if (source) lines.push(source);
|
|
1246
|
+
if (item.priority && item.priority !== "unset") lines.push(`\uC6B0\uC120\uC21C\uC704: ${item.priority}`);
|
|
1247
|
+
return lines.join("\n");
|
|
1248
|
+
}
|
|
1249
|
+
function renderDevClipList(items) {
|
|
1250
|
+
if (items.length === 0) return "";
|
|
1251
|
+
if (items.length === 1) return renderDevClipItem(items[0]);
|
|
1252
|
+
return items.map((item, index) => `${index + 1}. ${renderDevClipItem(item).split("\n").join("\n ")}`).join("\n\n");
|
|
1253
|
+
}
|
|
1254
|
+
async function writeToClipboard(text) {
|
|
1255
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
1256
|
+
if (!clipboard?.writeText) return false;
|
|
1257
|
+
try {
|
|
1258
|
+
await clipboard.writeText(text);
|
|
1259
|
+
return true;
|
|
1260
|
+
} catch {
|
|
1261
|
+
return false;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
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
|
+
}
|
|
1218
1295
|
|
|
1219
1296
|
// src/feedback-kit.tsx
|
|
1220
1297
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1483,7 +1560,10 @@ function PickBar({
|
|
|
1483
1560
|
markerCount,
|
|
1484
1561
|
onToggle,
|
|
1485
1562
|
onTogglePause,
|
|
1486
|
-
onClearMarkers
|
|
1563
|
+
onClearMarkers,
|
|
1564
|
+
onReportWholeScreen,
|
|
1565
|
+
devClipCount,
|
|
1566
|
+
onCopyAll
|
|
1487
1567
|
}) {
|
|
1488
1568
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1489
1569
|
"div",
|
|
@@ -1538,6 +1618,48 @@ function PickBar({
|
|
|
1538
1618
|
]
|
|
1539
1619
|
}
|
|
1540
1620
|
),
|
|
1621
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1622
|
+
"button",
|
|
1623
|
+
{
|
|
1624
|
+
type: "button",
|
|
1625
|
+
"data-fk-pick-whole": "",
|
|
1626
|
+
title: "\uAC00\uB9AC\uD0A8 \uC694\uC18C \uC5C6\uC774 \uC774 \uD654\uBA74 \uC804\uCCB4\uC5D0 \uB300\uD574 \uC81C\uBCF4\uD569\uB2C8\uB2E4.",
|
|
1627
|
+
onClick: onReportWholeScreen,
|
|
1628
|
+
style: {
|
|
1629
|
+
...baseButton,
|
|
1630
|
+
display: "inline-flex",
|
|
1631
|
+
alignItems: "center",
|
|
1632
|
+
gap: 6,
|
|
1633
|
+
whiteSpace: "nowrap"
|
|
1634
|
+
},
|
|
1635
|
+
children: [
|
|
1636
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u25A3" }),
|
|
1637
|
+
"\uD654\uBA74 \uC804\uCCB4\uB85C \uBCF4\uB0B4\uAE30"
|
|
1638
|
+
]
|
|
1639
|
+
}
|
|
1640
|
+
),
|
|
1641
|
+
devClipCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1642
|
+
"button",
|
|
1643
|
+
{
|
|
1644
|
+
type: "button",
|
|
1645
|
+
"data-fk-copy-all": devClipCount,
|
|
1646
|
+
title: "\uC774\uBC88 \uC138\uC158\uC5D0 \uCC0D\uC740 \uAC83\uC744 \uBC88\uD638 \uB9E4\uAE34 \uBAA9\uB85D \uD558\uB098\uB85C \uBCF5\uC0AC\uD569\uB2C8\uB2E4.",
|
|
1647
|
+
onClick: onCopyAll,
|
|
1648
|
+
style: {
|
|
1649
|
+
...baseButton,
|
|
1650
|
+
display: "inline-flex",
|
|
1651
|
+
alignItems: "center",
|
|
1652
|
+
gap: 6,
|
|
1653
|
+
whiteSpace: "nowrap",
|
|
1654
|
+
fontWeight: 600
|
|
1655
|
+
},
|
|
1656
|
+
children: [
|
|
1657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u29C9" }),
|
|
1658
|
+
"\uC804\uBD80 \uBCF5\uC0AC ",
|
|
1659
|
+
devClipCount
|
|
1660
|
+
]
|
|
1661
|
+
}
|
|
1662
|
+
) : null,
|
|
1541
1663
|
markerCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1542
1664
|
"button",
|
|
1543
1665
|
{
|
|
@@ -1592,7 +1714,7 @@ function HintChips({
|
|
|
1592
1714
|
"button",
|
|
1593
1715
|
{
|
|
1594
1716
|
type: "button",
|
|
1595
|
-
"data-fk-focus-id":
|
|
1717
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_HINT_TOGGLE,
|
|
1596
1718
|
"aria-expanded": hintsExpanded,
|
|
1597
1719
|
disabled,
|
|
1598
1720
|
onClick: onToggle,
|
|
@@ -1666,6 +1788,14 @@ function FeedbackKit(props) {
|
|
|
1666
1788
|
const [widgetState, setWidgetState] = (0, import_react.useState)(null);
|
|
1667
1789
|
const [pickingState, setPickingState] = (0, import_react.useState)(INITIAL_PICKING_STATE);
|
|
1668
1790
|
const [announcement, setAnnouncement] = (0, import_react.useState)(null);
|
|
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);
|
|
1796
|
+
const devClipsRef = (0, import_react.useRef)([]);
|
|
1797
|
+
const [devClipCount, setDevClipCount] = (0, import_react.useState)(0);
|
|
1798
|
+
const [devFallbackText, setDevFallbackText] = (0, import_react.useState)(null);
|
|
1669
1799
|
const {
|
|
1670
1800
|
queue,
|
|
1671
1801
|
createReport,
|
|
@@ -1726,7 +1856,7 @@ function FeedbackKit(props) {
|
|
|
1726
1856
|
}
|
|
1727
1857
|
if (modal2.closeConfirmVisible && !previousConfirmVisibleRef.current) confirmRef.current?.focus();
|
|
1728
1858
|
const wasModal = previousScreenRef.current === "modal";
|
|
1729
|
-
if (wasModal && screen2 === "button" && modal2.restoreFocusTo ===
|
|
1859
|
+
if (wasModal && screen2 === "button" && modal2.restoreFocusTo === import_feedback_kit_core4.FLOATING_BUTTON_ID) {
|
|
1730
1860
|
void nextPaint().then(() => floatingButtonRef.current?.focus());
|
|
1731
1861
|
}
|
|
1732
1862
|
previousScreenRef.current = screen2;
|
|
@@ -1790,6 +1920,56 @@ function FeedbackKit(props) {
|
|
|
1790
1920
|
if (root) root.style.visibility = previousVisibility;
|
|
1791
1921
|
}
|
|
1792
1922
|
}
|
|
1923
|
+
function currentClip() {
|
|
1924
|
+
const state = pickingState.popup;
|
|
1925
|
+
if (!state) return null;
|
|
1926
|
+
return {
|
|
1927
|
+
comment: state.comment,
|
|
1928
|
+
element: state.element ?? null,
|
|
1929
|
+
screen: typeof location === "undefined" ? null : location.pathname
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
async function putOnClipboard(text) {
|
|
1933
|
+
const ok = await writeToClipboard(text);
|
|
1934
|
+
setDevFallbackText(ok ? null : text);
|
|
1935
|
+
}
|
|
1936
|
+
function commitPopup() {
|
|
1937
|
+
if (devMode) {
|
|
1938
|
+
void copyOne();
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
void activeKit.picking.saveAnnotation();
|
|
1942
|
+
}
|
|
1943
|
+
async function copyOne() {
|
|
1944
|
+
const clip = currentClip();
|
|
1945
|
+
if (!clip || clip.comment.trim() === "") return;
|
|
1946
|
+
devClipsRef.current = [...devClipsRef.current, clip];
|
|
1947
|
+
setDevClipCount(devClipsRef.current.length);
|
|
1948
|
+
activeKit.picking.cancelAnnotation();
|
|
1949
|
+
await putOnClipboard(renderDevClipItem(clip));
|
|
1950
|
+
}
|
|
1951
|
+
async function copyAll() {
|
|
1952
|
+
if (devClipsRef.current.length === 0) return;
|
|
1953
|
+
await putOnClipboard(renderDevClipList(devClipsRef.current));
|
|
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
|
+
}
|
|
1965
|
+
async function pressFloatingButton() {
|
|
1966
|
+
if (props.defaultMode !== "report" && !pickingActive) {
|
|
1967
|
+
setAnnouncement(null);
|
|
1968
|
+
activeKit.widget.startPicking();
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
await openReport();
|
|
1972
|
+
}
|
|
1793
1973
|
async function openReport() {
|
|
1794
1974
|
setAnnouncement(null);
|
|
1795
1975
|
await withOwnUiHidden(() => activeKit.widget.openReport());
|
|
@@ -1839,8 +2019,26 @@ function FeedbackKit(props) {
|
|
|
1839
2019
|
}
|
|
1840
2020
|
function submitReport(event) {
|
|
1841
2021
|
event.preventDefault();
|
|
2022
|
+
if (devMode) {
|
|
2023
|
+
void copyFromModal();
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
1842
2026
|
void activeKit.widget.submitReport();
|
|
1843
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
|
+
}
|
|
1844
2042
|
const floating = screen === "button" || screen === "picking";
|
|
1845
2043
|
const hoverBox = pickingState.hovered?.boundingBox;
|
|
1846
2044
|
const popup = pickingState.popup;
|
|
@@ -1852,45 +2050,199 @@ function FeedbackKit(props) {
|
|
|
1852
2050
|
style: { fontFamily: FONT_STACK, color: TOKENS.ink, fontSize: 14, lineHeight: 1.45 },
|
|
1853
2051
|
children: [
|
|
1854
2052
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `@keyframes feedback-kit-spin{to{transform:rotate(360deg)}}` }),
|
|
1855
|
-
floating ?
|
|
1856
|
-
|
|
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
|
+
)
|
|
2111
|
+
) : null,
|
|
2112
|
+
floating && devMode ? (
|
|
2113
|
+
// 켠 줄 모르고 제보하면 "보냈다"고 믿는데 수집처엔 아무것도 안 남는다.
|
|
2114
|
+
// 조용한 유실이라 이 표시가 유일한 방어다. 버튼 **밖**에 두는 이유는 버튼의
|
|
2115
|
+
// 접근성 이름을 오염시키지 않기 위해서다.
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2117
|
+
"span",
|
|
2118
|
+
{
|
|
2119
|
+
"data-fk-dev-badge": "",
|
|
2120
|
+
"aria-label": "\uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uAC00 \uCF1C\uC838 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uC81C\uBCF4\uAC00 \uC218\uC9D1\uCC98\uB85C \uAC00\uC9C0 \uC54A\uACE0 \uD074\uB9BD\uBCF4\uB4DC\uB85C \uBCF5\uC0AC\uB429\uB2C8\uB2E4",
|
|
2121
|
+
style: {
|
|
2122
|
+
position: "fixed",
|
|
2123
|
+
right: 24,
|
|
2124
|
+
bottom: 62,
|
|
2125
|
+
zIndex: 2147483601,
|
|
2126
|
+
padding: "2px 8px",
|
|
2127
|
+
borderRadius: 6,
|
|
2128
|
+
background: TOKENS.warning,
|
|
2129
|
+
color: "#1f2933",
|
|
2130
|
+
fontSize: 11,
|
|
2131
|
+
fontWeight: 700,
|
|
2132
|
+
pointerEvents: "none"
|
|
2133
|
+
},
|
|
2134
|
+
children: "\uAC1C\uBC1C\uC6A9 \u2014 \uD074\uB9BD\uBCF4\uB4DC\uB85C \uBCF5\uC0AC"
|
|
2135
|
+
}
|
|
2136
|
+
)
|
|
2137
|
+
) : null,
|
|
2138
|
+
devFallbackText !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2139
|
+
"div",
|
|
1857
2140
|
{
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
"aria-label": "\uD53C\uB4DC\uBC31 \uBCF4\uB0B4\uAE30",
|
|
1862
|
-
onClick: () => void openReport(),
|
|
2141
|
+
role: "dialog",
|
|
2142
|
+
"aria-label": "\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBABB \uC368\uC11C \uB300\uC2E0 \uBCF4\uC5EC\uC90D\uB2C8\uB2E4",
|
|
2143
|
+
"data-fk-dev-fallback": "",
|
|
1863
2144
|
style: {
|
|
1864
|
-
...primaryButton,
|
|
1865
2145
|
position: "fixed",
|
|
1866
2146
|
right: 24,
|
|
1867
|
-
bottom:
|
|
1868
|
-
zIndex:
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
borderRadius:
|
|
1872
|
-
|
|
2147
|
+
bottom: 92,
|
|
2148
|
+
zIndex: 2147483602,
|
|
2149
|
+
width: "min(420px, calc(100vw - 48px))",
|
|
2150
|
+
border: `1px solid ${TOKENS.line}`,
|
|
2151
|
+
borderRadius: 12,
|
|
2152
|
+
background: TOKENS.surface,
|
|
2153
|
+
padding: 12,
|
|
2154
|
+
boxShadow: TOKENS.shadow,
|
|
2155
|
+
pointerEvents: "auto"
|
|
1873
2156
|
},
|
|
1874
|
-
children:
|
|
2157
|
+
children: [
|
|
2158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: 6, color: TOKENS.muted, fontSize: 12 }, children: "\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC544\uB798\uC5D0\uC11C \uC9C1\uC811 \uBCF5\uC0AC\uD558\uC138\uC694." }),
|
|
2159
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2160
|
+
"textarea",
|
|
2161
|
+
{
|
|
2162
|
+
readOnly: true,
|
|
2163
|
+
value: devFallbackText,
|
|
2164
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
2165
|
+
style: { ...inputStyle, height: 140, fontFamily: "ui-monospace, monospace", fontSize: 12 }
|
|
2166
|
+
}
|
|
2167
|
+
),
|
|
2168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => setDevFallbackText(null), style: baseButton, children: "\uB2EB\uAE30" }) })
|
|
2169
|
+
]
|
|
1875
2170
|
}
|
|
1876
2171
|
) : null,
|
|
1877
|
-
announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.
|
|
2172
|
+
devSettingsOpen || announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1878
2173
|
"div",
|
|
1879
2174
|
{
|
|
1880
|
-
role: "status",
|
|
1881
|
-
"aria-live": "polite",
|
|
1882
2175
|
style: {
|
|
1883
2176
|
position: "fixed",
|
|
1884
2177
|
right: 24,
|
|
1885
2178
|
bottom: 82,
|
|
1886
2179
|
zIndex: 2147483601,
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
boxShadow: TOKENS.shadow
|
|
2180
|
+
display: "flex",
|
|
2181
|
+
flexDirection: "column",
|
|
2182
|
+
alignItems: "flex-end",
|
|
2183
|
+
gap: 8
|
|
1892
2184
|
},
|
|
1893
|
-
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
|
+
]
|
|
1894
2246
|
}
|
|
1895
2247
|
) : null,
|
|
1896
2248
|
screen === "modal" && modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1971,7 +2323,7 @@ function FeedbackKit(props) {
|
|
|
1971
2323
|
active: pickingActive,
|
|
1972
2324
|
paused: pickingState.paused,
|
|
1973
2325
|
disabled: draftLocked,
|
|
1974
|
-
focusId:
|
|
2326
|
+
focusId: import_feedback_kit_core4.MODAL_ACTION_PICK,
|
|
1975
2327
|
onToggle: togglePicking
|
|
1976
2328
|
}
|
|
1977
2329
|
),
|
|
@@ -2005,7 +2357,7 @@ function FeedbackKit(props) {
|
|
|
2005
2357
|
"button",
|
|
2006
2358
|
{
|
|
2007
2359
|
type: "button",
|
|
2008
|
-
"data-fk-focus-id":
|
|
2360
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_REMOVE_SCREENSHOT,
|
|
2009
2361
|
disabled: draftLocked,
|
|
2010
2362
|
onClick: () => kit.widget.modal.removeScreenshot(),
|
|
2011
2363
|
style: baseButton,
|
|
@@ -2065,7 +2417,7 @@ function FeedbackKit(props) {
|
|
|
2065
2417
|
"textarea",
|
|
2066
2418
|
{
|
|
2067
2419
|
id: "feedback-kit-comment",
|
|
2068
|
-
"data-fk-focus-id":
|
|
2420
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_FIELD_COMMENT,
|
|
2069
2421
|
value: modal.comment,
|
|
2070
2422
|
disabled: draftLocked,
|
|
2071
2423
|
"aria-required": "true",
|
|
@@ -2086,7 +2438,7 @@ function FeedbackKit(props) {
|
|
|
2086
2438
|
"select",
|
|
2087
2439
|
{
|
|
2088
2440
|
id: "feedback-kit-priority",
|
|
2089
|
-
"data-fk-focus-id":
|
|
2441
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_FIELD_PRIORITY,
|
|
2090
2442
|
value: modal.priority,
|
|
2091
2443
|
disabled: draftLocked,
|
|
2092
2444
|
onChange: (event) => kit.widget.modal.setPriority(event.currentTarget.value),
|
|
@@ -2118,7 +2470,7 @@ function FeedbackKit(props) {
|
|
|
2118
2470
|
"button",
|
|
2119
2471
|
{
|
|
2120
2472
|
type: "button",
|
|
2121
|
-
"data-fk-focus-id":
|
|
2473
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_RETRY,
|
|
2122
2474
|
onClick: () => void kit.widget.retryReport(),
|
|
2123
2475
|
style: { ...baseButton, marginLeft: 10 },
|
|
2124
2476
|
children: "\uB2E4\uC2DC \uBCF4\uB0B4\uAE30"
|
|
@@ -2132,7 +2484,7 @@ function FeedbackKit(props) {
|
|
|
2132
2484
|
"button",
|
|
2133
2485
|
{
|
|
2134
2486
|
type: "button",
|
|
2135
|
-
"data-fk-focus-id":
|
|
2487
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_CANCEL,
|
|
2136
2488
|
onClick: closeReport,
|
|
2137
2489
|
style: baseButton,
|
|
2138
2490
|
children: "\uCDE8\uC18C"
|
|
@@ -2142,14 +2494,14 @@ function FeedbackKit(props) {
|
|
|
2142
2494
|
"button",
|
|
2143
2495
|
{
|
|
2144
2496
|
type: "submit",
|
|
2145
|
-
"data-fk-focus-id":
|
|
2497
|
+
"data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_SEND,
|
|
2146
2498
|
disabled: !modal.canSubmit,
|
|
2147
2499
|
style: {
|
|
2148
2500
|
...primaryButton,
|
|
2149
2501
|
opacity: modal.canSubmit ? 1 : 0.5,
|
|
2150
2502
|
cursor: modal.canSubmit ? "pointer" : "not-allowed"
|
|
2151
2503
|
},
|
|
2152
|
-
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"
|
|
2153
2505
|
}
|
|
2154
2506
|
)
|
|
2155
2507
|
] })
|
|
@@ -2228,7 +2580,10 @@ function FeedbackKit(props) {
|
|
|
2228
2580
|
markerCount: pickingState.markers.length,
|
|
2229
2581
|
onToggle: togglePicking,
|
|
2230
2582
|
onTogglePause: () => activeKit.picking.togglePause(),
|
|
2231
|
-
onClearMarkers: () => activeKit.picking.clearMarkers()
|
|
2583
|
+
onClearMarkers: () => activeKit.picking.clearMarkers(),
|
|
2584
|
+
onReportWholeScreen: () => void openReport(),
|
|
2585
|
+
devClipCount: devMode ? devClipCount : 0,
|
|
2586
|
+
onCopyAll: () => void copyAll()
|
|
2232
2587
|
}
|
|
2233
2588
|
),
|
|
2234
2589
|
pickingState.markers.map((marker, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -2265,7 +2620,7 @@ function FeedbackKit(props) {
|
|
|
2265
2620
|
"aria-label": "\uC694\uC18C \uC8FC\uC11D",
|
|
2266
2621
|
onSubmit: (event) => {
|
|
2267
2622
|
event.preventDefault();
|
|
2268
|
-
|
|
2623
|
+
commitPopup();
|
|
2269
2624
|
},
|
|
2270
2625
|
onPaste: (event) => {
|
|
2271
2626
|
if (!firstImageOf(event.clipboardData)) return;
|
|
@@ -2347,14 +2702,14 @@ function FeedbackKit(props) {
|
|
|
2347
2702
|
const native = event.nativeEvent;
|
|
2348
2703
|
if (native.isComposing) return;
|
|
2349
2704
|
event.preventDefault();
|
|
2350
|
-
|
|
2705
|
+
commitPopup();
|
|
2351
2706
|
},
|
|
2352
2707
|
rows: 2,
|
|
2353
2708
|
placeholder: "\uBB34\uC5C7\uC774 \uBB38\uC81C\uC778\uAC00\uC694? (Enter \uB85C \uBCF4\uB0B4\uAE30)",
|
|
2354
2709
|
style: { ...inputStyle, resize: "vertical", minHeight: 58 }
|
|
2355
2710
|
}
|
|
2356
2711
|
),
|
|
2357
|
-
popup.comment.length >
|
|
2712
|
+
popup.comment.length > import_feedback_kit_core4.COMMENT_MAX_CHARS ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "alert", style: { marginTop: 4, color: TOKENS.danger }, children: "4,000\uC790 \uC774\uD558\uB85C \uC785\uB825\uD574\uC8FC\uC138\uC694" }) : null,
|
|
2358
2713
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2359
2714
|
"div",
|
|
2360
2715
|
{
|
|
@@ -2418,7 +2773,7 @@ function FeedbackKit(props) {
|
|
|
2418
2773
|
opacity: popup.canSave && !popup.saving ? 1 : 0.5,
|
|
2419
2774
|
cursor: popup.canSave && !popup.saving ? "pointer" : "not-allowed"
|
|
2420
2775
|
},
|
|
2421
|
-
children: popup.saving ? "\uBCF4\uB0B4\uB294 \uC911\u2026" : "\uBCF4\uB0B4\uAE30"
|
|
2776
|
+
children: popup.saving ? "\uBCF4\uB0B4\uB294 \uC911\u2026" : devMode ? "\uBCF5\uC0AC" : "\uBCF4\uB0B4\uAE30"
|
|
2422
2777
|
}
|
|
2423
2778
|
)
|
|
2424
2779
|
] })
|