@solhun/feedback-kit-web 0.10.0 → 0.11.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.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ElementInfo, FeedbackPin, FeedbackScreenshot, FeedbackHint, FeedbackReport, SubmitOutcome, QueueStatus, ReportParts, ScreenshotCapture, ScreenshotReencode, RouteWatcher, WidgetControllerOpts, HintProvider, WidgetController, FeedbackStorage, ContextProviders, DiagnosticsInstallOpts, RouteTrailStore } from '@solhun/feedback-kit-core';
1
+ import { ElementInfo, FeedbackPin, FeedbackScreenshot, FeedbackHint, FeedbackReport, SubmitOutcome, QueueStatus, ReportParts, ScreenshotCapture, ScreenshotReencode, RouteWatcher, WidgetControllerOpts, HintProvider, WidgetController, FeedbackAdapter, FeedbackStorage, ContextProviders, DiagnosticsInstallOpts, RouteTrailStore } from '@solhun/feedback-kit-core';
2
2
  export { COMMENT_MAX_CHARS, COMMENT_REQUIRED_MESSAGE, COMMENT_TOO_LONG_MESSAGE, ElementInfo, ElementLike, FLOATING_BUTTON_ID, FeedbackAdapter, FeedbackConfig, FeedbackContext, FeedbackHint, FeedbackPin, FeedbackReport, FeedbackStorage, FeedbackUser, HintCatalog, HintElementRule, HintPlatform, HintProvider, HintRankInput, HintScope, MODAL_ACTION_HINT_TOGGLE, MODAL_ACTION_PICK, ModalSubmitStatus, ReportModalController, ReportModalState, ResolvedConfig, SCREENSHOT_FAILED_MESSAGE, SOURCE_ATTR, SUBMIT_DONE_MESSAGE, SUBMIT_PENDING_MESSAGE, ScreenshotStatus, SubmitResult, Visibility, VisibilityEnv, VisibilityFn, WidgetController, WidgetPosition, WidgetScreen, WidgetState, denormalizePin, normalizePin, parseSourceAttr, rankHints, resolveConfig, shouldShowWidget, sourceFromElement } from '@solhun/feedback-kit-core';
3
3
  import * as react from 'react';
4
4
 
@@ -391,6 +391,11 @@ interface WebWidget {
391
391
  widget: WidgetController;
392
392
  picking: ElementPickingController;
393
393
  store: MarkerStore;
394
+ /**
395
+ * "이 화면의 제보가 어디로 가나" 조회. 어댑터가 지원하지 않으면 `null` 이고,
396
+ * 그러면 설정 화면이 "확인 못 했습니다"를 보여준다. 표시용이라 없어도 제보에는 영향이 없다.
397
+ */
398
+ fetchConnection: NonNullable<FeedbackAdapter["fetchConnection"]> | null;
394
399
  dispose(): void;
395
400
  }
396
401
  declare function createWebWidget(opts: WebWidgetOpts): WebWidget;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ElementInfo, FeedbackPin, FeedbackScreenshot, FeedbackHint, FeedbackReport, SubmitOutcome, QueueStatus, ReportParts, ScreenshotCapture, ScreenshotReencode, RouteWatcher, WidgetControllerOpts, HintProvider, WidgetController, FeedbackStorage, ContextProviders, DiagnosticsInstallOpts, RouteTrailStore } from '@solhun/feedback-kit-core';
1
+ import { ElementInfo, FeedbackPin, FeedbackScreenshot, FeedbackHint, FeedbackReport, SubmitOutcome, QueueStatus, ReportParts, ScreenshotCapture, ScreenshotReencode, RouteWatcher, WidgetControllerOpts, HintProvider, WidgetController, FeedbackAdapter, FeedbackStorage, ContextProviders, DiagnosticsInstallOpts, RouteTrailStore } from '@solhun/feedback-kit-core';
2
2
  export { COMMENT_MAX_CHARS, COMMENT_REQUIRED_MESSAGE, COMMENT_TOO_LONG_MESSAGE, ElementInfo, ElementLike, FLOATING_BUTTON_ID, FeedbackAdapter, FeedbackConfig, FeedbackContext, FeedbackHint, FeedbackPin, FeedbackReport, FeedbackStorage, FeedbackUser, HintCatalog, HintElementRule, HintPlatform, HintProvider, HintRankInput, HintScope, MODAL_ACTION_HINT_TOGGLE, MODAL_ACTION_PICK, ModalSubmitStatus, ReportModalController, ReportModalState, ResolvedConfig, SCREENSHOT_FAILED_MESSAGE, SOURCE_ATTR, SUBMIT_DONE_MESSAGE, SUBMIT_PENDING_MESSAGE, ScreenshotStatus, SubmitResult, Visibility, VisibilityEnv, VisibilityFn, WidgetController, WidgetPosition, WidgetScreen, WidgetState, denormalizePin, normalizePin, parseSourceAttr, rankHints, resolveConfig, shouldShowWidget, sourceFromElement } from '@solhun/feedback-kit-core';
3
3
  import * as react from 'react';
4
4
 
@@ -391,6 +391,11 @@ interface WebWidget {
391
391
  widget: WidgetController;
392
392
  picking: ElementPickingController;
393
393
  store: MarkerStore;
394
+ /**
395
+ * "이 화면의 제보가 어디로 가나" 조회. 어댑터가 지원하지 않으면 `null` 이고,
396
+ * 그러면 설정 화면이 "확인 못 했습니다"를 보여준다. 표시용이라 없어도 제보에는 영향이 없다.
397
+ */
398
+ fetchConnection: NonNullable<FeedbackAdapter["fetchConnection"]> | null;
394
399
  dispose(): void;
395
400
  }
396
401
  declare function createWebWidget(opts: WebWidgetOpts): WebWidget;
package/dist/index.js CHANGED
@@ -1062,6 +1062,11 @@ function hintSourceFrom(queue) {
1062
1062
  const cacheKey = adapter.hintsCacheKey ?? "default";
1063
1063
  return { fetchHints: adapter.fetchHints.bind(adapter), cacheKey };
1064
1064
  }
1065
+ function connectionSourceFrom(queue) {
1066
+ const adapter = queue.adapter;
1067
+ if (!adapter || typeof adapter.fetchConnection !== "function") return null;
1068
+ return adapter.fetchConnection.bind(adapter);
1069
+ }
1065
1070
  function resolveHintProvider(opts) {
1066
1071
  if (opts.hintProvider) return opts.hintProvider;
1067
1072
  if (opts.hints) {
@@ -1147,6 +1152,7 @@ function createWebWidget(opts) {
1147
1152
  widget,
1148
1153
  picking,
1149
1154
  store,
1155
+ fetchConnection: connectionSourceFrom(opts.queue),
1150
1156
  dispose() {
1151
1157
  picking.dispose();
1152
1158
  widget.dispose();
@@ -1174,7 +1180,7 @@ import {
1174
1180
  } from "react";
1175
1181
 
1176
1182
  // src/version.ts
1177
- var VERSION = true ? "0.10.0" : "dev";
1183
+ var VERSION = true ? "0.11.0" : "dev";
1178
1184
 
1179
1185
  // src/dev-clipboard.ts
1180
1186
  import { sourceFromElement } from "@solhun/feedback-kit-core";
@@ -1753,6 +1759,8 @@ function FeedbackKit(props) {
1753
1759
  () => props.devMode === true || isDevSettingsHost(globalThis.location?.hostname ?? "")
1754
1760
  );
1755
1761
  const [devSettingsOpen, setDevSettingsOpen] = useState(false);
1762
+ const [connection, setConnection] = useState(null);
1763
+ const [connectionState, setConnectionState] = useState("idle");
1756
1764
  const devClipsRef = useRef([]);
1757
1765
  const [devClipCount, setDevClipCount] = useState(0);
1758
1766
  const [devFallbackText, setDevFallbackText] = useState(null);
@@ -1912,6 +1920,20 @@ function FeedbackKit(props) {
1912
1920
  if (devClipsRef.current.length === 0) return;
1913
1921
  await putOnClipboard(renderDevClipList(devClipsRef.current));
1914
1922
  }
1923
+ function openDevSettings() {
1924
+ setDevSettingsOpen(true);
1925
+ if (connectionState !== "idle") return;
1926
+ const fetchConnection = activeKit.fetchConnection;
1927
+ if (!fetchConnection) {
1928
+ setConnectionState("fail");
1929
+ return;
1930
+ }
1931
+ setConnectionState("loading");
1932
+ void fetchConnection().then((value) => {
1933
+ setConnection(value);
1934
+ setConnectionState(value ? "done" : "fail");
1935
+ }).catch(() => setConnectionState("fail"));
1936
+ }
1915
1937
  function toggleDevMode(next) {
1916
1938
  writeDevPreference(next);
1917
1939
  setDevMode(next);
@@ -2033,7 +2055,7 @@ function FeedbackKit(props) {
2033
2055
  "data-fk-dev-settings-toggle": "",
2034
2056
  "aria-label": "\uD53C\uB4DC\uBC31 \uC124\uC815",
2035
2057
  "aria-expanded": devSettingsOpen,
2036
- onClick: () => setDevSettingsOpen((open) => !open),
2058
+ onClick: () => devSettingsOpen ? setDevSettingsOpen(false) : openDevSettings(),
2037
2059
  style: {
2038
2060
  ...baseButton,
2039
2061
  width: 46,
@@ -2178,6 +2200,50 @@ function FeedbackKit(props) {
2178
2200
  ] })
2179
2201
  ] })
2180
2202
  ] }),
2203
+ /* @__PURE__ */ jsxs(
2204
+ "div",
2205
+ {
2206
+ "data-fk-connection": "",
2207
+ style: {
2208
+ marginTop: 12,
2209
+ paddingTop: 12,
2210
+ borderTop: `1px solid ${TOKENS.line}`,
2211
+ fontSize: 12.5
2212
+ },
2213
+ children: [
2214
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700, marginBottom: 6 }, children: "\uBCF4\uB0B4\uB294 \uACF3" }),
2215
+ connectionState === "loading" ? /* @__PURE__ */ jsx("div", { style: { color: TOKENS.muted }, children: "\uD655\uC778\uD558\uB294 \uC911\u2026" }) : connectionState === "fail" || !connection ? (
2216
+ // 조용히 비우면 "연결이 없다"로 읽힌다. 못 물어봤다는 것과 없다는 것은 다르다.
2217
+ /* @__PURE__ */ jsx("div", { style: { color: TOKENS.muted }, children: "\uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(\uC218\uC9D1\uCC98\uAC00 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC74C)." })
2218
+ ) : /* @__PURE__ */ jsxs("ul", { style: { margin: 0, paddingLeft: 16, color: TOKENS.ink, lineHeight: 1.7 }, children: [
2219
+ /* @__PURE__ */ jsxs("li", { children: [
2220
+ "\uC218\uC9D1\uCC98 \xB7 ",
2221
+ connection.project.name ?? "\uC774\uB984 \uC5C6\uB294 \uD504\uB85C\uC81D\uD2B8"
2222
+ ] }),
2223
+ /* @__PURE__ */ jsxs("li", { children: [
2224
+ "Linear \xB7",
2225
+ " ",
2226
+ connection.linear.connected ? /* @__PURE__ */ jsxs(Fragment, { children: [
2227
+ connection.linear.teamName ?? "\uC5F0\uACB0\uB41C \uD300",
2228
+ connection.linear.projectName ? ` / ${connection.linear.projectName}` : "",
2229
+ " \u2014 ",
2230
+ /* @__PURE__ */ jsx("b", { children: connection.linear.autoExport ? "\uC81C\uBCF4\uAC00 \uC790\uB3D9\uC73C\uB85C \uB098\uAC11\uB2C8\uB2E4" : "\uC790\uB3D9 \uBC1C\uC1A1 \uAEBC\uC9D0" })
2231
+ ] }) : "\uC5F0\uACB0 \uC5C6\uC74C"
2232
+ ] }),
2233
+ /* @__PURE__ */ jsxs("li", { children: [
2234
+ "Symphony \xB7",
2235
+ " ",
2236
+ connection.symphonySlug ? `${connection.symphonySlug} \uAC00 \uCC98\uB9AC` : "\uC790\uB3D9 \uCC98\uB9AC \uC548 \uD568"
2237
+ ] })
2238
+ ] }),
2239
+ devMode ? (
2240
+ // 개발용 모드가 켜져 있으면 위 목록은 "원래 가던 곳"일 뿐이다. 그대로 두면
2241
+ // 지금도 거기로 가는 줄 읽는다.
2242
+ /* @__PURE__ */ jsx("div", { style: { marginTop: 8, color: TOKENS.warning, fontWeight: 700 }, children: "\uC9C0\uAE08\uC740 \uC5B4\uB514\uC5D0\uB3C4 \uC548 \uBCF4\uB0C5\uB2C8\uB2E4 \u2014 \uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uAC00 \uCF1C\uC838 \uC788\uC2B5\uB2C8\uB2E4." })
2243
+ ) : null
2244
+ ]
2245
+ }
2246
+ ),
2181
2247
  /* @__PURE__ */ jsxs("p", { style: { margin: "12px 0 0", color: TOKENS.muted, fontSize: 12 }, children: [
2182
2248
  "\uC774 \uC124\uC815\uC740 \uB85C\uCEEC(",
2183
2249
  /* @__PURE__ */ jsx("code", { children: "localhost" }),