@youasked/react 0.5.0 → 0.6.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
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/YouAsked.tsx
4
- import { useCallback as useCallback2, useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
4
+ import { useCallback as useCallback3, useEffect as useEffect4, useMemo, useRef as useRef4, useState as useState4, useSyncExternalStore } from "react";
5
5
  import { createPortal } from "react-dom";
6
6
 
7
7
  // src/client.ts
@@ -120,7 +120,7 @@ var DAY = 24 * 60 * MIN;
120
120
  var uploads = /* @__PURE__ */ new Map();
121
121
  var wait = (ms = 380) => new Promise((r) => setTimeout(r, ms + Math.random() * ms * 0.5));
122
122
  var WORDS = (s) => new Set(s.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length > 2));
123
- function createDemoClient(appName = "Acme") {
123
+ function createDemoClient(appName = "this app") {
124
124
  const t0 = Date.now();
125
125
  let seq = 100;
126
126
  const listeners = /* @__PURE__ */ new Set();
@@ -147,31 +147,31 @@ function createDemoClient(appName = "Acme") {
147
147
  });
148
148
  const team = (id, body, ago2) => ({ id, body, team: true, author: null, mine: false, createdAt: t0 - ago2 });
149
149
  const store = [
150
- seed(12, "Split a bill with my partner", "We share groceries and rent. Would love to tag an expense as 50/50 and see who owes who.", 14, "planned", {
150
+ seed(12, "Dark mode", "Easier on the eyes at night, and it'd match the rest of my phone.", 14, "planned", {
151
151
  comments_: [
152
- { id: "c1", body: "Yes! Even just splitting one expense would help.", team: false, author: "Raj", mine: false, createdAt: t0 - 3 * DAY },
153
- team("c2", "On the list for December. Would a simple \u201Cwho owes who\u201D total be enough to start?", 2 * DAY)
152
+ { id: "c1", body: "Yes please. I use it every night.", team: false, author: "Raj", mine: false, createdAt: t0 - 3 * DAY },
153
+ team("c2", "On the list for December. Would following your phone's setting be enough to start?", 2 * DAY)
154
154
  ]
155
155
  }),
156
- seed(13, "Monthly budget per category", "Set $400 for food and get a heads-up when I'm close.", 11, "in_progress"),
157
- seed(7, "Dark mode for the charts", "", 8, "shipped", {
158
- shipNote: "Charts now follow your theme. Settings \u2192 Appearance.",
156
+ seed(13, "Export to CSV", "So I can open everything in a spreadsheet.", 11, "in_progress"),
157
+ seed(7, "Keyboard shortcuts", "", 8, "shipped", {
158
+ shipNote: "Press ? anywhere to see them all.",
159
159
  shippedAt: t0 - 2 * DAY,
160
160
  creditName: "Sam"
161
161
  }),
162
- seed(14, "Import my bank statement PDF", "Some of my older expenses never came through email.", 6, "open"),
163
- seed(15, "Recurring expenses (Netflix, rent)", "", 4, "open"),
164
- seed(16, "Widget for the home screen", "Just today's total would be enough.", 3, "open"),
165
- seed(9, "Show which card I paid with", "", 5, "shipped", {
166
- shipNote: "Each expense now shows the card's last 4 digits.",
162
+ seed(14, "Offline mode", "I use it on the train and keep losing signal.", 6, "open"),
163
+ seed(15, "Share a link with a friend", "", 4, "open"),
164
+ seed(16, "Widget for the home screen", "Just today's number would be enough.", 3, "open"),
165
+ seed(9, "Sign in with Apple", "", 5, "shipped", {
166
+ shipNote: "You can now sign in with your Apple ID.",
167
167
  shippedAt: t0 - 4 * 60 * MIN,
168
168
  mine: true,
169
169
  voted: true
170
170
  }),
171
- seed(17, "Export expenses to Excel", "For my accountant at tax time.", 2, "open", {
171
+ seed(17, "A reminder the day before", "A nudge the day before something is due would do.", 2, "open", {
172
172
  mine: true,
173
173
  voted: true,
174
- comments_: [team("c3", "Good one. Would a CSV that opens in Excel work, or do you need .xlsx?", 3 * 60 * MIN)]
174
+ comments_: [team("c3", "Good one. Would a push notification work, or would you rather get an email?", 3 * 60 * MIN)]
175
175
  })
176
176
  ];
177
177
  const find = (id) => store.find((r) => r.id === id);
@@ -344,11 +344,120 @@ var IconSpark = () => /* @__PURE__ */ jsxs("svg", { ...base, children: [
344
344
  /* @__PURE__ */ jsx("path", { d: "m12 3 1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9Z" }),
345
345
  /* @__PURE__ */ jsx("path", { d: "M19 16v4M17 18h4" })
346
346
  ] });
347
- var IconIdea = () => /* @__PURE__ */ jsxs("svg", { ...base, children: [
348
- /* @__PURE__ */ jsx("path", { d: "M12 3.5c-4.97 0-9 3.47-9 7.75 0 2.3 1.17 4.37 3.03 5.8L5.2 20.5l4.1-2.06c.86.2 1.76.31 2.7.31 4.97 0 9-3.47 9-7.75S16.97 3.5 12 3.5Z" }),
349
- /* @__PURE__ */ jsx("path", { d: "M8.2 13.2 12 9.4l3.8 3.8", strokeWidth: 2.6 })
347
+ var IconIdea = ({ ink = "var(--_bg)" }) => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: [
348
+ /* @__PURE__ */ jsx("path", { d: "M6 2.25h12a4.5 4.5 0 0 1 4.5 4.5V15a4.5 4.5 0 0 1-4.5 4.5h-6.75L6 23.25V19.5A4.5 4.5 0 0 1 1.5 15V6.75A4.5 4.5 0 0 1 6 2.25Z", fill: "currentColor" }),
349
+ /* @__PURE__ */ jsx("path", { d: "M7.9 13.9 12 9.8l4.1 4.1", fill: "none", stroke: ink, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round" })
350
350
  ] });
351
351
 
352
+ // src/nudge.tsx
353
+ import { useCallback, useEffect, useRef, useState } from "react";
354
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
355
+ var NUDGE_DEFAULTS = { everyDays: 7, activeSeconds: 30, skipVisits: 1, message: null, position: "bottom" };
356
+ var DAY2 = 24 * 60 * 60 * 1e3;
357
+ var VISIT_GAP = 30 * 60 * 1e3;
358
+ function resolveNudge(server, prop) {
359
+ if (prop === false) return null;
360
+ if (typeof prop === "object") return { ...NUDGE_DEFAULTS, ...server, ...prop };
361
+ if (prop === true) return server ?? NUDGE_DEFAULTS;
362
+ return server ?? null;
363
+ }
364
+ function load(key) {
365
+ const empty = { visits: 0, lastVisitAt: 0, lastShownAt: 0, lastEngagedAt: 0, dismissals: 0 };
366
+ if (!key) return empty;
367
+ try {
368
+ return { ...empty, ...JSON.parse(localStorage.getItem(key) ?? "{}") };
369
+ } catch {
370
+ return empty;
371
+ }
372
+ }
373
+ function save(key, m) {
374
+ if (!key) return;
375
+ try {
376
+ localStorage.setItem(key, JSON.stringify(m));
377
+ } catch {
378
+ }
379
+ }
380
+ function useNudge(settings, storageKey, blocked) {
381
+ const memory = useRef(null);
382
+ const [show, setShow] = useState(false);
383
+ useEffect(() => {
384
+ if (!settings || memory.current) return;
385
+ const m = load(storageKey);
386
+ const now = Date.now();
387
+ if (now - m.lastVisitAt > VISIT_GAP) m.visits += 1;
388
+ m.lastVisitAt = now;
389
+ memory.current = m;
390
+ save(storageKey, m);
391
+ }, [settings, storageKey]);
392
+ useEffect(() => {
393
+ if (!settings || show) return;
394
+ let active = 0;
395
+ const timer = window.setInterval(() => {
396
+ if (document.visibilityState !== "visible" || blocked) return;
397
+ active += 1;
398
+ if (active < settings.activeSeconds) return;
399
+ window.clearInterval(timer);
400
+ const m = memory.current;
401
+ if (!m) return;
402
+ const now = Date.now();
403
+ const wait2 = settings.everyDays * DAY2 * 2 ** Math.min(m.dismissals, 3);
404
+ const due = !storageKey || m.visits > settings.skipVisits && now - m.lastShownAt >= wait2 && now - m.lastEngagedAt >= wait2;
405
+ if (!due) return;
406
+ m.lastShownAt = now;
407
+ save(storageKey, m);
408
+ setShow(true);
409
+ }, 1e3);
410
+ return () => window.clearInterval(timer);
411
+ }, [settings, storageKey, blocked, show]);
412
+ const engaged = useCallback(() => {
413
+ const m = memory.current;
414
+ if (m) {
415
+ m.lastEngagedAt = Date.now();
416
+ m.dismissals = 0;
417
+ save(storageKey, m);
418
+ }
419
+ setShow(false);
420
+ }, [storageKey]);
421
+ const dismiss = useCallback(() => {
422
+ const m = memory.current;
423
+ if (m) {
424
+ m.dismissals += 1;
425
+ save(storageKey, m);
426
+ }
427
+ setShow(false);
428
+ }, [storageKey]);
429
+ return { show, engaged, dismiss };
430
+ }
431
+ function NudgeToast({
432
+ settings,
433
+ appName,
434
+ position,
435
+ trigger,
436
+ onOpen,
437
+ onDismiss
438
+ }) {
439
+ return /* @__PURE__ */ jsxs2("div", { className: "ya-toast ya-nudge", role: "status", "data-pos": position, "data-trigger": trigger, "data-place": settings.position, children: [
440
+ /* @__PURE__ */ jsxs2("div", { className: "ya-toast-top", children: [
441
+ /* @__PURE__ */ jsxs2("p", { className: "ya-toast-kicker", children: [
442
+ "Help shape ",
443
+ appName
444
+ ] }),
445
+ /* @__PURE__ */ jsx2("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx2(IconClose, {}) })
446
+ ] }),
447
+ /* @__PURE__ */ jsxs2("div", { className: "ya-nudge-body", children: [
448
+ /* @__PURE__ */ jsx2("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(IconIdea, {}) }),
449
+ /* @__PURE__ */ jsxs2("div", { children: [
450
+ /* @__PURE__ */ jsx2("p", { className: "ya-toast-title", children: settings.message ?? `Got an idea for ${appName}?` }),
451
+ /* @__PURE__ */ jsx2("p", { className: "ya-toast-note", children: "Ask for a feature or vote on what others want." })
452
+ ] })
453
+ ] }),
454
+ /* @__PURE__ */ jsxs2("div", { className: "ya-toast-actions", children: [
455
+ /* @__PURE__ */ jsx2("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "Share an idea" }),
456
+ /* @__PURE__ */ jsx2("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Not now" })
457
+ ] })
458
+ ] });
459
+ }
460
+
352
461
  // src/styles.ts
353
462
  var css = `
354
463
  .ya-scope{--_bg:var(--ya-bg);--_fg:var(--ya-fg);--_accent:var(--ya-accent);--_accent-fg:var(--ya-accent-fg);
@@ -579,6 +688,10 @@ box-shadow:0 0 0 1px var(--_border),0 24px 70px rgba(0,0,0,.22);padding-bottom:0
579
688
  .ya-toast .ya-live{margin-top:8px}
580
689
  .ya-live svg{width:15px;height:15px}
581
690
  .ya-toast-note{font-size:13.5px;color:var(--_muted);margin-top:6px;overflow-wrap:anywhere}
691
+ .ya-toast[data-place=top]{top:calc(16px + env(safe-area-inset-top));bottom:auto}
692
+ .ya-nudge-body{display:flex;gap:12px;align-items:flex-start;margin-top:6px}
693
+ .ya-nudge-body .ya-card-icon{flex:none;margin-top:2px}
694
+ .ya-nudge-body .ya-toast-title{margin-top:0}
582
695
  .ya-toast-actions{display:flex;gap:8px;margin-top:12px}
583
696
  .ya-toast-quote{color:var(--_fg);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
584
697
  .ya-toast .ya-icon-btn{width:30px;height:30px;margin:-6px -6px 0 0;background:none}
@@ -764,13 +877,13 @@ function tokenStyle(t) {
764
877
  }
765
878
 
766
879
  // src/shared.tsx
767
- import { useCallback, useEffect, useRef, useState } from "react";
768
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
880
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
881
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
769
882
  function useVote(client, initial) {
770
- const [state, setState] = useState({ voted: initial.voted, votes: initial.votes });
771
- const busy = useRef(false);
772
- useEffect(() => setState({ voted: initial.voted, votes: initial.votes }), [initial.voted, initial.votes]);
773
- const toggle = useCallback(async () => {
883
+ const [state, setState] = useState2({ voted: initial.voted, votes: initial.votes });
884
+ const busy = useRef2(false);
885
+ useEffect2(() => setState({ voted: initial.voted, votes: initial.votes }), [initial.voted, initial.votes]);
886
+ const toggle = useCallback2(async () => {
774
887
  if (busy.current) return;
775
888
  busy.current = true;
776
889
  const before = state;
@@ -787,7 +900,7 @@ function useVote(client, initial) {
787
900
  }
788
901
  function VoteButton({ client, request, compact }) {
789
902
  const { voted, votes, toggle } = useVote(client, request);
790
- return /* @__PURE__ */ jsxs2(
903
+ return /* @__PURE__ */ jsxs3(
791
904
  "button",
792
905
  {
793
906
  type: "button",
@@ -799,7 +912,7 @@ function VoteButton({ client, request, compact }) {
799
912
  toggle();
800
913
  },
801
914
  children: [
802
- /* @__PURE__ */ jsx2(IconUp, {}),
915
+ /* @__PURE__ */ jsx3(IconUp, {}),
803
916
  votes
804
917
  ]
805
918
  }
@@ -811,9 +924,9 @@ function BigVote({
811
924
  onChange
812
925
  }) {
813
926
  const { voted, votes, toggle } = useVote(client, request);
814
- useEffect(() => onChange?.(voted), [voted, onChange]);
815
- return /* @__PURE__ */ jsxs2("button", { type: "button", className: "ya-bigvote", "aria-pressed": voted, onClick: toggle, children: [
816
- /* @__PURE__ */ jsx2(IconUp, {}),
927
+ useEffect2(() => onChange?.(voted), [voted, onChange]);
928
+ return /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-bigvote", "aria-pressed": voted, onClick: toggle, children: [
929
+ /* @__PURE__ */ jsx3(IconUp, {}),
817
930
  voted ? "Voted" : "Upvote",
818
931
  " \xB7 ",
819
932
  votes
@@ -828,8 +941,8 @@ var STATUS_LABEL = {
828
941
  pending: "Awaiting approval"
829
942
  };
830
943
  function StatusPill({ status }) {
831
- return /* @__PURE__ */ jsxs2("span", { className: "ya-pill", "data-s": status, children: [
832
- status === "shipped" && /* @__PURE__ */ jsx2(IconCheck, {}),
944
+ return /* @__PURE__ */ jsxs3("span", { className: "ya-pill", "data-s": status, children: [
945
+ status === "shipped" && /* @__PURE__ */ jsx3(IconCheck, {}),
833
946
  STATUS_LABEL[status]
834
947
  ] });
835
948
  }
@@ -839,32 +952,32 @@ function RequestRow({
839
952
  onOpen,
840
953
  compact
841
954
  }) {
842
- return /* @__PURE__ */ jsxs2("li", { className: compact ? "ya-row ya-row-sm" : "ya-row", children: [
843
- /* @__PURE__ */ jsx2(VoteButton, { client, request, compact }),
844
- /* @__PURE__ */ jsxs2("button", { type: "button", className: "ya-row-main", onClick: onOpen, children: [
845
- /* @__PURE__ */ jsx2("span", { className: "ya-row-title", children: request.title }),
846
- (request.status !== "open" || request.comments > 0 || request.mine) && /* @__PURE__ */ jsxs2("span", { className: "ya-meta", children: [
847
- request.status !== "open" && /* @__PURE__ */ jsx2(StatusPill, { status: request.status }),
848
- request.comments > 0 && /* @__PURE__ */ jsxs2("span", { children: [
849
- /* @__PURE__ */ jsx2(IconChat, {}),
955
+ return /* @__PURE__ */ jsxs3("li", { className: compact ? "ya-row ya-row-sm" : "ya-row", children: [
956
+ /* @__PURE__ */ jsx3(VoteButton, { client, request, compact }),
957
+ /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-row-main", onClick: onOpen, children: [
958
+ /* @__PURE__ */ jsx3("span", { className: "ya-row-title", children: request.title }),
959
+ (request.status !== "open" || request.comments > 0 || request.mine) && /* @__PURE__ */ jsxs3("span", { className: "ya-meta", children: [
960
+ request.status !== "open" && /* @__PURE__ */ jsx3(StatusPill, { status: request.status }),
961
+ request.comments > 0 && /* @__PURE__ */ jsxs3("span", { children: [
962
+ /* @__PURE__ */ jsx3(IconChat, {}),
850
963
  request.comments
851
964
  ] }),
852
- request.mine && /* @__PURE__ */ jsx2("span", { children: "You asked" })
965
+ request.mine && /* @__PURE__ */ jsx3("span", { children: "You asked" })
853
966
  ] })
854
967
  ] })
855
968
  ] });
856
969
  }
857
970
  function Skeleton({ rows = 3 }) {
858
- return /* @__PURE__ */ jsx2("div", { className: "ya-list", "aria-label": "Loading", role: "status", children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx2("div", { className: "ya-skel" }, i)) });
971
+ return /* @__PURE__ */ jsx3("div", { className: "ya-list", "aria-label": "Loading", role: "status", children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx3("div", { className: "ya-skel" }, i)) });
859
972
  }
860
- function useLoad(load, deps) {
861
- const [data, setData] = useState(null);
862
- const [error, setError] = useState(null);
863
- useEffect(() => {
973
+ function useLoad(load2, deps) {
974
+ const [data, setData] = useState2(null);
975
+ const [error, setError] = useState2(null);
976
+ useEffect2(() => {
864
977
  let alive = true;
865
978
  setData(null);
866
979
  setError(null);
867
- load().then((d) => alive && setData(d)).catch((e) => alive && setError(e instanceof YouAskedError ? e.code : "network"));
980
+ load2().then((d) => alive && setData(d)).catch((e) => alive && setError(e instanceof YouAskedError ? e.code : "network"));
868
981
  return () => {
869
982
  alive = false;
870
983
  };
@@ -904,9 +1017,9 @@ function ago(t) {
904
1017
  return new Date(t).toLocaleDateString(void 0, { month: "short", day: "numeric" });
905
1018
  }
906
1019
  function AppAvatar({ icon, size = 36 }) {
907
- const [failed, setFailed] = useState(false);
1020
+ const [failed, setFailed] = useState2(false);
908
1021
  if (!icon || failed) return null;
909
- return /* @__PURE__ */ jsx2(
1022
+ return /* @__PURE__ */ jsx3(
910
1023
  "img",
911
1024
  {
912
1025
  className: "ya-avatar",
@@ -927,31 +1040,31 @@ function Header({
927
1040
  onClose,
928
1041
  right
929
1042
  }) {
930
- return /* @__PURE__ */ jsxs2("div", { className: onBack ? "ya-head ya-head-back" : "ya-head", children: [
931
- onBack && /* @__PURE__ */ jsx2("button", { type: "button", className: "ya-icon-btn", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx2(IconBack, {}) }),
1043
+ return /* @__PURE__ */ jsxs3("div", { className: onBack ? "ya-head ya-head-back" : "ya-head", children: [
1044
+ onBack && /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-icon-btn", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx3(IconBack, {}) }),
932
1045
  leading,
933
- /* @__PURE__ */ jsxs2("div", { className: "ya-head-text", children: [
934
- /* @__PURE__ */ jsx2("h2", { className: "ya-h", children: title }),
935
- subtitle && /* @__PURE__ */ jsx2("p", { className: "ya-sub", children: subtitle })
1046
+ /* @__PURE__ */ jsxs3("div", { className: "ya-head-text", children: [
1047
+ /* @__PURE__ */ jsx3("h2", { className: "ya-h", children: title }),
1048
+ subtitle && /* @__PURE__ */ jsx3("p", { className: "ya-sub", children: subtitle })
936
1049
  ] }),
937
1050
  right,
938
- onClose && /* @__PURE__ */ jsx2("button", { type: "button", className: "ya-icon-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx2(IconClose, {}) })
1051
+ onClose && /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-icon-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx3(IconClose, {}) })
939
1052
  ] });
940
1053
  }
941
1054
 
942
1055
  // src/views.tsx
943
- import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
944
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1056
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
1057
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
945
1058
  function Navigator({ route, setRoute, onClose }) {
946
1059
  switch (route.view) {
947
1060
  case "home":
948
- return /* @__PURE__ */ jsx3(Home, { route, setRoute, onClose }, `${route.draft ?? ""}${route.focus ? "f" : ""}${route.topic ?? ""}`);
1061
+ return /* @__PURE__ */ jsx4(Home, { route, setRoute, onClose }, `${route.draft ?? ""}${route.focus ? "f" : ""}${route.topic ?? ""}`);
949
1062
  case "board":
950
- return /* @__PURE__ */ jsx3(Board, { initialTab: route.tab, setRoute, onClose });
1063
+ return /* @__PURE__ */ jsx4(Board, { initialTab: route.tab, setRoute, onClose });
951
1064
  case "detail":
952
- return /* @__PURE__ */ jsx3(Detail, { id: route.id, setRoute, onClose }, route.id);
1065
+ return /* @__PURE__ */ jsx4(Detail, { id: route.id, from: route.from, setRoute, onClose }, route.id);
953
1066
  case "mine":
954
- return /* @__PURE__ */ jsx3(Mine, { setRoute, onClose });
1067
+ return /* @__PURE__ */ jsx4(Mine, { setRoute, onClose });
955
1068
  }
956
1069
  }
957
1070
  function splitMessage(text) {
@@ -963,23 +1076,23 @@ function splitMessage(text) {
963
1076
  return { title, body: t };
964
1077
  }
965
1078
  function ReplyBubble({ notice, appName, onOpen }) {
966
- return /* @__PURE__ */ jsxs3("div", { className: "ya-bubble ya-bubble-in", children: [
967
- /* @__PURE__ */ jsxs3("span", { className: "ya-bubble-kicker", children: [
1079
+ return /* @__PURE__ */ jsxs4("div", { className: "ya-bubble ya-bubble-in", children: [
1080
+ /* @__PURE__ */ jsxs4("span", { className: "ya-bubble-kicker", children: [
968
1081
  appName,
969
1082
  " replied about ",
970
1083
  notice.title
971
1084
  ] }),
972
- /* @__PURE__ */ jsx3("span", { children: notice.reply }),
973
- /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-bubble-link", onClick: onOpen, children: "Reply" })
1085
+ /* @__PURE__ */ jsx4("span", { children: notice.reply }),
1086
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-bubble-link", onClick: onOpen, children: "Reply" })
974
1087
  ] });
975
1088
  }
976
1089
  var MAX_SHOTS = 3;
977
1090
  function Confetti() {
978
1091
  const colors = ["var(--_accent)", "var(--_green)", "var(--_amber)", "#ff7eb3"];
979
- return /* @__PURE__ */ jsx3("span", { className: "ya-confetti", "aria-hidden": "true", children: Array.from({ length: 14 }, (_, i) => {
1092
+ return /* @__PURE__ */ jsx4("span", { className: "ya-confetti", "aria-hidden": "true", children: Array.from({ length: 14 }, (_, i) => {
980
1093
  const angle = Math.PI * (0.15 + i / 13 * 0.7) % Math.PI;
981
1094
  const dist = 38 + i % 4 * 14;
982
- return /* @__PURE__ */ jsx3(
1095
+ return /* @__PURE__ */ jsx4(
983
1096
  "i",
984
1097
  {
985
1098
  style: {
@@ -998,33 +1111,33 @@ function Home({ route, setRoute, onClose }) {
998
1111
  const { client, config, appName, appIcon, greeting, markSeen, whatsNew, dismissWhatsNew, pointAtIt } = useInternal();
999
1112
  const top = useLoad(() => client.list("top", "active"), [client]);
1000
1113
  const shipped = useLoad(() => client.list("new", "shipped"), [client]);
1001
- const [text, setText] = useState2(route.draft ?? "");
1002
- const [thread, setThread] = useState2([]);
1003
- const [similar, setSimilar] = useState2([]);
1004
- const [notices] = useState2(() => config?.unseen ?? []);
1005
- const [news] = useState2(() => whatsNew);
1006
- const [shots, setShots] = useState2([]);
1007
- const [shotError, setShotError] = useState2(null);
1008
- const [credit, setCredit] = useState2(false);
1009
- const urls = useRef2([]);
1010
- const inputRef = useRef2(null);
1011
- const bodyRef = useRef2(null);
1114
+ const [text, setText] = useState3(route.draft ?? "");
1115
+ const [thread, setThread] = useState3([]);
1116
+ const [similar, setSimilar] = useState3([]);
1117
+ const [notices] = useState3(() => config?.unseen ?? []);
1118
+ const [news] = useState3(() => whatsNew);
1119
+ const [shots, setShots] = useState3([]);
1120
+ const [shotError, setShotError] = useState3(null);
1121
+ const [credit, setCredit] = useState3(false);
1122
+ const urls = useRef3([]);
1123
+ const inputRef = useRef3(null);
1124
+ const bodyRef = useRef3(null);
1012
1125
  const sending = thread.some((t) => t.kind === "typing");
1013
- useEffect2(() => {
1126
+ useEffect3(() => {
1014
1127
  if (notices.length) markSeen(notices.map((n) => n.id));
1015
1128
  }, [notices, markSeen]);
1016
- useEffect2(() => {
1129
+ useEffect3(() => {
1017
1130
  if (news) dismissWhatsNew();
1018
1131
  }, [news, dismissWhatsNew]);
1019
1132
  const arrived = config?.unseen.filter((n) => n.kind === "reply" && !notices.some((o) => o.id === n.id)) ?? [];
1020
1133
  const arrivedKey = arrived.map((n) => n.id).join(",");
1021
- useEffect2(() => {
1134
+ useEffect3(() => {
1022
1135
  if (!arrived.length) return;
1023
1136
  setThread((th) => [...th, ...arrived.map((notice) => ({ kind: "reply", notice }))]);
1024
1137
  markSeen(arrived.map((n) => n.id));
1025
1138
  }, [arrivedKey]);
1026
- useEffect2(() => () => urls.current.forEach((u) => URL.revokeObjectURL(u)), []);
1027
- useEffect2(() => {
1139
+ useEffect3(() => () => urls.current.forEach((u) => URL.revokeObjectURL(u)), []);
1140
+ useEffect3(() => {
1028
1141
  if (!route.focus) return;
1029
1142
  const t = setTimeout(() => {
1030
1143
  const el = inputRef.current;
@@ -1034,16 +1147,16 @@ function Home({ route, setRoute, onClose }) {
1034
1147
  }, 60);
1035
1148
  return () => clearTimeout(t);
1036
1149
  }, [route.focus]);
1037
- useEffect2(() => {
1150
+ useEffect3(() => {
1038
1151
  const el = inputRef.current;
1039
1152
  if (!el) return;
1040
1153
  el.style.height = "";
1041
1154
  if (text.includes("\n") || el.scrollHeight > el.clientHeight + 2) el.style.height = `${Math.min(el.scrollHeight, 132)}px`;
1042
1155
  }, [text]);
1043
- useEffect2(() => {
1156
+ useEffect3(() => {
1044
1157
  if (thread.length) bodyRef.current?.scrollTo({ top: bodyRef.current.scrollHeight, behavior: "smooth" });
1045
1158
  }, [thread]);
1046
- useEffect2(() => {
1159
+ useEffect3(() => {
1047
1160
  const q = text.trim();
1048
1161
  if (q.length < 4) {
1049
1162
  setSimilar([]);
@@ -1104,106 +1217,106 @@ function Home({ route, setRoute, onClose }) {
1104
1217
  }
1105
1218
  };
1106
1219
  const chatting = thread.length > 0;
1107
- const openRequest = (id) => setRoute({ view: "detail", id });
1220
+ const openRequest = (id) => setRoute({ view: "detail", id, from: "home" });
1108
1221
  const asking = route.topic && route.placeholder ? route.topic : null;
1109
1222
  const placeholder = route.placeholder ?? "Ask for a feature\u2026";
1110
1223
  const yours = news?.items.find((i) => i.mine);
1111
1224
  const listed = new Set(news?.items.map((i) => i.id));
1112
1225
  const shownNotices = notices.filter((n) => !(n.kind === "shipped" && listed.has(n.requestId)));
1113
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
1114
- /* @__PURE__ */ jsx3(
1226
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1227
+ /* @__PURE__ */ jsx4(
1115
1228
  Header,
1116
1229
  {
1117
- leading: /* @__PURE__ */ jsx3(AppAvatar, { icon: appIcon }),
1230
+ leading: /* @__PURE__ */ jsx4(AppAvatar, { icon: appIcon }),
1118
1231
  title: appName,
1119
1232
  subtitle: "Ideas, votes and what's new",
1120
1233
  onClose
1121
1234
  }
1122
1235
  ),
1123
- /* @__PURE__ */ jsxs3("div", { className: "ya-body ya-chat", ref: bodyRef, children: [
1124
- /* @__PURE__ */ jsx3("div", { className: "ya-bubble ya-bubble-in", children: asking ? `Let's talk about ${asking}. What's missing, or what bugs you?` : greeting ?? `Hey! What would make ${appName} better for you?` }),
1125
- news && /* @__PURE__ */ jsxs3("div", { className: yours ? "ya-bubble ya-bubble-in ya-bubble-win ya-bubble-news" : "ya-bubble ya-bubble-in ya-bubble-news", children: [
1126
- yours && /* @__PURE__ */ jsx3(Confetti, {}),
1127
- /* @__PURE__ */ jsx3("span", { className: "ya-bubble-kicker", children: whatsNewHeading(news.total) }),
1128
- /* @__PURE__ */ jsx3("ul", { className: "ya-news", children: news.items.map((i) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs3("button", { type: "button", onClick: () => openRequest(i.id), children: [
1129
- /* @__PURE__ */ jsx3("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx3(IconCheck, {}) }),
1130
- /* @__PURE__ */ jsxs3("span", { className: "ya-news-text", children: [
1131
- /* @__PURE__ */ jsx3("span", { className: "ya-news-title", children: i.title }),
1132
- i.mine && /* @__PURE__ */ jsx3("span", { className: "ya-news-you", children: "You asked for this" })
1236
+ /* @__PURE__ */ jsxs4("div", { className: "ya-body ya-chat", ref: bodyRef, children: [
1237
+ /* @__PURE__ */ jsx4("div", { className: "ya-bubble ya-bubble-in", children: asking ? `Let's talk about ${asking}. What's missing, or what bugs you?` : greeting ?? `Hey! What would make ${appName} better for you?` }),
1238
+ news && /* @__PURE__ */ jsxs4("div", { className: yours ? "ya-bubble ya-bubble-in ya-bubble-win ya-bubble-news" : "ya-bubble ya-bubble-in ya-bubble-news", children: [
1239
+ yours && /* @__PURE__ */ jsx4(Confetti, {}),
1240
+ /* @__PURE__ */ jsx4("span", { className: "ya-bubble-kicker", children: whatsNewHeading(news.total) }),
1241
+ /* @__PURE__ */ jsx4("ul", { className: "ya-news", children: news.items.map((i) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs4("button", { type: "button", onClick: () => openRequest(i.id), children: [
1242
+ /* @__PURE__ */ jsx4("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx4(IconCheck, {}) }),
1243
+ /* @__PURE__ */ jsxs4("span", { className: "ya-news-text", children: [
1244
+ /* @__PURE__ */ jsx4("span", { className: "ya-news-title", children: i.title }),
1245
+ i.mine && /* @__PURE__ */ jsx4("span", { className: "ya-news-you", children: "You asked for this" })
1133
1246
  ] }),
1134
- /* @__PURE__ */ jsx3(IconChevron, {})
1247
+ /* @__PURE__ */ jsx4(IconChevron, {})
1135
1248
  ] }) }, i.id)) }),
1136
- yours && /* @__PURE__ */ jsx3("span", { children: "That one was yours. Thanks for asking." }),
1137
- news.total > news.items.length && /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-bubble-link", onClick: () => setRoute({ view: "board", tab: "shipped" }), children: [
1249
+ yours && /* @__PURE__ */ jsx4("span", { children: "That one was yours. Thanks for asking." }),
1250
+ news.total > news.items.length && /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-bubble-link", onClick: () => setRoute({ view: "board", tab: "shipped" }), children: [
1138
1251
  "See all ",
1139
1252
  news.total
1140
1253
  ] })
1141
1254
  ] }),
1142
1255
  shownNotices.map(
1143
- (n) => n.kind === "reply" ? /* @__PURE__ */ jsx3(ReplyBubble, { notice: n, appName, onOpen: () => openRequest(n.requestId) }, n.id) : /* @__PURE__ */ jsxs3("div", { className: "ya-bubble ya-bubble-in ya-bubble-win", children: [
1144
- /* @__PURE__ */ jsxs3("span", { className: "ya-live", children: [
1145
- /* @__PURE__ */ jsx3(IconCheck, {}),
1256
+ (n) => n.kind === "reply" ? /* @__PURE__ */ jsx4(ReplyBubble, { notice: n, appName, onOpen: () => openRequest(n.requestId) }, n.id) : /* @__PURE__ */ jsxs4("div", { className: "ya-bubble ya-bubble-in ya-bubble-win", children: [
1257
+ /* @__PURE__ */ jsxs4("span", { className: "ya-live", children: [
1258
+ /* @__PURE__ */ jsx4(IconCheck, {}),
1146
1259
  "It's live"
1147
1260
  ] }),
1148
- /* @__PURE__ */ jsxs3("span", { children: [
1261
+ /* @__PURE__ */ jsxs4("span", { children: [
1149
1262
  "You asked for ",
1150
- /* @__PURE__ */ jsx3("b", { children: n.title }),
1263
+ /* @__PURE__ */ jsx4("b", { children: n.title }),
1151
1264
  ". ",
1152
1265
  n.shipNote ?? "Thanks for asking."
1153
1266
  ] }),
1154
- /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-bubble-link", onClick: () => openRequest(n.requestId), children: "See it" })
1267
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-bubble-link", onClick: () => openRequest(n.requestId), children: "See it" })
1155
1268
  ] }, n.id)
1156
1269
  ),
1157
- !chatting && /* @__PURE__ */ jsxs3(Fragment, { children: [
1158
- /* @__PURE__ */ jsx3(Section, { title: "Popular right now", action: "See all", onAction: () => setRoute({ view: "board" }), children: top.error ? /* @__PURE__ */ jsx3("p", { className: "ya-note", children: errorText(top.error) }) : !top.data ? /* @__PURE__ */ jsx3(Skeleton, { rows: 2 }) : top.data.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "ya-note", children: "No requests yet. Yours could be the first." }) : /* @__PURE__ */ jsx3("ul", { className: "ya-list", children: top.data.slice(0, 3).map((r) => /* @__PURE__ */ jsx3(RequestRow, { client, request: r, compact: true, onOpen: () => openRequest(r.id) }, r.id)) }) }),
1159
- shipped.data && shipped.data.length > 0 && /* @__PURE__ */ jsx3(Section, { title: "Recently shipped", action: "All", onAction: () => setRoute({ view: "board", tab: "shipped" }), children: /* @__PURE__ */ jsx3("ul", { className: "ya-shipped", children: shipped.data.slice(0, 3).map((r) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs3("button", { type: "button", onClick: () => openRequest(r.id), children: [
1160
- /* @__PURE__ */ jsx3("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx3(IconCheck, {}) }),
1161
- /* @__PURE__ */ jsx3("span", { className: "ya-shipped-title", children: r.title }),
1162
- /* @__PURE__ */ jsx3("span", { className: "ya-shipped-when", children: r.shippedAt ? ago(r.shippedAt) : "" })
1270
+ !chatting && /* @__PURE__ */ jsxs4(Fragment, { children: [
1271
+ /* @__PURE__ */ jsx4(Section, { title: "Popular right now", action: "See all", onAction: () => setRoute({ view: "board" }), children: top.error ? /* @__PURE__ */ jsx4("p", { className: "ya-note", children: errorText(top.error) }) : !top.data ? /* @__PURE__ */ jsx4(Skeleton, { rows: 2 }) : top.data.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "ya-note", children: "No requests yet. Yours could be the first." }) : /* @__PURE__ */ jsx4("ul", { className: "ya-list", children: top.data.slice(0, 3).map((r) => /* @__PURE__ */ jsx4(RequestRow, { client, request: r, compact: true, onOpen: () => openRequest(r.id) }, r.id)) }) }),
1272
+ shipped.data && shipped.data.length > 0 && /* @__PURE__ */ jsx4(Section, { title: "Recently shipped", action: "All", onAction: () => setRoute({ view: "board", tab: "shipped" }), children: /* @__PURE__ */ jsx4("ul", { className: "ya-shipped", children: shipped.data.slice(0, 3).map((r) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs4("button", { type: "button", onClick: () => openRequest(r.id), children: [
1273
+ /* @__PURE__ */ jsx4("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx4(IconCheck, {}) }),
1274
+ /* @__PURE__ */ jsx4("span", { className: "ya-shipped-title", children: r.title }),
1275
+ /* @__PURE__ */ jsx4("span", { className: "ya-shipped-when", children: r.shippedAt ? ago(r.shippedAt) : "" })
1163
1276
  ] }) }, r.id)) }) })
1164
1277
  ] }),
1165
1278
  thread.map(
1166
- (t, i) => t.kind === "out" ? /* @__PURE__ */ jsxs3("div", { className: "ya-bubble ya-bubble-out", children: [
1167
- t.images?.map((src) => /* @__PURE__ */ jsx3("img", { className: "ya-bubble-img", src, alt: "Your screenshot" }, src)),
1279
+ (t, i) => t.kind === "out" ? /* @__PURE__ */ jsxs4("div", { className: "ya-bubble ya-bubble-out", children: [
1280
+ t.images?.map((src) => /* @__PURE__ */ jsx4("img", { className: "ya-bubble-img", src, alt: "Your screenshot" }, src)),
1168
1281
  t.text
1169
- ] }, i) : t.kind === "typing" ? /* @__PURE__ */ jsxs3("div", { className: "ya-bubble ya-bubble-in ya-typing", "aria-label": "Posting", children: [
1170
- /* @__PURE__ */ jsx3("span", {}),
1171
- /* @__PURE__ */ jsx3("span", {}),
1172
- /* @__PURE__ */ jsx3("span", {})
1173
- ] }, i) : t.kind === "reply" ? /* @__PURE__ */ jsx3(ReplyBubble, { notice: t.notice, appName, onOpen: () => openRequest(t.notice.requestId) }, i) : t.kind === "posted" ? /* @__PURE__ */ jsxs3("div", { className: "ya-bubble ya-bubble-in", children: [
1174
- /* @__PURE__ */ jsxs3("span", { children: [
1282
+ ] }, i) : t.kind === "typing" ? /* @__PURE__ */ jsxs4("div", { className: "ya-bubble ya-bubble-in ya-typing", "aria-label": "Posting", children: [
1283
+ /* @__PURE__ */ jsx4("span", {}),
1284
+ /* @__PURE__ */ jsx4("span", {}),
1285
+ /* @__PURE__ */ jsx4("span", {})
1286
+ ] }, i) : t.kind === "reply" ? /* @__PURE__ */ jsx4(ReplyBubble, { notice: t.notice, appName, onOpen: () => openRequest(t.notice.requestId) }, i) : t.kind === "posted" ? /* @__PURE__ */ jsxs4("div", { className: "ya-bubble ya-bubble-in", children: [
1287
+ /* @__PURE__ */ jsxs4("span", { children: [
1175
1288
  "Got it. ",
1176
- /* @__PURE__ */ jsx3("b", { children: t.request.title }),
1289
+ /* @__PURE__ */ jsx4("b", { children: t.request.title }),
1177
1290
  " is on the board, and we'll tell you right here when it ships."
1178
1291
  ] }),
1179
- /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-bubble-link", onClick: () => openRequest(t.request.id), children: "View request" })
1180
- ] }, i) : /* @__PURE__ */ jsx3("div", { className: "ya-bubble ya-bubble-in ya-bubble-error", role: "alert", children: t.text }, i)
1292
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-bubble-link", onClick: () => openRequest(t.request.id), children: "View request" })
1293
+ ] }, i) : /* @__PURE__ */ jsx4("div", { className: "ya-bubble ya-bubble-in ya-bubble-error", role: "alert", children: t.text }, i)
1181
1294
  ),
1182
- chatting && !sending && /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-chip", onClick: () => setRoute({ view: "board" }), children: "See what others asked for" })
1295
+ chatting && !sending && /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-chip", onClick: () => setRoute({ view: "board" }), children: "See what others asked for" })
1183
1296
  ] }),
1184
- /* @__PURE__ */ jsxs3("div", { className: "ya-composer-wrap", children: [
1185
- similar.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "ya-tray", "aria-live": "polite", children: [
1186
- /* @__PURE__ */ jsx3("p", { className: "ya-tray-h", children: "Sounds like one of these. Vote instead?" }),
1187
- /* @__PURE__ */ jsx3("ul", { className: "ya-list", children: similar.map((r) => /* @__PURE__ */ jsx3(RequestRow, { client, request: r, compact: true, onOpen: () => openRequest(r.id) }, r.id)) })
1297
+ /* @__PURE__ */ jsxs4("div", { className: "ya-composer-wrap", children: [
1298
+ similar.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "ya-tray", "aria-live": "polite", children: [
1299
+ /* @__PURE__ */ jsx4("p", { className: "ya-tray-h", children: "Sounds like one of these. Vote instead?" }),
1300
+ /* @__PURE__ */ jsx4("ul", { className: "ya-list", children: similar.map((r) => /* @__PURE__ */ jsx4(RequestRow, { client, request: r, compact: true, onOpen: () => openRequest(r.id) }, r.id)) })
1188
1301
  ] }),
1189
- shots.length > 0 && /* @__PURE__ */ jsx3("ul", { className: "ya-shots", "aria-label": "Screenshots", children: shots.map((s, i) => /* @__PURE__ */ jsxs3("li", { className: "ya-shot", children: [
1190
- /* @__PURE__ */ jsx3("img", { src: s.url, alt: "" }),
1191
- /* @__PURE__ */ jsxs3("span", { children: [
1302
+ shots.length > 0 && /* @__PURE__ */ jsx4("ul", { className: "ya-shots", "aria-label": "Screenshots", children: shots.map((s, i) => /* @__PURE__ */ jsxs4("li", { className: "ya-shot", children: [
1303
+ /* @__PURE__ */ jsx4("img", { src: s.url, alt: "" }),
1304
+ /* @__PURE__ */ jsxs4("span", { children: [
1192
1305
  "Screenshot",
1193
1306
  shots.length > 1 ? ` ${i + 1}` : ""
1194
1307
  ] }),
1195
- /* @__PURE__ */ jsx3(
1308
+ /* @__PURE__ */ jsx4(
1196
1309
  "button",
1197
1310
  {
1198
1311
  type: "button",
1199
1312
  className: "ya-shot-x",
1200
1313
  "aria-label": `Remove screenshot${shots.length > 1 ? ` ${i + 1}` : ""}`,
1201
1314
  onClick: () => setShots((all) => all.filter((x) => x !== s)),
1202
- children: /* @__PURE__ */ jsx3(IconClose, {})
1315
+ children: /* @__PURE__ */ jsx4(IconClose, {})
1203
1316
  }
1204
1317
  )
1205
1318
  ] }, s.url)) }),
1206
- /* @__PURE__ */ jsxs3(
1319
+ /* @__PURE__ */ jsxs4(
1207
1320
  "form",
1208
1321
  {
1209
1322
  className: "ya-composer",
@@ -1212,7 +1325,7 @@ function Home({ route, setRoute, onClose }) {
1212
1325
  send();
1213
1326
  },
1214
1327
  children: [
1215
- /* @__PURE__ */ jsx3(
1328
+ /* @__PURE__ */ jsx4(
1216
1329
  "textarea",
1217
1330
  {
1218
1331
  ref: inputRef,
@@ -1231,12 +1344,12 @@ function Home({ route, setRoute, onClose }) {
1231
1344
  }
1232
1345
  }
1233
1346
  ),
1234
- /* @__PURE__ */ jsx3("button", { type: "submit", className: "ya-send", disabled: text.trim().length < 3 || sending, "aria-label": "Send", children: /* @__PURE__ */ jsx3(IconSend, {}) })
1347
+ /* @__PURE__ */ jsx4("button", { type: "submit", className: "ya-send", disabled: text.trim().length < 3 || sending, "aria-label": "Send", children: /* @__PURE__ */ jsx4(IconSend, {}) })
1235
1348
  ]
1236
1349
  }
1237
1350
  ),
1238
- /* @__PURE__ */ jsxs3("div", { className: "ya-tools", children: [
1239
- /* @__PURE__ */ jsxs3(
1351
+ /* @__PURE__ */ jsxs4("div", { className: "ya-tools", children: [
1352
+ /* @__PURE__ */ jsxs4(
1240
1353
  "button",
1241
1354
  {
1242
1355
  type: "button",
@@ -1246,18 +1359,18 @@ function Home({ route, setRoute, onClose }) {
1246
1359
  onFocus: () => void import("./capture-FYZGL54F.js"),
1247
1360
  disabled: sending || shots.length >= MAX_SHOTS,
1248
1361
  children: [
1249
- /* @__PURE__ */ jsx3(IconFrame, {}),
1362
+ /* @__PURE__ */ jsx4(IconFrame, {}),
1250
1363
  "Show us"
1251
1364
  ]
1252
1365
  }
1253
1366
  ),
1254
- config?.canCredit && text.trim().length > 0 && /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-switch-row", role: "switch", "aria-checked": credit, onClick: () => setCredit((c) => !c), children: [
1367
+ config?.canCredit && text.trim().length > 0 && /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-switch-row", role: "switch", "aria-checked": credit, onClick: () => setCredit((c) => !c), children: [
1255
1368
  "Credit me when it ships",
1256
- /* @__PURE__ */ jsx3("span", { className: "ya-switch", "aria-hidden": "true" })
1369
+ /* @__PURE__ */ jsx4("span", { className: "ya-switch", "aria-hidden": "true" })
1257
1370
  ] })
1258
1371
  ] }),
1259
- shotError && /* @__PURE__ */ jsx3("p", { className: "ya-note", role: "alert", children: shotError }),
1260
- config?.watermark && /* @__PURE__ */ jsx3("p", { className: "ya-mark", children: "Feedback by YouAsked" })
1372
+ shotError && /* @__PURE__ */ jsx4("p", { className: "ya-note", role: "alert", children: shotError }),
1373
+ config?.watermark && /* @__PURE__ */ jsx4("p", { className: "ya-mark", children: "Feedback by YouAsked" })
1261
1374
  ] })
1262
1375
  ] });
1263
1376
  }
@@ -1267,12 +1380,12 @@ function Section({
1267
1380
  onAction,
1268
1381
  children
1269
1382
  }) {
1270
- return /* @__PURE__ */ jsxs3("section", { className: "ya-section", children: [
1271
- /* @__PURE__ */ jsxs3("div", { className: "ya-section-head", children: [
1272
- /* @__PURE__ */ jsx3("h3", { children: title }),
1273
- action && /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-link", onClick: onAction, children: [
1383
+ return /* @__PURE__ */ jsxs4("section", { className: "ya-section", children: [
1384
+ /* @__PURE__ */ jsxs4("div", { className: "ya-section-head", children: [
1385
+ /* @__PURE__ */ jsx4("h3", { children: title }),
1386
+ action && /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-link", onClick: onAction, children: [
1274
1387
  action,
1275
- /* @__PURE__ */ jsx3(IconChevron, {})
1388
+ /* @__PURE__ */ jsx4(IconChevron, {})
1276
1389
  ] })
1277
1390
  ] }),
1278
1391
  children
@@ -1289,36 +1402,36 @@ function Board({
1289
1402
  onClose
1290
1403
  }) {
1291
1404
  const { client, title } = useInternal();
1292
- const [tab, setTab] = useState2(TABS.find((t) => t.key === initialTab) ?? TABS[0]);
1405
+ const [tab, setTab] = useState3(TABS.find((t) => t.key === initialTab) ?? TABS[0]);
1293
1406
  const { data, error } = useLoad(() => client.list(tab.sort, tab.status), [client, tab.key]);
1294
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
1295
- /* @__PURE__ */ jsx3(
1407
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1408
+ /* @__PURE__ */ jsx4(
1296
1409
  Header,
1297
1410
  {
1298
1411
  title,
1299
1412
  onBack: () => setRoute({ view: "home" }),
1300
1413
  onClose,
1301
- right: /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-link", onClick: () => setRoute({ view: "mine" }), children: "Yours" })
1414
+ right: /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-link", onClick: () => setRoute({ view: "mine" }), children: "Yours" })
1302
1415
  }
1303
1416
  ),
1304
- /* @__PURE__ */ jsx3("div", { className: "ya-tabs", role: "tablist", "aria-label": "Sort requests", children: TABS.map((t) => /* @__PURE__ */ jsx3("button", { type: "button", role: "tab", className: "ya-tab", "aria-selected": tab.key === t.key, onClick: () => setTab(t), children: t.label }, t.key)) }),
1305
- /* @__PURE__ */ jsx3("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx3("p", { className: "ya-empty", children: errorText(error) }) : !data ? /* @__PURE__ */ jsx3(Skeleton, {}) : data.length === 0 ? /* @__PURE__ */ jsxs3("div", { className: "ya-empty", children: [
1306
- /* @__PURE__ */ jsx3("b", { children: tab.key === "shipped" ? "Nothing shipped yet" : "No requests yet" }),
1417
+ /* @__PURE__ */ jsx4("div", { className: "ya-tabs", role: "tablist", "aria-label": "Sort requests", children: TABS.map((t) => /* @__PURE__ */ jsx4("button", { type: "button", role: "tab", className: "ya-tab", "aria-selected": tab.key === t.key, onClick: () => setTab(t), children: t.label }, t.key)) }),
1418
+ /* @__PURE__ */ jsx4("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx4("p", { className: "ya-empty", children: errorText(error) }) : !data ? /* @__PURE__ */ jsx4(Skeleton, {}) : data.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "ya-empty", children: [
1419
+ /* @__PURE__ */ jsx4("b", { children: tab.key === "shipped" ? "Nothing shipped yet" : "No requests yet" }),
1307
1420
  tab.key === "shipped" ? "Requests show up here once they're live." : "Tell us what you'd like next. Others can vote on it."
1308
- ] }) : /* @__PURE__ */ jsx3("ul", { className: "ya-list", children: data.map((r) => /* @__PURE__ */ jsx3(RequestRow, { client, request: r, onOpen: () => setRoute({ view: "detail", id: r.id }) }, r.id)) }) }),
1309
- /* @__PURE__ */ jsx3("div", { className: "ya-foot", children: /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-btn", onClick: () => setRoute({ view: "home", focus: true }), children: [
1310
- /* @__PURE__ */ jsx3(IconPlus, {}),
1421
+ ] }) : /* @__PURE__ */ jsx4("ul", { className: "ya-list", children: data.map((r) => /* @__PURE__ */ jsx4(RequestRow, { client, request: r, onOpen: () => setRoute({ view: "detail", id: r.id, from: "board" }) }, r.id)) }) }),
1422
+ /* @__PURE__ */ jsx4("div", { className: "ya-foot", children: /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-btn", onClick: () => setRoute({ view: "home", focus: true }), children: [
1423
+ /* @__PURE__ */ jsx4(IconPlus, {}),
1311
1424
  "Request a feature"
1312
1425
  ] }) })
1313
1426
  ] });
1314
1427
  }
1315
- function Detail({ id, setRoute, onClose }) {
1428
+ function Detail({ id, from, setRoute, onClose }) {
1316
1429
  const { client, config, markSeen, appName, appIcon } = useInternal();
1317
1430
  const { data, error, setData } = useLoad(() => client.get(id), [client, id]);
1318
1431
  const unseenHere = config?.unseen.filter((n) => n.requestId === id).map((n) => n.id).join(",") ?? "";
1319
- const loaded = useRef2(false);
1432
+ const loaded = useRef3(false);
1320
1433
  loaded.current = Boolean(data);
1321
- useEffect2(() => {
1434
+ useEffect3(() => {
1322
1435
  if (!unseenHere) return;
1323
1436
  markSeen(unseenHere.split(","));
1324
1437
  if (loaded.current) {
@@ -1326,15 +1439,15 @@ function Detail({ id, setRoute, onClose }) {
1326
1439
  });
1327
1440
  }
1328
1441
  }, [unseenHere, markSeen]);
1329
- const [reply, setReply] = useState2("");
1330
- const [sending, setSending] = useState2(false);
1331
- const [replyError, setReplyError] = useState2(null);
1332
- const [voted, setVoted] = useState2(null);
1333
- const [early, setEarly] = useState2(false);
1334
- useEffect2(() => setEarly(Boolean(data?.earlyAccess)), [data?.earlyAccess]);
1335
- const [confirmDelete, setConfirmDelete] = useState2(false);
1336
- const [deleting, setDeleting] = useState2(false);
1337
- const [deleteError, setDeleteError] = useState2(null);
1442
+ const [reply, setReply] = useState3("");
1443
+ const [sending, setSending] = useState3(false);
1444
+ const [replyError, setReplyError] = useState3(null);
1445
+ const [voted, setVoted] = useState3(null);
1446
+ const [early, setEarly] = useState3(false);
1447
+ useEffect3(() => setEarly(Boolean(data?.earlyAccess)), [data?.earlyAccess]);
1448
+ const [confirmDelete, setConfirmDelete] = useState3(false);
1449
+ const [deleting, setDeleting] = useState3(false);
1450
+ const [deleteError, setDeleteError] = useState3(null);
1338
1451
  const remove = async () => {
1339
1452
  if (!data?.request || deleting) return;
1340
1453
  setDeleting(true);
@@ -1357,7 +1470,7 @@ function Detail({ id, setRoute, onClose }) {
1357
1470
  setEarly(before);
1358
1471
  }
1359
1472
  };
1360
- useEffect2(() => {
1473
+ useEffect3(() => {
1361
1474
  if (data?.redirect) setRoute({ view: "detail", id: data.redirect });
1362
1475
  }, [data?.redirect, setRoute]);
1363
1476
  const request = data?.request;
@@ -1377,58 +1490,58 @@ function Detail({ id, setRoute, onClose }) {
1377
1490
  setSending(false);
1378
1491
  }
1379
1492
  };
1380
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
1381
- /* @__PURE__ */ jsx3(Header, { title: "", onBack: () => setRoute({ view: "board" }), onClose }),
1382
- /* @__PURE__ */ jsx3("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx3("p", { className: "ya-empty", children: error === "not_found" ? "This request was removed." : errorText(error) }) : !request ? /* @__PURE__ */ jsx3(Skeleton, {}) : /* @__PURE__ */ jsxs3(Fragment, { children: [
1383
- /* @__PURE__ */ jsxs3("div", { className: "ya-detail-meta", children: [
1384
- request.status !== "open" && /* @__PURE__ */ jsx3(StatusPill, { status: request.status }),
1385
- /* @__PURE__ */ jsxs3("span", { className: "ya-ref", children: [
1493
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1494
+ /* @__PURE__ */ jsx4(Header, { title: "", onBack: () => setRoute({ view: from ?? "board" }), onClose }),
1495
+ /* @__PURE__ */ jsx4("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx4("p", { className: "ya-empty", children: error === "not_found" ? "This request was removed." : errorText(error) }) : !request ? /* @__PURE__ */ jsx4(Skeleton, {}) : /* @__PURE__ */ jsxs4(Fragment, { children: [
1496
+ /* @__PURE__ */ jsxs4("div", { className: "ya-detail-meta", children: [
1497
+ request.status !== "open" && /* @__PURE__ */ jsx4(StatusPill, { status: request.status }),
1498
+ /* @__PURE__ */ jsxs4("span", { className: "ya-ref", children: [
1386
1499
  "YA-",
1387
1500
  request.number
1388
1501
  ] })
1389
1502
  ] }),
1390
- /* @__PURE__ */ jsx3("h3", { className: "ya-detail-title", children: request.title }),
1391
- request.body && request.body !== request.title && /* @__PURE__ */ jsx3("p", { className: "ya-text", children: request.body }),
1392
- data?.attachments && data.attachments.length > 0 && /* @__PURE__ */ jsx3("div", { className: "ya-attachments", children: data.attachments.map((a) => /* @__PURE__ */ jsx3("a", { href: a.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx3("img", { src: a.url, alt: "Screenshot attached to this request", loading: "lazy" }) }, a.id)) }),
1393
- /* @__PURE__ */ jsx3(BigVote, { client, request, onChange: setVoted }),
1394
- (request.status === "planned" || request.status === "in_progress") && (voted ?? request.voted) && /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-early", role: "switch", "aria-checked": early, onClick: toggleEarly, children: [
1395
- /* @__PURE__ */ jsx3("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(IconSpark, {}) }),
1396
- /* @__PURE__ */ jsxs3("span", { className: "ya-menurow-text", children: [
1397
- /* @__PURE__ */ jsx3("span", { className: "ya-menurow-label", children: "Try it early" }),
1398
- /* @__PURE__ */ jsx3("span", { className: "ya-menurow-sub", children: early ? "You're on the list. We'll let you in first." : "Get access before everyone else" })
1503
+ /* @__PURE__ */ jsx4("h3", { className: "ya-detail-title", children: request.title }),
1504
+ request.body && request.body !== request.title && /* @__PURE__ */ jsx4("p", { className: "ya-text", children: request.body }),
1505
+ data?.attachments && data.attachments.length > 0 && /* @__PURE__ */ jsx4("div", { className: "ya-attachments", children: data.attachments.map((a) => /* @__PURE__ */ jsx4("a", { href: a.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx4("img", { src: a.url, alt: "Screenshot attached to this request", loading: "lazy" }) }, a.id)) }),
1506
+ /* @__PURE__ */ jsx4(BigVote, { client, request, onChange: setVoted }),
1507
+ (request.status === "planned" || request.status === "in_progress") && (voted ?? request.voted) && /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-early", role: "switch", "aria-checked": early, onClick: toggleEarly, children: [
1508
+ /* @__PURE__ */ jsx4("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(IconSpark, {}) }),
1509
+ /* @__PURE__ */ jsxs4("span", { className: "ya-menurow-text", children: [
1510
+ /* @__PURE__ */ jsx4("span", { className: "ya-menurow-label", children: "Try it early" }),
1511
+ /* @__PURE__ */ jsx4("span", { className: "ya-menurow-sub", children: early ? "You're on the list. We'll let you in first." : "Get access before everyone else" })
1399
1512
  ] }),
1400
- /* @__PURE__ */ jsx3("span", { className: "ya-switch", "aria-hidden": "true" })
1513
+ /* @__PURE__ */ jsx4("span", { className: "ya-switch", "aria-hidden": "true" })
1401
1514
  ] }),
1402
- request.source && /* @__PURE__ */ jsxs3("p", { className: "ya-note", children: [
1515
+ request.source && /* @__PURE__ */ jsxs4("p", { className: "ya-note", children: [
1403
1516
  "Also asked",
1404
1517
  " ",
1405
- request.sourceUrl ? /* @__PURE__ */ jsx3("a", { href: request.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: request.source === "reddit" ? "on Reddit" : "in App Store reviews" }) : request.source === "reddit" ? "on Reddit" : "in App Store reviews",
1518
+ request.sourceUrl ? /* @__PURE__ */ jsx4("a", { href: request.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: request.source === "reddit" ? "on Reddit" : "in App Store reviews" }) : request.source === "reddit" ? "on Reddit" : "in App Store reviews",
1406
1519
  "."
1407
1520
  ] }),
1408
- request.mine && request.status !== "shipped" && /* @__PURE__ */ jsx3("p", { className: "ya-note", children: "You asked for this. We'll tell you here when it ships." }),
1409
- data?.canDelete && (confirmDelete ? /* @__PURE__ */ jsxs3("p", { className: "ya-note ya-delete-row", children: [
1521
+ request.mine && request.status !== "shipped" && /* @__PURE__ */ jsx4("p", { className: "ya-note", children: "You asked for this. We'll tell you here when it ships." }),
1522
+ data?.canDelete && (confirmDelete ? /* @__PURE__ */ jsxs4("p", { className: "ya-note ya-delete-row", children: [
1410
1523
  "Delete this request? This can't be undone.",
1411
- /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-link ya-link-danger", onClick: remove, disabled: deleting, children: deleting ? "Deleting\u2026" : "Delete" }),
1412
- /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-link", onClick: () => setConfirmDelete(false), disabled: deleting, children: "Keep it" })
1413
- ] }) : /* @__PURE__ */ jsx3("p", { className: "ya-note ya-delete-row", children: /* @__PURE__ */ jsx3("button", { type: "button", className: "ya-link ya-link-quiet", onClick: () => setConfirmDelete(true), children: "Delete my request" }) })),
1414
- deleteError && /* @__PURE__ */ jsx3("p", { className: "ya-note", role: "alert", children: deleteError }),
1415
- request.status === "shipped" && /* @__PURE__ */ jsxs3("div", { className: "ya-callout", "data-tone": "success", children: [
1416
- /* @__PURE__ */ jsx3(IconCheck, {}),
1417
- /* @__PURE__ */ jsxs3("span", { children: [
1418
- /* @__PURE__ */ jsx3("b", { children: "It's live." }),
1524
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-link ya-link-danger", onClick: remove, disabled: deleting, children: deleting ? "Deleting\u2026" : "Delete" }),
1525
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-link", onClick: () => setConfirmDelete(false), disabled: deleting, children: "Keep it" })
1526
+ ] }) : /* @__PURE__ */ jsx4("p", { className: "ya-note ya-delete-row", children: /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-link ya-link-quiet", onClick: () => setConfirmDelete(true), children: "Delete my request" }) })),
1527
+ deleteError && /* @__PURE__ */ jsx4("p", { className: "ya-note", role: "alert", children: deleteError }),
1528
+ request.status === "shipped" && /* @__PURE__ */ jsxs4("div", { className: "ya-callout", "data-tone": "success", children: [
1529
+ /* @__PURE__ */ jsx4(IconCheck, {}),
1530
+ /* @__PURE__ */ jsxs4("span", { children: [
1531
+ /* @__PURE__ */ jsx4("b", { children: "It's live." }),
1419
1532
  request.shipNote ? ` ${request.shipNote}` : " Thanks for asking.",
1420
- request.creditName && /* @__PURE__ */ jsxs3("span", { className: "ya-credit", children: [
1533
+ request.creditName && /* @__PURE__ */ jsxs4("span", { className: "ya-credit", children: [
1421
1534
  "Thanks to ",
1422
1535
  request.creditName,
1423
1536
  " for asking."
1424
1537
  ] })
1425
1538
  ] })
1426
1539
  ] }),
1427
- /* @__PURE__ */ jsx3("p", { className: "ya-section-h", children: "Conversation" }),
1428
- comments.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "ya-text ya-text-muted", children: "No messages yet. Add details or ask a question below." }) : /* @__PURE__ */ jsx3("div", { className: "ya-thread", children: comments.map((c) => /* @__PURE__ */ jsx3(Message, { comment: c, appName, appIcon }, c.id)) })
1540
+ /* @__PURE__ */ jsx4("p", { className: "ya-section-h", children: "Conversation" }),
1541
+ comments.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "ya-text ya-text-muted", children: "No messages yet. Add details or ask a question below." }) : /* @__PURE__ */ jsx4("div", { className: "ya-thread", children: comments.map((c) => /* @__PURE__ */ jsx4(Message, { comment: c, appName, appIcon }, c.id)) })
1429
1542
  ] }) }),
1430
- request && /* @__PURE__ */ jsxs3("form", { className: "ya-composer ya-composer-bar", onSubmit: send, children: [
1431
- /* @__PURE__ */ jsx3(
1543
+ request && /* @__PURE__ */ jsxs4("form", { className: "ya-composer ya-composer-bar", onSubmit: send, children: [
1544
+ /* @__PURE__ */ jsx4(
1432
1545
  "textarea",
1433
1546
  {
1434
1547
  className: "ya-composer-input",
@@ -1446,49 +1559,49 @@ function Detail({ id, setRoute, onClose }) {
1446
1559
  }
1447
1560
  }
1448
1561
  ),
1449
- /* @__PURE__ */ jsx3("button", { type: "submit", className: "ya-send", disabled: !reply.trim() || sending, "aria-label": "Send comment", children: /* @__PURE__ */ jsx3(IconSend, {}) }),
1450
- replyError && /* @__PURE__ */ jsx3("span", { className: "ya-sr", role: "alert", children: replyError })
1562
+ /* @__PURE__ */ jsx4("button", { type: "submit", className: "ya-send", disabled: !reply.trim() || sending, "aria-label": "Send comment", children: /* @__PURE__ */ jsx4(IconSend, {}) }),
1563
+ replyError && /* @__PURE__ */ jsx4("span", { className: "ya-sr", role: "alert", children: replyError })
1451
1564
  ] })
1452
1565
  ] });
1453
1566
  }
1454
1567
  function Message({ comment, appName, appIcon }) {
1455
- const when = /* @__PURE__ */ jsx3("time", { dateTime: new Date(comment.createdAt).toISOString(), children: ago(comment.createdAt) });
1568
+ const when = /* @__PURE__ */ jsx4("time", { dateTime: new Date(comment.createdAt).toISOString(), children: ago(comment.createdAt) });
1456
1569
  if (comment.mine) {
1457
- return /* @__PURE__ */ jsxs3("div", { className: "ya-msg ya-msg-out", children: [
1458
- /* @__PURE__ */ jsx3("div", { className: "ya-bubble ya-bubble-out", children: comment.body }),
1459
- /* @__PURE__ */ jsx3("span", { className: "ya-msg-meta", children: when })
1570
+ return /* @__PURE__ */ jsxs4("div", { className: "ya-msg ya-msg-out", children: [
1571
+ /* @__PURE__ */ jsx4("div", { className: "ya-bubble ya-bubble-out", children: comment.body }),
1572
+ /* @__PURE__ */ jsx4("span", { className: "ya-msg-meta", children: when })
1460
1573
  ] });
1461
1574
  }
1462
- return /* @__PURE__ */ jsxs3("div", { className: "ya-msg", children: [
1463
- comment.team && appIcon ? /* @__PURE__ */ jsx3(AppAvatar, { icon: appIcon, size: 26 }) : null,
1464
- /* @__PURE__ */ jsxs3("div", { className: "ya-msg-body", children: [
1465
- /* @__PURE__ */ jsxs3("span", { className: "ya-msg-meta", children: [
1466
- /* @__PURE__ */ jsx3("b", { children: comment.team ? appName : comment.author || "Someone" }),
1467
- comment.team && /* @__PURE__ */ jsx3("span", { className: "ya-team", children: "Team" }),
1575
+ return /* @__PURE__ */ jsxs4("div", { className: "ya-msg", children: [
1576
+ comment.team && appIcon ? /* @__PURE__ */ jsx4(AppAvatar, { icon: appIcon, size: 26 }) : null,
1577
+ /* @__PURE__ */ jsxs4("div", { className: "ya-msg-body", children: [
1578
+ /* @__PURE__ */ jsxs4("span", { className: "ya-msg-meta", children: [
1579
+ /* @__PURE__ */ jsx4("b", { children: comment.team ? appName : comment.author || "Someone" }),
1580
+ comment.team && /* @__PURE__ */ jsx4("span", { className: "ya-team", children: "Team" }),
1468
1581
  when
1469
1582
  ] }),
1470
- /* @__PURE__ */ jsx3("div", { className: "ya-bubble ya-bubble-in", children: comment.body })
1583
+ /* @__PURE__ */ jsx4("div", { className: "ya-bubble ya-bubble-in", children: comment.body })
1471
1584
  ] })
1472
1585
  ] });
1473
1586
  }
1474
1587
  function Mine({ setRoute, onClose }) {
1475
1588
  const { client } = useInternal();
1476
1589
  const { data, error } = useLoad(() => client.mine(), [client]);
1477
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
1478
- /* @__PURE__ */ jsx3(Header, { title: "Your requests", onBack: () => setRoute({ view: "board" }), onClose }),
1479
- /* @__PURE__ */ jsx3("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx3("p", { className: "ya-empty", children: errorText(error) }) : !data ? /* @__PURE__ */ jsx3(Skeleton, {}) : data.length === 0 ? /* @__PURE__ */ jsxs3("div", { className: "ya-empty", children: [
1480
- /* @__PURE__ */ jsx3("b", { children: "Nothing yet" }),
1590
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1591
+ /* @__PURE__ */ jsx4(Header, { title: "Your requests", onBack: () => setRoute({ view: "board" }), onClose }),
1592
+ /* @__PURE__ */ jsx4("div", { className: "ya-body", children: error ? /* @__PURE__ */ jsx4("p", { className: "ya-empty", children: errorText(error) }) : !data ? /* @__PURE__ */ jsx4(Skeleton, {}) : data.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "ya-empty", children: [
1593
+ /* @__PURE__ */ jsx4("b", { children: "Nothing yet" }),
1481
1594
  "Requests you post or vote on show up here, with their status."
1482
- ] }) : /* @__PURE__ */ jsx3("ul", { className: "ya-list", children: data.map((r) => /* @__PURE__ */ jsx3(RequestRow, { client, request: r, onOpen: () => setRoute({ view: "detail", id: r.id }) }, r.id)) }) }),
1483
- /* @__PURE__ */ jsx3("div", { className: "ya-foot", children: /* @__PURE__ */ jsxs3("button", { type: "button", className: "ya-btn", onClick: () => setRoute({ view: "home", focus: true }), children: [
1484
- /* @__PURE__ */ jsx3(IconPlus, {}),
1595
+ ] }) : /* @__PURE__ */ jsx4("ul", { className: "ya-list", children: data.map((r) => /* @__PURE__ */ jsx4(RequestRow, { client, request: r, onOpen: () => setRoute({ view: "detail", id: r.id, from: "mine" }) }, r.id)) }) }),
1596
+ /* @__PURE__ */ jsx4("div", { className: "ya-foot", children: /* @__PURE__ */ jsxs4("button", { type: "button", className: "ya-btn", onClick: () => setRoute({ view: "home", focus: true }), children: [
1597
+ /* @__PURE__ */ jsx4(IconPlus, {}),
1485
1598
  "Request a feature"
1486
1599
  ] }) })
1487
1600
  ] });
1488
1601
  }
1489
1602
 
1490
1603
  // src/YouAsked.tsx
1491
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1604
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1492
1605
  var warnedTestMode = false;
1493
1606
  var DEFAULT_API_URL = "https://api.youasked.dev";
1494
1607
  function lastWhatsNew(key) {
@@ -1505,6 +1618,7 @@ function YouAsked({
1505
1618
  appKey = "",
1506
1619
  demo = false,
1507
1620
  cards = true,
1621
+ nudge: nudgeProp,
1508
1622
  user,
1509
1623
  signature,
1510
1624
  ready = true,
@@ -1528,26 +1642,36 @@ function YouAsked({
1528
1642
  [demo, appName, appKey, apiUrl, userId, userEmail, userName, signature]
1529
1643
  );
1530
1644
  const whatsNewKey = demo ? null : `youasked:whats-new:${appKey}:${userId ?? "anon"}`;
1531
- const [mounted, setMounted] = useState3(false);
1532
- const [route, setRoute] = useState3(null);
1533
- const [config, setConfig] = useState3(null);
1534
- const [testMode, setTestMode] = useState3(false);
1535
- const [whatsNew, setWhatsNew] = useState3(null);
1536
- const [whatsNewToast, setWhatsNewToast] = useState3(false);
1537
- const [capture, setCapture] = useState3(null);
1645
+ const [mounted, setMounted] = useState4(false);
1646
+ const [route, setRoute] = useState4(null);
1647
+ const [config, setConfig] = useState4(null);
1648
+ const [testMode, setTestMode] = useState4(false);
1649
+ const [whatsNew, setWhatsNew] = useState4(null);
1650
+ const [whatsNewToast, setWhatsNewToast] = useState4(false);
1651
+ const [capture, setCapture] = useState4(null);
1538
1652
  const tokens = useTokens(appearance, mounted);
1539
- const openerRef = useRef3(null);
1540
- const [detectedIcon, setDetectedIcon] = useState3(null);
1541
- useEffect3(() => {
1653
+ const openerRef = useRef4(null);
1654
+ const [detectedIcon, setDetectedIcon] = useState4(null);
1655
+ useEffect4(() => {
1542
1656
  if (appIcon === void 0) setDetectedIcon(findPageIcon());
1543
1657
  }, [appIcon]);
1544
- useEffect3(() => {
1658
+ useEffect4(() => {
1545
1659
  injectStyles();
1546
1660
  setMounted(true);
1547
1661
  }, []);
1548
- useEffect3(() => {
1662
+ const [refresh, setRefresh] = useState4(0);
1663
+ const lastLoad = useRef4(0);
1664
+ useEffect4(() => {
1665
+ const onVisible = () => {
1666
+ if (document.visibilityState === "visible" && Date.now() - lastLoad.current > 6e4) setRefresh((n) => n + 1);
1667
+ };
1668
+ document.addEventListener("visibilitychange", onVisible);
1669
+ return () => document.removeEventListener("visibilitychange", onVisible);
1670
+ }, []);
1671
+ useEffect4(() => {
1549
1672
  if (!ready) return;
1550
1673
  let alive = true;
1674
+ lastLoad.current = Date.now();
1551
1675
  client.config().then((c) => {
1552
1676
  if (!alive) return;
1553
1677
  const seenAt = lastWhatsNew(whatsNewKey);
@@ -1567,14 +1691,14 @@ function YouAsked({
1567
1691
  return () => {
1568
1692
  alive = false;
1569
1693
  };
1570
- }, [client, ready]);
1571
- useEffect3(() => {
1694
+ }, [client, ready, refresh]);
1695
+ useEffect4(() => {
1572
1696
  if (!("onNotice" in client)) return;
1573
1697
  return client.onNotice(
1574
1698
  (n) => setConfig((c) => c ? { ...c, unseen: [...c.unseen, n] } : c)
1575
1699
  );
1576
1700
  }, [client]);
1577
- const dismissWhatsNew = useCallback2(() => {
1701
+ const dismissWhatsNew = useCallback3(() => {
1578
1702
  setWhatsNew(null);
1579
1703
  setWhatsNewToast(false);
1580
1704
  try {
@@ -1584,7 +1708,7 @@ function YouAsked({
1584
1708
  client.whatsNewSeen().catch(() => {
1585
1709
  });
1586
1710
  }, [client, whatsNewKey]);
1587
- const pointAtIt = useCallback2(
1711
+ const pointAtIt = useCallback3(
1588
1712
  () => new Promise((resolve, reject) => {
1589
1713
  import("./capture-FYZGL54F.js").then(
1590
1714
  (m) => setCapture({ Layer: m.default, resolve }),
@@ -1593,20 +1717,20 @@ function YouAsked({
1593
1717
  }),
1594
1718
  []
1595
1719
  );
1596
- const open = useCallback2((options) => {
1720
+ const open = useCallback3((options) => {
1597
1721
  openerRef.current = document.activeElement;
1598
1722
  setRoute(toRoute(options));
1599
1723
  }, []);
1600
- const close = useCallback2(() => {
1724
+ const close = useCallback3(() => {
1601
1725
  setRoute(null);
1602
1726
  openerRef.current?.focus?.({ preventScroll: true });
1603
1727
  }, []);
1604
- useEffect3(() => {
1728
+ useEffect4(() => {
1605
1729
  const onOpen = (e) => open(e.detail);
1606
1730
  window.addEventListener("youasked:open", onOpen);
1607
1731
  return () => window.removeEventListener("youasked:open", onOpen);
1608
1732
  }, [open]);
1609
- const markSeen = useCallback2(
1733
+ const markSeen = useCallback3(
1610
1734
  (ids) => {
1611
1735
  if (!ids.length) return;
1612
1736
  setConfig((c) => c ? { ...c, unseen: c.unseen.filter((n) => !ids.includes(n.id)) } : c);
@@ -1645,12 +1769,22 @@ function YouAsked({
1645
1769
  );
1646
1770
  const standing = unseen.filter((n) => !coveredBy(whatsNew, n));
1647
1771
  const notice = standing.find((n) => n.kind === "shipped") ?? standing.find((n) => n.kind === "reply");
1648
- if (testMode) return /* @__PURE__ */ jsx4(YouAskedContext.Provider, { value, children });
1649
- return /* @__PURE__ */ jsxs4(YouAskedContext.Provider, { value, children: [
1772
+ const nudgeSettings = useMemo(
1773
+ () => config && cards && !testMode ? resolveNudge(config.nudge, nudgeProp) : null,
1774
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1775
+ [Boolean(config), JSON.stringify(config?.nudge ?? null), cards, testMode, typeof nudgeProp === "object" ? JSON.stringify(nudgeProp) : nudgeProp]
1776
+ );
1777
+ const busy = route !== null || Boolean(notice) || whatsNewToast && Boolean(whatsNew);
1778
+ const nudge = useNudge(nudgeSettings, demo ? null : `youasked:nudge:${appKey}:${userId ?? "anon"}`, busy);
1779
+ useEffect4(() => {
1780
+ if (route !== null) nudge.engaged();
1781
+ }, [route, nudge.engaged]);
1782
+ if (testMode) return /* @__PURE__ */ jsx5(YouAskedContext.Provider, { value, children });
1783
+ return /* @__PURE__ */ jsxs5(YouAskedContext.Provider, { value, children: [
1650
1784
  children,
1651
1785
  mounted && createPortal(
1652
- /* @__PURE__ */ jsxs4("div", { className: "ya-scope", "data-ya-mode": tokens?.mode, "data-ya-skip": "", style: scopeStyle, children: [
1653
- trigger === "floating" && !capture && /* @__PURE__ */ jsx4(
1786
+ /* @__PURE__ */ jsxs5("div", { className: "ya-scope", "data-ya-mode": tokens?.mode, "data-ya-skip": "", style: scopeStyle, children: [
1787
+ trigger === "floating" && !capture && /* @__PURE__ */ jsx5(
1654
1788
  Launcher,
1655
1789
  {
1656
1790
  position,
@@ -1660,7 +1794,7 @@ function YouAsked({
1660
1794
  onClick: () => route ? close() : open()
1661
1795
  }
1662
1796
  ),
1663
- cards && !notice && whatsNewToast && whatsNew && route === null && /* @__PURE__ */ jsx4(
1797
+ cards && !notice && whatsNewToast && whatsNew && route === null && /* @__PURE__ */ jsx5(
1664
1798
  WhatsNewToast,
1665
1799
  {
1666
1800
  news: whatsNew,
@@ -1670,7 +1804,18 @@ function YouAsked({
1670
1804
  onDismiss: dismissWhatsNew
1671
1805
  }
1672
1806
  ),
1673
- cards && notice && route === null && /* @__PURE__ */ jsx4(
1807
+ nudgeSettings && nudge.show && !busy && /* @__PURE__ */ jsx5(
1808
+ NudgeToast,
1809
+ {
1810
+ settings: nudgeSettings,
1811
+ appName: appName ?? config?.app.name ?? "us",
1812
+ position,
1813
+ trigger,
1814
+ onOpen: () => open({ view: "new" }),
1815
+ onDismiss: nudge.dismiss
1816
+ }
1817
+ ),
1818
+ cards && notice && route === null && /* @__PURE__ */ jsx5(
1674
1819
  ShippedToast,
1675
1820
  {
1676
1821
  notice,
@@ -1683,7 +1828,7 @@ function YouAsked({
1683
1828
  onDismiss: () => markSeen([notice.id])
1684
1829
  }
1685
1830
  ),
1686
- route && /* @__PURE__ */ jsx4(
1831
+ route && /* @__PURE__ */ jsx5(
1687
1832
  Panel,
1688
1833
  {
1689
1834
  route,
@@ -1694,7 +1839,7 @@ function YouAsked({
1694
1839
  hidden: capture !== null
1695
1840
  }
1696
1841
  ),
1697
- capture && /* @__PURE__ */ jsx4(
1842
+ capture && /* @__PURE__ */ jsx5(
1698
1843
  capture.Layer,
1699
1844
  {
1700
1845
  onDone: (image) => {
@@ -1721,8 +1866,8 @@ function findPageIcon() {
1721
1866
  }
1722
1867
  function useTokens(appearance, mounted) {
1723
1868
  const key = JSON.stringify(appearance ?? {});
1724
- const [tokens, setTokens] = useState3(null);
1725
- useEffect3(() => {
1869
+ const [tokens, setTokens] = useState4(null);
1870
+ useEffect4(() => {
1726
1871
  if (!mounted) return;
1727
1872
  const parsed = JSON.parse(key);
1728
1873
  const update = () => setTokens(resolveTokens(parsed));
@@ -1757,20 +1902,20 @@ function Panel({
1757
1902
  hasLauncher,
1758
1903
  hidden
1759
1904
  }) {
1760
- const panelRef = useRef3(null);
1761
- const backdropRef = useRef3(null);
1762
- const [closing, setClosing] = useState3(false);
1905
+ const panelRef = useRef4(null);
1906
+ const backdropRef = useRef4(null);
1907
+ const [closing, setClosing] = useState4(false);
1763
1908
  const isSheet = useMedia("(max-width: 639px)");
1764
1909
  const reduceMotion = useMedia("(prefers-reduced-motion: reduce)");
1765
- const hiddenRef = useRef3(hidden);
1910
+ const hiddenRef = useRef4(hidden);
1766
1911
  hiddenRef.current = hidden;
1767
- const drag = useRef3(null);
1768
- const requestClose = useCallback2(() => {
1912
+ const drag = useRef4(null);
1913
+ const requestClose = useCallback3(() => {
1769
1914
  if (reduceMotion) return onClose();
1770
1915
  setClosing(true);
1771
1916
  setTimeout(onClose, 200);
1772
1917
  }, [onClose, reduceMotion]);
1773
- useEffect3(() => {
1918
+ useEffect4(() => {
1774
1919
  if (!isSheet) return;
1775
1920
  const html = document.documentElement;
1776
1921
  const previous = html.style.overflow;
@@ -1779,10 +1924,10 @@ function Panel({
1779
1924
  html.style.overflow = previous;
1780
1925
  };
1781
1926
  }, [isSheet]);
1782
- useEffect3(() => {
1927
+ useEffect4(() => {
1783
1928
  panelRef.current?.focus({ preventScroll: true });
1784
1929
  }, []);
1785
- useEffect3(() => {
1930
+ useEffect4(() => {
1786
1931
  const onKey = (e) => {
1787
1932
  if (hiddenRef.current) return;
1788
1933
  if (e.key === "Escape") {
@@ -1836,7 +1981,7 @@ function Panel({
1836
1981
  if (backdrop) backdrop.style.opacity = "";
1837
1982
  }
1838
1983
  };
1839
- return /* @__PURE__ */ jsxs4(
1984
+ return /* @__PURE__ */ jsxs5(
1840
1985
  "div",
1841
1986
  {
1842
1987
  className: "ya-overlay",
@@ -1845,8 +1990,8 @@ function Panel({
1845
1990
  "data-closing": closing || void 0,
1846
1991
  hidden,
1847
1992
  children: [
1848
- /* @__PURE__ */ jsx4("div", { className: "ya-backdrop", ref: backdropRef, onClick: requestClose, "aria-hidden": "true" }),
1849
- /* @__PURE__ */ jsxs4(
1993
+ /* @__PURE__ */ jsx5("div", { className: "ya-backdrop", ref: backdropRef, onClick: requestClose, "aria-hidden": "true" }),
1994
+ /* @__PURE__ */ jsxs5(
1850
1995
  "div",
1851
1996
  {
1852
1997
  className: "ya-panel",
@@ -1860,8 +2005,8 @@ function Panel({
1860
2005
  onPointerUp,
1861
2006
  onPointerCancel: onPointerUp,
1862
2007
  children: [
1863
- /* @__PURE__ */ jsx4("div", { className: "ya-grab-zone", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("div", { className: "ya-grab" }) }),
1864
- /* @__PURE__ */ jsx4(Navigator, { route, setRoute, onClose: requestClose })
2008
+ /* @__PURE__ */ jsx5("div", { className: "ya-grab-zone", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { className: "ya-grab" }) }),
2009
+ /* @__PURE__ */ jsx5(Navigator, { route, setRoute, onClose: requestClose })
1865
2010
  ]
1866
2011
  }
1867
2012
  )
@@ -1891,7 +2036,7 @@ function Launcher({
1891
2036
  badge,
1892
2037
  onClick
1893
2038
  }) {
1894
- return /* @__PURE__ */ jsxs4(
2039
+ return /* @__PURE__ */ jsxs5(
1895
2040
  "button",
1896
2041
  {
1897
2042
  type: "button",
@@ -1902,9 +2047,9 @@ function Launcher({
1902
2047
  "aria-label": isOpen ? "Close feature requests" : label || "Feature requests",
1903
2048
  "aria-expanded": isOpen,
1904
2049
  children: [
1905
- /* @__PURE__ */ jsx4("span", { className: "ya-fab-icon", children: isOpen ? /* @__PURE__ */ jsx4(IconClose, {}) : /* @__PURE__ */ jsx4(IconIdea, {}) }),
1906
- label && !isOpen && /* @__PURE__ */ jsx4("span", { children: label }),
1907
- badge && !isOpen && /* @__PURE__ */ jsx4("span", { className: "ya-dot", "aria-hidden": "true" })
2050
+ /* @__PURE__ */ jsx5("span", { className: "ya-fab-icon", children: isOpen ? /* @__PURE__ */ jsx5(IconClose, {}) : /* @__PURE__ */ jsx5(IconIdea, { ink: "var(--_accent)" }) }),
2051
+ label && !isOpen && /* @__PURE__ */ jsx5("span", { children: label }),
2052
+ badge && !isOpen && /* @__PURE__ */ jsx5("span", { className: "ya-dot", "aria-hidden": "true" })
1908
2053
  ]
1909
2054
  }
1910
2055
  );
@@ -1916,18 +2061,18 @@ function ShippedToast({
1916
2061
  onOpen,
1917
2062
  onDismiss
1918
2063
  }) {
1919
- return /* @__PURE__ */ jsx4("div", { className: "ya-toast", role: "status", "data-pos": position, "data-trigger": trigger, children: notice.kind === "reply" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1920
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-top", children: [
1921
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-kicker", children: "New reply about" }),
1922
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx4(IconClose, {}) })
2064
+ return /* @__PURE__ */ jsx5("div", { className: "ya-toast", role: "status", "data-pos": position, "data-trigger": trigger, children: notice.kind === "reply" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
2065
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-top", children: [
2066
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-kicker", children: "New reply about" }),
2067
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx5(IconClose, {}) })
1923
2068
  ] }),
1924
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-title", children: notice.title }),
1925
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-note ya-toast-quote", children: notice.reply }),
1926
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-actions", children: [
1927
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "Reply" }),
1928
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Later" })
2069
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-title", children: notice.title }),
2070
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-note ya-toast-quote", children: notice.reply }),
2071
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-actions", children: [
2072
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "Reply" }),
2073
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Later" })
1929
2074
  ] })
1930
- ] }) : /* @__PURE__ */ jsx4(ShippedBody, { notice, onOpen, onDismiss }) });
2075
+ ] }) : /* @__PURE__ */ jsx5(ShippedBody, { notice, onOpen, onDismiss }) });
1931
2076
  }
1932
2077
  function WhatsNewToast({
1933
2078
  news,
@@ -1937,44 +2082,44 @@ function WhatsNewToast({
1937
2082
  onDismiss
1938
2083
  }) {
1939
2084
  const mine = news.items.some((i) => i.mine);
1940
- return /* @__PURE__ */ jsxs4("div", { className: "ya-toast", role: "status", "data-pos": position, "data-trigger": trigger, children: [
1941
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-top", children: [
1942
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-kicker", children: "What's new" }),
1943
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx4(IconClose, {}) })
2085
+ return /* @__PURE__ */ jsxs5("div", { className: "ya-toast", role: "status", "data-pos": position, "data-trigger": trigger, children: [
2086
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-top", children: [
2087
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-kicker", children: "What's new" }),
2088
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx5(IconClose, {}) })
1944
2089
  ] }),
1945
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-title", children: whatsNewHeading(news.total) }),
1946
- mine && /* @__PURE__ */ jsxs4("div", { className: "ya-live", children: [
1947
- /* @__PURE__ */ jsx4(IconCheck, {}),
2090
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-title", children: whatsNewHeading(news.total) }),
2091
+ mine && /* @__PURE__ */ jsxs5("div", { className: "ya-live", children: [
2092
+ /* @__PURE__ */ jsx5(IconCheck, {}),
1948
2093
  "Including something you asked for"
1949
2094
  ] }),
1950
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-actions", children: [
1951
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "See what's new" }),
1952
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Not now" })
2095
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-actions", children: [
2096
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "See what's new" }),
2097
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Not now" })
1953
2098
  ] })
1954
2099
  ] });
1955
2100
  }
1956
2101
  function ShippedBody({ notice, onOpen, onDismiss }) {
1957
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1958
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-top", children: [
1959
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-kicker", children: "You asked for" }),
1960
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx4(IconClose, {}) })
2102
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
2103
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-top", children: [
2104
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-kicker", children: "You asked for" }),
2105
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-icon-btn", onClick: onDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx5(IconClose, {}) })
1961
2106
  ] }),
1962
- /* @__PURE__ */ jsx4("p", { className: "ya-toast-title", children: notice.title }),
1963
- /* @__PURE__ */ jsxs4("div", { className: "ya-live", children: [
1964
- /* @__PURE__ */ jsx4(IconCheck, {}),
2107
+ /* @__PURE__ */ jsx5("p", { className: "ya-toast-title", children: notice.title }),
2108
+ /* @__PURE__ */ jsxs5("div", { className: "ya-live", children: [
2109
+ /* @__PURE__ */ jsx5(IconCheck, {}),
1965
2110
  "It's live"
1966
2111
  ] }),
1967
- notice.shipNote && /* @__PURE__ */ jsx4("p", { className: "ya-toast-note", children: notice.shipNote }),
1968
- /* @__PURE__ */ jsxs4("div", { className: "ya-toast-actions", children: [
1969
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "See it" }),
1970
- /* @__PURE__ */ jsx4("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Nice" })
2112
+ notice.shipNote && /* @__PURE__ */ jsx5("p", { className: "ya-toast-note", children: notice.shipNote }),
2113
+ /* @__PURE__ */ jsxs5("div", { className: "ya-toast-actions", children: [
2114
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: onOpen, children: "See it" }),
2115
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: onDismiss, children: "Nice" })
1971
2116
  ] })
1972
2117
  ] });
1973
2118
  }
1974
2119
 
1975
2120
  // src/entries.tsx
1976
- import { useState as useState4 } from "react";
1977
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2121
+ import { useState as useState5 } from "react";
2122
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1978
2123
  function useScope(className, style) {
1979
2124
  const { scope } = useInternal();
1980
2125
  return {
@@ -1985,11 +2130,11 @@ function useScope(className, style) {
1985
2130
  }
1986
2131
  function AskBar({ placeholder = "Ask for a feature\u2026", className, style }) {
1987
2132
  const { open, appIcon, unseenCount } = useInternal();
1988
- return /* @__PURE__ */ jsx5("div", { ...useScope(className, style), children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-askbar", onClick: () => open({ view: "new" }), children: [
1989
- appIcon ? /* @__PURE__ */ jsx5(AppAvatar, { icon: appIcon, size: 30 }) : /* @__PURE__ */ jsx5("span", { className: "ya-askbar-glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(IconIdea, {}) }),
1990
- /* @__PURE__ */ jsx5("span", { className: "ya-askbar-text", children: placeholder }),
1991
- unseenCount > 0 && /* @__PURE__ */ jsx5("span", { className: "ya-badge", children: unseenCount }),
1992
- /* @__PURE__ */ jsx5("span", { className: "ya-askbar-send", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(IconSend, {}) })
2133
+ return /* @__PURE__ */ jsx6("div", { ...useScope(className, style), children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-askbar", onClick: () => open({ view: "new" }), children: [
2134
+ appIcon ? /* @__PURE__ */ jsx6(AppAvatar, { icon: appIcon, size: 30 }) : /* @__PURE__ */ jsx6("span", { className: "ya-askbar-glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(IconIdea, {}) }),
2135
+ /* @__PURE__ */ jsx6("span", { className: "ya-askbar-text", children: placeholder }),
2136
+ unseenCount > 0 && /* @__PURE__ */ jsx6("span", { className: "ya-badge", children: unseenCount }),
2137
+ /* @__PURE__ */ jsx6("span", { className: "ya-askbar-send", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(IconSend, {}) })
1993
2138
  ] }) });
1994
2139
  }
1995
2140
  function FeatureCard({
@@ -2002,15 +2147,15 @@ function FeatureCard({
2002
2147
  const { client, open, config, markSeen } = useInternal();
2003
2148
  const { data } = useLoad(() => client.list("top", "active"), [client]);
2004
2149
  const notice = config?.unseen.find((n) => n.kind === "shipped");
2005
- return /* @__PURE__ */ jsx5("div", { ...useScope(className, style), children: /* @__PURE__ */ jsxs5("section", { className: "ya-card", children: [
2006
- /* @__PURE__ */ jsxs5("div", { className: "ya-card-head", children: [
2007
- /* @__PURE__ */ jsx5("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(IconIdea, {}) }),
2008
- /* @__PURE__ */ jsxs5("div", { children: [
2009
- /* @__PURE__ */ jsx5("h3", { className: "ya-card-title", children: heading }),
2010
- /* @__PURE__ */ jsx5("p", { className: "ya-card-sub", children: description })
2150
+ return /* @__PURE__ */ jsx6("div", { ...useScope(className, style), children: /* @__PURE__ */ jsxs6("section", { className: "ya-card", children: [
2151
+ /* @__PURE__ */ jsxs6("div", { className: "ya-card-head", children: [
2152
+ /* @__PURE__ */ jsx6("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(IconIdea, {}) }),
2153
+ /* @__PURE__ */ jsxs6("div", { children: [
2154
+ /* @__PURE__ */ jsx6("h3", { className: "ya-card-title", children: heading }),
2155
+ /* @__PURE__ */ jsx6("p", { className: "ya-card-sub", children: description })
2011
2156
  ] })
2012
2157
  ] }),
2013
- notice && /* @__PURE__ */ jsxs5(
2158
+ notice && /* @__PURE__ */ jsxs6(
2014
2159
  "button",
2015
2160
  {
2016
2161
  type: "button",
@@ -2020,20 +2165,20 @@ function FeatureCard({
2020
2165
  open({ requestId: notice.requestId });
2021
2166
  },
2022
2167
  children: [
2023
- /* @__PURE__ */ jsx5("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx5(IconCheck, {}) }),
2024
- /* @__PURE__ */ jsxs5("span", { children: [
2168
+ /* @__PURE__ */ jsx6("span", { className: "ya-shipped-dot", children: /* @__PURE__ */ jsx6(IconCheck, {}) }),
2169
+ /* @__PURE__ */ jsxs6("span", { children: [
2025
2170
  "You asked for ",
2026
- /* @__PURE__ */ jsx5("b", { children: notice.title }),
2171
+ /* @__PURE__ */ jsx6("b", { children: notice.title }),
2027
2172
  ". It's live."
2028
2173
  ] }),
2029
- /* @__PURE__ */ jsx5(IconChevron, {})
2174
+ /* @__PURE__ */ jsx6(IconChevron, {})
2030
2175
  ]
2031
2176
  }
2032
2177
  ),
2033
- !data ? /* @__PURE__ */ jsx5(Skeleton, { rows: 2 }) : data.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "ya-list", children: data.slice(0, limit).map((r) => /* @__PURE__ */ jsx5(RequestRow, { client, request: r, compact: true, onOpen: () => open({ requestId: r.id }) }, r.id)) }) : null,
2034
- /* @__PURE__ */ jsxs5("div", { className: "ya-card-actions", children: [
2035
- /* @__PURE__ */ jsx5("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: () => open({ view: "new" }), children: "Suggest an idea" }),
2036
- data && data.length > limit && /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: () => open({ view: "board" }), children: [
2178
+ !data ? /* @__PURE__ */ jsx6(Skeleton, { rows: 2 }) : data.length > 0 ? /* @__PURE__ */ jsx6("ul", { className: "ya-list", children: data.slice(0, limit).map((r) => /* @__PURE__ */ jsx6(RequestRow, { client, request: r, compact: true, onOpen: () => open({ requestId: r.id }) }, r.id)) }) : null,
2179
+ /* @__PURE__ */ jsxs6("div", { className: "ya-card-actions", children: [
2180
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "ya-btn ya-btn-sm", onClick: () => open({ view: "new" }), children: "Suggest an idea" }),
2181
+ data && data.length > limit && /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-btn ya-btn-sm ya-btn-ghost", onClick: () => open({ view: "board" }), children: [
2037
2182
  "See all ",
2038
2183
  data.length
2039
2184
  ] })
@@ -2049,26 +2194,26 @@ function RequestButton({
2049
2194
  }) {
2050
2195
  const { open, unseenCount } = useInternal();
2051
2196
  const scope = useScope(className, style);
2052
- const badge = unseenCount > 0 && (variant === "icon" ? /* @__PURE__ */ jsx5("span", { className: "ya-dot", "aria-hidden": "true" }) : /* @__PURE__ */ jsx5("span", { className: "ya-badge", children: unseenCount }));
2197
+ const badge = unseenCount > 0 && (variant === "icon" ? /* @__PURE__ */ jsx6("span", { className: "ya-dot", "aria-hidden": "true" }) : /* @__PURE__ */ jsx6("span", { className: "ya-badge", children: unseenCount }));
2053
2198
  if (variant === "icon") {
2054
- return /* @__PURE__ */ jsx5("span", { ...scope, children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-iconbtn", onClick: () => open(), "aria-label": label, children: [
2055
- /* @__PURE__ */ jsx5(IconIdea, {}),
2199
+ return /* @__PURE__ */ jsx6("span", { ...scope, children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-iconbtn", onClick: () => open(), "aria-label": label, children: [
2200
+ /* @__PURE__ */ jsx6(IconIdea, {}),
2056
2201
  badge
2057
2202
  ] }) });
2058
2203
  }
2059
2204
  if (variant === "row") {
2060
- return /* @__PURE__ */ jsx5("div", { ...scope, children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-menurow", onClick: () => open(), children: [
2061
- /* @__PURE__ */ jsx5("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(IconIdea, {}) }),
2062
- /* @__PURE__ */ jsxs5("span", { className: "ya-menurow-text", children: [
2063
- /* @__PURE__ */ jsx5("span", { className: "ya-menurow-label", children: label }),
2064
- sublabel && /* @__PURE__ */ jsx5("span", { className: "ya-menurow-sub", children: sublabel })
2205
+ return /* @__PURE__ */ jsx6("div", { ...scope, children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-menurow", onClick: () => open(), children: [
2206
+ /* @__PURE__ */ jsx6("span", { className: "ya-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(IconIdea, {}) }),
2207
+ /* @__PURE__ */ jsxs6("span", { className: "ya-menurow-text", children: [
2208
+ /* @__PURE__ */ jsx6("span", { className: "ya-menurow-label", children: label }),
2209
+ sublabel && /* @__PURE__ */ jsx6("span", { className: "ya-menurow-sub", children: sublabel })
2065
2210
  ] }),
2066
2211
  badge,
2067
- /* @__PURE__ */ jsx5(IconChevron, {})
2212
+ /* @__PURE__ */ jsx6(IconChevron, {})
2068
2213
  ] }) });
2069
2214
  }
2070
- return /* @__PURE__ */ jsx5("span", { ...scope, children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-pillbtn", onClick: () => open(), children: [
2071
- /* @__PURE__ */ jsx5(IconIdea, {}),
2215
+ return /* @__PURE__ */ jsx6("span", { ...scope, children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-pillbtn", onClick: () => open(), children: [
2216
+ /* @__PURE__ */ jsx6(IconIdea, {}),
2072
2217
  label,
2073
2218
  badge
2074
2219
  ] }) });
@@ -2080,8 +2225,8 @@ function AskAbout({
2080
2225
  style
2081
2226
  }) {
2082
2227
  const { open } = useInternal();
2083
- return /* @__PURE__ */ jsx5("span", { ...useScope(className, style), children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-askabout", onClick: () => open({ view: "new", topic }), children: [
2084
- /* @__PURE__ */ jsx5(IconIdea, {}),
2228
+ return /* @__PURE__ */ jsx6("span", { ...useScope(className, style), children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-askabout", onClick: () => open({ view: "new", topic }), children: [
2229
+ /* @__PURE__ */ jsx6(IconIdea, {}),
2085
2230
  prompt ?? `Want more from ${topic}?`
2086
2231
  ] }) });
2087
2232
  }
@@ -2089,11 +2234,11 @@ function AskForIt({ query, className, style }) {
2089
2234
  const { open } = useInternal();
2090
2235
  const q = query.trim();
2091
2236
  const shown = q.length > 40 ? `${q.slice(0, 39).trimEnd()}\u2026` : q;
2092
- return /* @__PURE__ */ jsx5("span", { ...useScope(className, style), children: /* @__PURE__ */ jsxs5("button", { type: "button", className: "ya-askforit", onClick: () => open({ view: "new", draft: q, topic: "search" }), children: [
2093
- /* @__PURE__ */ jsx5("span", { children: shown ? `Can't find \u201C${shown}\u201D?` : "Can't find it?" }),
2094
- /* @__PURE__ */ jsxs5("b", { children: [
2237
+ return /* @__PURE__ */ jsx6("span", { ...useScope(className, style), children: /* @__PURE__ */ jsxs6("button", { type: "button", className: "ya-askforit", onClick: () => open({ view: "new", draft: q, topic: "search" }), children: [
2238
+ /* @__PURE__ */ jsx6("span", { children: shown ? `Can't find \u201C${shown}\u201D?` : "Can't find it?" }),
2239
+ /* @__PURE__ */ jsxs6("b", { children: [
2095
2240
  "Ask for it",
2096
- /* @__PURE__ */ jsx5(IconChevron, {})
2241
+ /* @__PURE__ */ jsx6(IconChevron, {})
2097
2242
  ] })
2098
2243
  ] }) });
2099
2244
  }
@@ -2103,8 +2248,8 @@ function FeatureBoard({
2103
2248
  className,
2104
2249
  style
2105
2250
  }) {
2106
- const [route, setRoute] = useState4(start === "board" ? { view: "board" } : { view: "home" });
2107
- return /* @__PURE__ */ jsx5("div", { ...useScope(className, style), children: /* @__PURE__ */ jsx5("div", { className: "ya-embed", style: { height }, children: /* @__PURE__ */ jsx5(Navigator, { route, setRoute }) }) });
2251
+ const [route, setRoute] = useState5(start === "board" ? { view: "board" } : { view: "home" });
2252
+ return /* @__PURE__ */ jsx6("div", { ...useScope(className, style), children: /* @__PURE__ */ jsx6("div", { className: "ya-embed", style: { height }, children: /* @__PURE__ */ jsx6(Navigator, { route, setRoute }) }) });
2108
2253
  }
2109
2254
  export {
2110
2255
  AskAbout,