@solhun/feedback-kit-web 0.10.0 → 0.12.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
@@ -1117,6 +1117,11 @@ function hintSourceFrom(queue) {
1117
1117
  const cacheKey = adapter.hintsCacheKey ?? "default";
1118
1118
  return { fetchHints: adapter.fetchHints.bind(adapter), cacheKey };
1119
1119
  }
1120
+ function connectionSourceFrom(queue) {
1121
+ const adapter = queue.adapter;
1122
+ if (!adapter || typeof adapter.fetchConnection !== "function") return null;
1123
+ return adapter.fetchConnection.bind(adapter);
1124
+ }
1120
1125
  function resolveHintProvider(opts) {
1121
1126
  if (opts.hintProvider) return opts.hintProvider;
1122
1127
  if (opts.hints) {
@@ -1202,6 +1207,7 @@ function createWebWidget(opts) {
1202
1207
  widget,
1203
1208
  picking,
1204
1209
  store,
1210
+ fetchConnection: connectionSourceFrom(opts.queue),
1205
1211
  dispose() {
1206
1212
  picking.dispose();
1207
1213
  widget.dispose();
@@ -1214,7 +1220,7 @@ var import_feedback_kit_core4 = require("@solhun/feedback-kit-core");
1214
1220
  var import_react = require("react");
1215
1221
 
1216
1222
  // src/version.ts
1217
- var VERSION = true ? "0.10.0" : "dev";
1223
+ var VERSION = true ? "0.12.0" : "dev";
1218
1224
 
1219
1225
  // src/dev-clipboard.ts
1220
1226
  var import_feedback_kit_core3 = require("@solhun/feedback-kit-core");
@@ -1292,6 +1298,36 @@ function resolveDevMode(propValue, stored) {
1292
1298
  if (stored !== null) return stored;
1293
1299
  return propValue === true;
1294
1300
  }
1301
+ var SETTINGS_FLAG = "fk-settings";
1302
+ var SESSION_KEY = "feedback-kit:settings-visible";
1303
+ function isSettingsRequested(search, session) {
1304
+ const store = session === void 0 ? sessionStorageOrNull() : session;
1305
+ let requested = false;
1306
+ try {
1307
+ requested = new URLSearchParams(search).get(SETTINGS_FLAG) === "1";
1308
+ } catch {
1309
+ requested = false;
1310
+ }
1311
+ if (requested) {
1312
+ try {
1313
+ store?.setItem(SESSION_KEY, "1");
1314
+ } catch {
1315
+ }
1316
+ return true;
1317
+ }
1318
+ try {
1319
+ return store?.getItem(SESSION_KEY) === "1";
1320
+ } catch {
1321
+ return false;
1322
+ }
1323
+ }
1324
+ function sessionStorageOrNull() {
1325
+ try {
1326
+ return globalThis.sessionStorage ?? null;
1327
+ } catch {
1328
+ return null;
1329
+ }
1330
+ }
1295
1331
 
1296
1332
  // src/feedback-kit.tsx
1297
1333
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1789,10 +1825,15 @@ function FeedbackKit(props) {
1789
1825
  const [pickingState, setPickingState] = (0, import_react.useState)(INITIAL_PICKING_STATE);
1790
1826
  const [announcement, setAnnouncement] = (0, import_react.useState)(null);
1791
1827
  const [devMode, setDevMode] = (0, import_react.useState)(() => resolveDevMode(props.devMode, readDevPreference()));
1792
- const [devSettingsAvailable] = (0, import_react.useState)(
1828
+ const [devToggleAvailable] = (0, import_react.useState)(
1793
1829
  () => props.devMode === true || isDevSettingsHost(globalThis.location?.hostname ?? "")
1794
1830
  );
1831
+ const [devSettingsAvailable] = (0, import_react.useState)(
1832
+ () => props.devMode === true || isDevSettingsHost(globalThis.location?.hostname ?? "") || isSettingsRequested(globalThis.location?.search ?? "")
1833
+ );
1795
1834
  const [devSettingsOpen, setDevSettingsOpen] = (0, import_react.useState)(false);
1835
+ const [connection, setConnection] = (0, import_react.useState)(null);
1836
+ const [connectionState, setConnectionState] = (0, import_react.useState)("idle");
1796
1837
  const devClipsRef = (0, import_react.useRef)([]);
1797
1838
  const [devClipCount, setDevClipCount] = (0, import_react.useState)(0);
1798
1839
  const [devFallbackText, setDevFallbackText] = (0, import_react.useState)(null);
@@ -1952,6 +1993,20 @@ function FeedbackKit(props) {
1952
1993
  if (devClipsRef.current.length === 0) return;
1953
1994
  await putOnClipboard(renderDevClipList(devClipsRef.current));
1954
1995
  }
1996
+ function openDevSettings() {
1997
+ setDevSettingsOpen(true);
1998
+ if (connectionState !== "idle") return;
1999
+ const fetchConnection = activeKit.fetchConnection;
2000
+ if (!fetchConnection) {
2001
+ setConnectionState("fail");
2002
+ return;
2003
+ }
2004
+ setConnectionState("loading");
2005
+ void fetchConnection().then((value) => {
2006
+ setConnection(value);
2007
+ setConnectionState(value ? "done" : "fail");
2008
+ }).catch(() => setConnectionState("fail"));
2009
+ }
1955
2010
  function toggleDevMode(next) {
1956
2011
  writeDevPreference(next);
1957
2012
  setDevMode(next);
@@ -2073,7 +2128,7 @@ function FeedbackKit(props) {
2073
2128
  "data-fk-dev-settings-toggle": "",
2074
2129
  "aria-label": "\uD53C\uB4DC\uBC31 \uC124\uC815",
2075
2130
  "aria-expanded": devSettingsOpen,
2076
- onClick: () => setDevSettingsOpen((open) => !open),
2131
+ onClick: () => devSettingsOpen ? setDevSettingsOpen(false) : openDevSettings(),
2077
2132
  style: {
2078
2133
  ...baseButton,
2079
2134
  width: 46,
@@ -2205,6 +2260,7 @@ function FeedbackKit(props) {
2205
2260
  {
2206
2261
  type: "checkbox",
2207
2262
  checked: devMode,
2263
+ disabled: !devToggleAvailable,
2208
2264
  onChange: (event) => toggleDevMode(event.currentTarget.checked),
2209
2265
  style: { marginTop: 3 }
2210
2266
  }
@@ -2218,11 +2274,61 @@ function FeedbackKit(props) {
2218
2274
  ] })
2219
2275
  ] })
2220
2276
  ] }),
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(",
2277
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2278
+ "div",
2279
+ {
2280
+ "data-fk-connection": "",
2281
+ style: {
2282
+ marginTop: 12,
2283
+ paddingTop: 12,
2284
+ borderTop: `1px solid ${TOKENS.line}`,
2285
+ fontSize: 12.5
2286
+ },
2287
+ children: [
2288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 700, marginBottom: 6 }, children: "\uBCF4\uB0B4\uB294 \uACF3" }),
2289
+ connectionState === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: TOKENS.muted }, children: "\uD655\uC778\uD558\uB294 \uC911\u2026" }) : connectionState === "fail" || !connection ? (
2290
+ // 조용히 비우면 "연결이 없다"로 읽힌다. 못 물어봤다는 것과 없다는 것은 다르다.
2291
+ /* @__PURE__ */ (0, import_jsx_runtime.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)." })
2292
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { style: { margin: 0, paddingLeft: 16, color: TOKENS.ink, lineHeight: 1.7 }, children: [
2293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
2294
+ "\uC218\uC9D1\uCC98 \xB7 ",
2295
+ connection.project.name ?? "\uC774\uB984 \uC5C6\uB294 \uD504\uB85C\uC81D\uD2B8"
2296
+ ] }),
2297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
2298
+ "Linear \xB7",
2299
+ " ",
2300
+ connection.linear.connected ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2301
+ connection.linear.teamName ?? "\uC5F0\uACB0\uB41C \uD300",
2302
+ connection.linear.projectName ? ` / ${connection.linear.projectName}` : "",
2303
+ " \u2014 ",
2304
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: connection.linear.autoExport ? "\uC81C\uBCF4\uAC00 \uC790\uB3D9\uC73C\uB85C \uB098\uAC11\uB2C8\uB2E4" : "\uC790\uB3D9 \uBC1C\uC1A1 \uAEBC\uC9D0" })
2305
+ ] }) : "\uC5F0\uACB0 \uC5C6\uC74C"
2306
+ ] }),
2307
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
2308
+ "Symphony \xB7",
2309
+ " ",
2310
+ connection.symphonySlug ? `${connection.symphonySlug} \uAC00 \uCC98\uB9AC` : "\uC790\uB3D9 \uCC98\uB9AC \uC548 \uD568"
2311
+ ] })
2312
+ ] }),
2313
+ devMode ? (
2314
+ // 개발용 모드가 켜져 있으면 위 목록은 "원래 가던 곳"일 뿐이다. 그대로 두면
2315
+ // 지금도 거기로 가는 줄 읽는다.
2316
+ /* @__PURE__ */ (0, import_jsx_runtime.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." })
2317
+ ) : null
2318
+ ]
2319
+ }
2320
+ ),
2321
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: "12px 0 0", color: TOKENS.muted, fontSize: 12 }, children: devToggleAvailable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2322
+ "\uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uB294 \uB85C\uCEEC(",
2223
2323
  /* @__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
- ] }),
2324
+ ")\uC5D0\uC11C\uB9CC \uCF24 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBC30\uD3EC\uB41C \uD654\uBA74\uC5D0\uC11C \uC2E4\uC0AC\uC6A9\uC790\uAC00 \uCF1C\uBA74 \uADF8 \uC0AC\uB78C \uC81C\uBCF4\uAC00 \uC5B4\uB514\uC5D0\uB3C4 \uC548 \uB0A8\uAE30 \uB54C\uBB38\uC785\uB2C8\uB2E4."
2325
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2326
+ "\uC5EC\uAE30\uC11C\uB294 ",
2327
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: "\uBCF4\uAE30\uB9CC" }),
2328
+ " \uB429\uB2C8\uB2E4. \uAC1C\uBC1C\uC6A9 \uBAA8\uB4DC\uB294 \uB85C\uCEEC(",
2329
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: "localhost" }),
2330
+ ")\uC5D0\uC11C\uB9CC \uCF24 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uC2E4\uC0AC\uC6A9\uC790\uAC00 \uCF1C\uBA74 \uADF8 \uC0AC\uB78C \uC81C\uBCF4\uAC00 \uC5B4\uB514\uC5D0\uB3C4 \uC548 \uB0A8\uAE30 \uB54C\uBB38\uC785\uB2C8\uB2E4."
2331
+ ] }) }),
2226
2332
  /* @__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
2333
  ]
2228
2334
  }