@fewchurs/react 1.2.1 → 1.4.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.js CHANGED
@@ -85,7 +85,7 @@ module.exports = __toCommonJS(src_exports);
85
85
  var import_react = require("react");
86
86
 
87
87
  // src/client/version.ts
88
- var SDK_VERSION = "1.2.1";
88
+ var SDK_VERSION = "1.4.0";
89
89
 
90
90
  // src/client/constants.ts
91
91
  var SDK_HEADER = `react/${SDK_VERSION}`;
@@ -307,7 +307,9 @@ function createFewchursClient(options = {}) {
307
307
  await delay(retryDelayMs);
308
308
  continue;
309
309
  }
310
- return { ok: false, error: networkError(messageOf(error)) };
310
+ const failure2 = networkError(messageOf(error));
311
+ logError(failure2);
312
+ return { ok: false, error: failure2 };
311
313
  }
312
314
  if (response.ok) {
313
315
  const payload = await readJson(response);
@@ -318,7 +320,7 @@ function createFewchursClient(options = {}) {
318
320
  continue;
319
321
  }
320
322
  const failure = errorFromResponse(response.status, await readJson(response));
321
- warnAboutKey(failure);
323
+ logError(failure);
322
324
  return { ok: false, error: failure };
323
325
  }
324
326
  return { ok: false, error: networkError() };
@@ -409,14 +411,15 @@ function delay(ms) {
409
411
  function messageOf(error) {
410
412
  return error instanceof Error ? error.message : "Network request failed.";
411
413
  }
412
- var warnedAboutKey = false;
413
- function warnAboutKey(error) {
414
- if (error.code !== "invalid_key" || warnedAboutKey) return;
414
+ var INVALID_KEY_HELP = "The API key was rejected. Check FEWCHURS_API_KEY (server) or the apiKey passed to FewchursProvider, and that the key is active in your Fewchurs dashboard.";
415
+ var loggedErrors = /* @__PURE__ */ new Set();
416
+ function logError(error) {
415
417
  if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
416
- warnedAboutKey = true;
417
- console.warn(
418
- error.status === 403 ? `[fewchurs] ${error.message}` : "[fewchurs] The API key was rejected. Check FEWCHURS_API_KEY (server) or the apiKey passed to FewchursProvider, and that the key is active in your Fewchurs dashboard."
419
- );
418
+ const isInvalidKey = error.code === "invalid_key" && error.status === 401;
419
+ const detail = isInvalidKey ? INVALID_KEY_HELP : error.message;
420
+ if (loggedErrors.has(detail)) return;
421
+ loggedErrors.add(detail);
422
+ console.warn(`[fewchurs] : ${detail}`);
420
423
  }
421
424
 
422
425
  // src/identity/deviceId.ts
@@ -846,6 +849,12 @@ var DEFAULT_LABELS = {
846
849
  loading: "Loading\u2026",
847
850
  loadMore: "Load more",
848
851
  retry: "Try again",
852
+ errorInvalidKeyTitle: "Invalid API key",
853
+ errorInvalidKeyDetail: "We can't connect to this board right now. The owner of this site needs to check its setup.",
854
+ errorWrongAppTitle: "Wrong platform",
855
+ errorWrongAppDetail: "This board isn't set up for this site or app yet. Its owner needs to add it in Fewchurs.",
856
+ errorTitle: "Something went wrong",
857
+ errorDetail: "We couldn't load the requests. Please try again.",
849
858
  comments: "Comments",
850
859
  commentPlaceholder: "Add a comment",
851
860
  postComment: "Post",
@@ -1321,6 +1330,12 @@ function Bar({ width, height }) {
1321
1330
 
1322
1331
  // src/components/FeatureList.tsx
1323
1332
  var import_jsx_runtime9 = require("react/jsx-runtime");
1333
+ function errorCopy(error, labels) {
1334
+ if (error.code !== "invalid_key") {
1335
+ return { title: labels.errorTitle, detail: labels.errorDetail };
1336
+ }
1337
+ return error.status === 403 ? { title: labels.errorWrongAppTitle, detail: labels.errorWrongAppDetail } : { title: labels.errorInvalidKeyTitle, detail: labels.errorInvalidKeyDetail };
1338
+ }
1324
1339
  function FeatureList() {
1325
1340
  const { initialFeatureId } = useBoard();
1326
1341
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
@@ -1350,17 +1365,11 @@ function Listing({ excludeId }) {
1350
1365
  return showDeclined || feature.status !== "declined";
1351
1366
  });
1352
1367
  if (error && visible.length === 0) {
1368
+ const { title, detail } = errorCopy(error, labels);
1353
1369
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: cx("fw-empty"), role: "alert", children: [
1354
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: userMessage(error) }),
1355
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1356
- "button",
1357
- {
1358
- type: "button",
1359
- className: cx("fw-btn", "fw-btn--ghost"),
1360
- onClick: () => void refresh(),
1361
- children: labels.retry
1362
- }
1363
- )
1370
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: cx("fw-empty__title"), children: title }),
1371
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: cx("fw-empty__detail"), children: detail }),
1372
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: cx("fw-btn-text"), onClick: () => void refresh(), children: labels.retry })
1364
1373
  ] });
1365
1374
  }
1366
1375
  if (isLoading && visible.length === 0) {
@@ -1774,16 +1783,22 @@ function FewchursBoardDialog({
1774
1783
  var import_react17 = require("react");
1775
1784
  var import_react_dom = require("react-dom");
1776
1785
  var import_jsx_runtime13 = require("react/jsx-runtime");
1786
+ function launcherClasses(floating) {
1787
+ if (!floating) return "fw-launcher";
1788
+ const side = floating === "left" ? " fw-launcher--left" : "";
1789
+ return `fw-launcher fw-launcher--floating${side}`;
1790
+ }
1777
1791
  function FewchursButton({
1778
1792
  children = "Feedback",
1779
1793
  className,
1780
1794
  style,
1781
1795
  ariaLabel,
1796
+ floating = false,
1782
1797
  ...board
1783
1798
  }) {
1784
1799
  const [open, setOpen] = (0, import_react17.useState)(false);
1785
1800
  const close = (0, import_react17.useCallback)(() => setOpen(false), []);
1786
- const classes = [board.unstyled ? "" : "fw-launcher", className].filter(Boolean).join(" ");
1801
+ const classes = [board.unstyled ? "" : launcherClasses(floating), className].filter(Boolean).join(" ");
1787
1802
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1788
1803
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1789
1804
  "button",