@solhun/feedback-kit-web 0.8.0 → 0.9.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 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: () => import_feedback_kit_core6.COMMENT_MAX_CHARS,
34
- COMMENT_REQUIRED_MESSAGE: () => import_feedback_kit_core6.COMMENT_REQUIRED_MESSAGE,
35
- COMMENT_TOO_LONG_MESSAGE: () => import_feedback_kit_core6.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: () => import_feedback_kit_core6.FLOATING_BUTTON_ID,
38
+ FLOATING_BUTTON_ID: () => import_feedback_kit_core7.FLOATING_BUTTON_ID,
39
39
  FeedbackKit: () => FeedbackKit,
40
- HintProvider: () => import_feedback_kit_core7.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: () => import_feedback_kit_core6.MODAL_ACTION_HINT_TOGGLE,
44
- MODAL_ACTION_PICK: () => import_feedback_kit_core6.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: () => import_feedback_kit_core6.ReportModalController,
49
- SCREENSHOT_FAILED_MESSAGE: () => import_feedback_kit_core6.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: () => import_feedback_kit_core5.SOURCE_ATTR,
52
- SUBMIT_DONE_MESSAGE: () => import_feedback_kit_core6.SUBMIT_DONE_MESSAGE,
53
- SUBMIT_PENDING_MESSAGE: () => import_feedback_kit_core6.SUBMIT_PENDING_MESSAGE,
54
- WidgetController: () => import_feedback_kit_core6.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: () => import_feedback_kit_core6.denormalizePin,
60
+ denormalizePin: () => import_feedback_kit_core7.denormalizePin,
61
61
  describeElement: () => describeElement,
62
62
  isOwnUi: () => isOwnUi2,
63
- normalizePin: () => import_feedback_kit_core6.normalizePin,
64
- parseSourceAttr: () => import_feedback_kit_core5.parseSourceAttr,
65
- rankHints: () => import_feedback_kit_core7.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: () => import_feedback_kit_core4.resolveConfig,
70
- shouldShowWidget: () => import_feedback_kit_core4.shouldShowWidget,
71
- sourceFromElement: () => import_feedback_kit_core5.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,57 @@ function createWebWidget(opts) {
1210
1210
  }
1211
1211
 
1212
1212
  // src/feedback-kit.tsx
1213
- var import_feedback_kit_core3 = require("@solhun/feedback-kit-core");
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.8.0" : "dev";
1217
+ var VERSION = true ? "0.9.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
+ }
1218
1264
 
1219
1265
  // src/feedback-kit.tsx
1220
1266
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1483,7 +1529,10 @@ function PickBar({
1483
1529
  markerCount,
1484
1530
  onToggle,
1485
1531
  onTogglePause,
1486
- onClearMarkers
1532
+ onClearMarkers,
1533
+ onReportWholeScreen,
1534
+ devClipCount,
1535
+ onCopyAll
1487
1536
  }) {
1488
1537
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1489
1538
  "div",
@@ -1538,6 +1587,48 @@ function PickBar({
1538
1587
  ]
1539
1588
  }
1540
1589
  ),
1590
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1591
+ "button",
1592
+ {
1593
+ type: "button",
1594
+ "data-fk-pick-whole": "",
1595
+ title: "\uAC00\uB9AC\uD0A8 \uC694\uC18C \uC5C6\uC774 \uC774 \uD654\uBA74 \uC804\uCCB4\uC5D0 \uB300\uD574 \uC81C\uBCF4\uD569\uB2C8\uB2E4.",
1596
+ onClick: onReportWholeScreen,
1597
+ style: {
1598
+ ...baseButton,
1599
+ display: "inline-flex",
1600
+ alignItems: "center",
1601
+ gap: 6,
1602
+ whiteSpace: "nowrap"
1603
+ },
1604
+ children: [
1605
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u25A3" }),
1606
+ "\uD654\uBA74 \uC804\uCCB4\uB85C \uBCF4\uB0B4\uAE30"
1607
+ ]
1608
+ }
1609
+ ),
1610
+ devClipCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1611
+ "button",
1612
+ {
1613
+ type: "button",
1614
+ "data-fk-copy-all": devClipCount,
1615
+ title: "\uC774\uBC88 \uC138\uC158\uC5D0 \uCC0D\uC740 \uAC83\uC744 \uBC88\uD638 \uB9E4\uAE34 \uBAA9\uB85D \uD558\uB098\uB85C \uBCF5\uC0AC\uD569\uB2C8\uB2E4.",
1616
+ onClick: onCopyAll,
1617
+ style: {
1618
+ ...baseButton,
1619
+ display: "inline-flex",
1620
+ alignItems: "center",
1621
+ gap: 6,
1622
+ whiteSpace: "nowrap",
1623
+ fontWeight: 600
1624
+ },
1625
+ children: [
1626
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u29C9" }),
1627
+ "\uC804\uBD80 \uBCF5\uC0AC ",
1628
+ devClipCount
1629
+ ]
1630
+ }
1631
+ ) : null,
1541
1632
  markerCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1542
1633
  "button",
1543
1634
  {
@@ -1592,7 +1683,7 @@ function HintChips({
1592
1683
  "button",
1593
1684
  {
1594
1685
  type: "button",
1595
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_ACTION_HINT_TOGGLE,
1686
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_HINT_TOGGLE,
1596
1687
  "aria-expanded": hintsExpanded,
1597
1688
  disabled,
1598
1689
  onClick: onToggle,
@@ -1666,6 +1757,10 @@ function FeedbackKit(props) {
1666
1757
  const [widgetState, setWidgetState] = (0, import_react.useState)(null);
1667
1758
  const [pickingState, setPickingState] = (0, import_react.useState)(INITIAL_PICKING_STATE);
1668
1759
  const [announcement, setAnnouncement] = (0, import_react.useState)(null);
1760
+ const [devMode] = (0, import_react.useState)(() => props.devMode === true);
1761
+ const devClipsRef = (0, import_react.useRef)([]);
1762
+ const [devClipCount, setDevClipCount] = (0, import_react.useState)(0);
1763
+ const [devFallbackText, setDevFallbackText] = (0, import_react.useState)(null);
1669
1764
  const {
1670
1765
  queue,
1671
1766
  createReport,
@@ -1726,7 +1821,7 @@ function FeedbackKit(props) {
1726
1821
  }
1727
1822
  if (modal2.closeConfirmVisible && !previousConfirmVisibleRef.current) confirmRef.current?.focus();
1728
1823
  const wasModal = previousScreenRef.current === "modal";
1729
- if (wasModal && screen2 === "button" && modal2.restoreFocusTo === import_feedback_kit_core3.FLOATING_BUTTON_ID) {
1824
+ if (wasModal && screen2 === "button" && modal2.restoreFocusTo === import_feedback_kit_core4.FLOATING_BUTTON_ID) {
1730
1825
  void nextPaint().then(() => floatingButtonRef.current?.focus());
1731
1826
  }
1732
1827
  previousScreenRef.current = screen2;
@@ -1790,6 +1885,39 @@ function FeedbackKit(props) {
1790
1885
  if (root) root.style.visibility = previousVisibility;
1791
1886
  }
1792
1887
  }
1888
+ function currentClip() {
1889
+ const state = pickingState.popup;
1890
+ if (!state) return null;
1891
+ return {
1892
+ comment: state.comment,
1893
+ element: state.element ?? null,
1894
+ screen: typeof location === "undefined" ? null : location.pathname
1895
+ };
1896
+ }
1897
+ async function putOnClipboard(text) {
1898
+ const ok = await writeToClipboard(text);
1899
+ setDevFallbackText(ok ? null : text);
1900
+ }
1901
+ async function copyOne() {
1902
+ const clip = currentClip();
1903
+ if (!clip || clip.comment.trim() === "") return;
1904
+ devClipsRef.current = [...devClipsRef.current, clip];
1905
+ setDevClipCount(devClipsRef.current.length);
1906
+ activeKit.picking.cancelAnnotation();
1907
+ await putOnClipboard(renderDevClipItem(clip));
1908
+ }
1909
+ async function copyAll() {
1910
+ if (devClipsRef.current.length === 0) return;
1911
+ await putOnClipboard(renderDevClipList(devClipsRef.current));
1912
+ }
1913
+ async function pressFloatingButton() {
1914
+ if (props.defaultMode !== "report" && !pickingActive) {
1915
+ setAnnouncement(null);
1916
+ activeKit.widget.startPicking();
1917
+ return;
1918
+ }
1919
+ await openReport();
1920
+ }
1793
1921
  async function openReport() {
1794
1922
  setAnnouncement(null);
1795
1923
  await withOwnUiHidden(() => activeKit.widget.openReport());
@@ -1856,10 +1984,10 @@ function FeedbackKit(props) {
1856
1984
  "button",
1857
1985
  {
1858
1986
  ref: floatingButtonRef,
1859
- id: import_feedback_kit_core3.FLOATING_BUTTON_ID,
1987
+ id: import_feedback_kit_core4.FLOATING_BUTTON_ID,
1860
1988
  type: "button",
1861
1989
  "aria-label": "\uD53C\uB4DC\uBC31 \uBCF4\uB0B4\uAE30",
1862
- onClick: () => void openReport(),
1990
+ onClick: () => void pressFloatingButton(),
1863
1991
  style: {
1864
1992
  ...primaryButton,
1865
1993
  position: "fixed",
@@ -1874,6 +2002,66 @@ function FeedbackKit(props) {
1874
2002
  children: "\uD53C\uB4DC\uBC31"
1875
2003
  }
1876
2004
  ) : null,
2005
+ floating && devMode ? (
2006
+ // 켠 줄 모르고 제보하면 "보냈다"고 믿는데 수집처엔 아무것도 안 남는다.
2007
+ // 조용한 유실이라 이 표시가 유일한 방어다. 버튼 **밖**에 두는 이유는 버튼의
2008
+ // 접근성 이름을 오염시키지 않기 위해서다.
2009
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2010
+ "span",
2011
+ {
2012
+ "data-fk-dev-badge": "",
2013
+ "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",
2014
+ style: {
2015
+ position: "fixed",
2016
+ right: 24,
2017
+ bottom: 62,
2018
+ zIndex: 2147483601,
2019
+ padding: "2px 8px",
2020
+ borderRadius: 6,
2021
+ background: TOKENS.warning,
2022
+ color: "#1f2933",
2023
+ fontSize: 11,
2024
+ fontWeight: 700,
2025
+ pointerEvents: "none"
2026
+ },
2027
+ children: "\uAC1C\uBC1C\uC6A9 \u2014 \uD074\uB9BD\uBCF4\uB4DC\uB85C \uBCF5\uC0AC"
2028
+ }
2029
+ )
2030
+ ) : null,
2031
+ devFallbackText !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2032
+ "div",
2033
+ {
2034
+ role: "dialog",
2035
+ "aria-label": "\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBABB \uC368\uC11C \uB300\uC2E0 \uBCF4\uC5EC\uC90D\uB2C8\uB2E4",
2036
+ "data-fk-dev-fallback": "",
2037
+ style: {
2038
+ position: "fixed",
2039
+ right: 24,
2040
+ bottom: 92,
2041
+ zIndex: 2147483602,
2042
+ width: "min(420px, calc(100vw - 48px))",
2043
+ border: `1px solid ${TOKENS.line}`,
2044
+ borderRadius: 12,
2045
+ background: TOKENS.surface,
2046
+ padding: 12,
2047
+ boxShadow: TOKENS.shadow,
2048
+ pointerEvents: "auto"
2049
+ },
2050
+ children: [
2051
+ /* @__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." }),
2052
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2053
+ "textarea",
2054
+ {
2055
+ readOnly: true,
2056
+ value: devFallbackText,
2057
+ onFocus: (event) => event.currentTarget.select(),
2058
+ style: { ...inputStyle, height: 140, fontFamily: "ui-monospace, monospace", fontSize: 12 }
2059
+ }
2060
+ ),
2061
+ /* @__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" }) })
2062
+ ]
2063
+ }
2064
+ ) : null,
1877
2065
  announcement && !modal.open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1878
2066
  "div",
1879
2067
  {
@@ -1971,7 +2159,7 @@ function FeedbackKit(props) {
1971
2159
  active: pickingActive,
1972
2160
  paused: pickingState.paused,
1973
2161
  disabled: draftLocked,
1974
- focusId: import_feedback_kit_core3.MODAL_ACTION_PICK,
2162
+ focusId: import_feedback_kit_core4.MODAL_ACTION_PICK,
1975
2163
  onToggle: togglePicking
1976
2164
  }
1977
2165
  ),
@@ -2005,7 +2193,7 @@ function FeedbackKit(props) {
2005
2193
  "button",
2006
2194
  {
2007
2195
  type: "button",
2008
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_ACTION_REMOVE_SCREENSHOT,
2196
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_REMOVE_SCREENSHOT,
2009
2197
  disabled: draftLocked,
2010
2198
  onClick: () => kit.widget.modal.removeScreenshot(),
2011
2199
  style: baseButton,
@@ -2065,7 +2253,7 @@ function FeedbackKit(props) {
2065
2253
  "textarea",
2066
2254
  {
2067
2255
  id: "feedback-kit-comment",
2068
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_FIELD_COMMENT,
2256
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_FIELD_COMMENT,
2069
2257
  value: modal.comment,
2070
2258
  disabled: draftLocked,
2071
2259
  "aria-required": "true",
@@ -2086,7 +2274,7 @@ function FeedbackKit(props) {
2086
2274
  "select",
2087
2275
  {
2088
2276
  id: "feedback-kit-priority",
2089
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_FIELD_PRIORITY,
2277
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_FIELD_PRIORITY,
2090
2278
  value: modal.priority,
2091
2279
  disabled: draftLocked,
2092
2280
  onChange: (event) => kit.widget.modal.setPriority(event.currentTarget.value),
@@ -2118,7 +2306,7 @@ function FeedbackKit(props) {
2118
2306
  "button",
2119
2307
  {
2120
2308
  type: "button",
2121
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_ACTION_RETRY,
2309
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_RETRY,
2122
2310
  onClick: () => void kit.widget.retryReport(),
2123
2311
  style: { ...baseButton, marginLeft: 10 },
2124
2312
  children: "\uB2E4\uC2DC \uBCF4\uB0B4\uAE30"
@@ -2132,7 +2320,7 @@ function FeedbackKit(props) {
2132
2320
  "button",
2133
2321
  {
2134
2322
  type: "button",
2135
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_ACTION_CANCEL,
2323
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_CANCEL,
2136
2324
  onClick: closeReport,
2137
2325
  style: baseButton,
2138
2326
  children: "\uCDE8\uC18C"
@@ -2142,7 +2330,7 @@ function FeedbackKit(props) {
2142
2330
  "button",
2143
2331
  {
2144
2332
  type: "submit",
2145
- "data-fk-focus-id": import_feedback_kit_core3.MODAL_ACTION_SEND,
2333
+ "data-fk-focus-id": import_feedback_kit_core4.MODAL_ACTION_SEND,
2146
2334
  disabled: !modal.canSubmit,
2147
2335
  style: {
2148
2336
  ...primaryButton,
@@ -2228,7 +2416,10 @@ function FeedbackKit(props) {
2228
2416
  markerCount: pickingState.markers.length,
2229
2417
  onToggle: togglePicking,
2230
2418
  onTogglePause: () => activeKit.picking.togglePause(),
2231
- onClearMarkers: () => activeKit.picking.clearMarkers()
2419
+ onClearMarkers: () => activeKit.picking.clearMarkers(),
2420
+ onReportWholeScreen: () => void openReport(),
2421
+ devClipCount: devMode ? devClipCount : 0,
2422
+ onCopyAll: () => void copyAll()
2232
2423
  }
2233
2424
  ),
2234
2425
  pickingState.markers.map((marker, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -2265,6 +2456,10 @@ function FeedbackKit(props) {
2265
2456
  "aria-label": "\uC694\uC18C \uC8FC\uC11D",
2266
2457
  onSubmit: (event) => {
2267
2458
  event.preventDefault();
2459
+ if (devMode) {
2460
+ void copyOne();
2461
+ return;
2462
+ }
2268
2463
  void kit.picking.saveAnnotation();
2269
2464
  },
2270
2465
  onPaste: (event) => {
@@ -2354,7 +2549,7 @@ function FeedbackKit(props) {
2354
2549
  style: { ...inputStyle, resize: "vertical", minHeight: 58 }
2355
2550
  }
2356
2551
  ),
2357
- popup.comment.length > import_feedback_kit_core3.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,
2552
+ 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
2553
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2359
2554
  "div",
2360
2555
  {
@@ -2418,7 +2613,7 @@ function FeedbackKit(props) {
2418
2613
  opacity: popup.canSave && !popup.saving ? 1 : 0.5,
2419
2614
  cursor: popup.canSave && !popup.saving ? "pointer" : "not-allowed"
2420
2615
  },
2421
- children: popup.saving ? "\uBCF4\uB0B4\uB294 \uC911\u2026" : "\uBCF4\uB0B4\uAE30"
2616
+ children: popup.saving ? "\uBCF4\uB0B4\uB294 \uC911\u2026" : devMode ? "\uBCF5\uC0AC" : "\uBCF4\uB0B4\uAE30"
2422
2617
  }
2423
2618
  )
2424
2619
  ] })