@youasked/react 0.0.0-stage → 0.4.1

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Server-only helper. Signs a user id with your secret key so nobody can vote or post as someone else.
3
+ *
4
+ * const signature = await signUser(process.env.YOUASKED_SECRET_KEY!, user.id)
5
+ *
6
+ * Works in Node 18+, edge runtimes, Bun and Deno (Web Crypto).
7
+ */
8
+ export declare function signUser(secretKey: string, userId: string | number): Promise<string>;
package/dist/server.js ADDED
@@ -0,0 +1,11 @@
1
+ // src/server.ts
2
+ async function signUser(secretKey, userId) {
3
+ if (!secretKey?.startsWith("ya_sec_")) throw new Error("signUser needs your secret key (ya_sec_\u2026)");
4
+ const enc = new TextEncoder();
5
+ const key = await crypto.subtle.importKey("raw", enc.encode(secretKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
6
+ const sig = await crypto.subtle.sign("HMAC", key, enc.encode(String(userId)));
7
+ return Array.from(new Uint8Array(sig), (b) => b.toString(16).padStart(2, "0")).join("");
8
+ }
9
+ export {
10
+ signUser
11
+ };
@@ -0,0 +1,51 @@
1
+ import { type ReactNode } from "react";
2
+ import { type Client, type FeatureRequest, type Status } from "./client";
3
+ export declare function useVote(client: Client, initial: FeatureRequest): {
4
+ toggle: () => Promise<void>;
5
+ voted: boolean;
6
+ votes: number;
7
+ };
8
+ export declare function VoteButton({ client, request, compact }: {
9
+ client: Client;
10
+ request: FeatureRequest;
11
+ compact?: boolean;
12
+ }): import("react").JSX.Element;
13
+ export declare function BigVote({ client, request, onChange, }: {
14
+ client: Client;
15
+ request: FeatureRequest;
16
+ onChange?: (voted: boolean) => void;
17
+ }): import("react").JSX.Element;
18
+ export declare const STATUS_LABEL: Record<Status, string>;
19
+ export declare function StatusPill({ status }: {
20
+ status: Status;
21
+ }): import("react").JSX.Element;
22
+ export declare function RequestRow({ client, request, onOpen, compact, }: {
23
+ client: Client;
24
+ request: FeatureRequest;
25
+ onOpen: () => void;
26
+ compact?: boolean;
27
+ }): import("react").JSX.Element;
28
+ export declare function Skeleton({ rows }: {
29
+ rows?: number;
30
+ }): import("react").JSX.Element;
31
+ export declare function useLoad<T>(load: () => Promise<T>, deps: unknown[]): {
32
+ data: T | null;
33
+ error: string | null;
34
+ setData: import("react").Dispatch<import("react").SetStateAction<T | null>>;
35
+ };
36
+ export declare function errorText(code: string | null): string;
37
+ export declare function whatsNewHeading(total: number): string;
38
+ export declare function ago(t: number): string;
39
+ /** The app's own icon, or nothing. A guessed letter tile looks generic, so it's never drawn. */
40
+ export declare function AppAvatar({ icon, size }: {
41
+ icon?: string | null;
42
+ size?: number;
43
+ }): import("react").JSX.Element | null;
44
+ export declare function Header({ title, subtitle, leading, onBack, onClose, right, }: {
45
+ title: ReactNode;
46
+ subtitle?: ReactNode;
47
+ leading?: ReactNode;
48
+ onBack?: () => void;
49
+ onClose?: () => void;
50
+ right?: ReactNode;
51
+ }): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export declare const css = "\n.ya-scope{--_bg:var(--ya-bg);--_fg:var(--ya-fg);--_accent:var(--ya-accent);--_accent-fg:var(--ya-accent-fg);\n--_muted:var(--ya-muted,color-mix(in srgb,var(--ya-fg) 58%,var(--ya-bg)));\n--_surface:var(--ya-surface,color-mix(in srgb,var(--ya-fg) 5%,var(--ya-bg)));\n--_border:var(--ya-border,color-mix(in srgb,var(--ya-fg) 11%,var(--ya-bg)));\n--_tint:color-mix(in srgb,var(--_accent) 12%,transparent);\n--_radius:var(--ya-radius,14px);--_offset:var(--ya-offset,20px);--_green:#16a34a;--_amber:#c26a04;\nfont-family:var(--ya-font,inherit);color:var(--_fg);font-size:15px;line-height:1.45;letter-spacing:normal;text-align:left;-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent}\n.ya-scope[data-ya-mode=dark]{--_green:#3fd07f;--_amber:#f2a93b}\n.ya-scope :where(*,*::before,*::after){box-sizing:border-box}\n/* :where() keeps the reset at class-level specificity, so component rules below win. */\n.ya-scope :where(button){font:inherit;color:inherit;background:none;border:0;margin:0;padding:0;cursor:pointer;text-align:inherit;letter-spacing:inherit}\n.ya-scope :where(button:disabled){cursor:default}\n.ya-scope :where(h2,h3,p,ul){margin:0;padding:0}\n.ya-scope :focus-visible{outline:2px solid var(--_accent);outline-offset:2px}\n.ya-scope :where(svg){display:block;flex:none}\n.ya-inline{display:block}\n.ya-overlay[hidden]{display:none}\nspan.ya-inline{display:inline-block}\n\n/* ---------- overlay: bottom sheet on phones */\n.ya-overlay{position:fixed;inset:0;z-index:2147483600;display:flex;align-items:flex-end;justify-content:center}\n.ya-backdrop{position:absolute;inset:0;background:rgba(8,10,20,.42);animation:ya-fade .25s ease-out}\n.ya-panel{position:relative;width:100%;max-width:520px;height:min(90vh,760px);height:min(90dvh,760px);background:var(--_bg);color:var(--_fg);\nborder-radius:calc(var(--_radius) + 10px) calc(var(--_radius) + 10px) 0 0;box-shadow:0 -10px 40px rgba(0,0,0,.18);\ndisplay:flex;flex-direction:column;overflow:hidden;animation:ya-sheet-in .42s cubic-bezier(.2,.9,.25,1);padding-bottom:env(safe-area-inset-bottom)}\n.ya-panel:focus{outline:none}\n.ya-grab-zone{flex:none;padding:7px 0 0;cursor:grab;touch-action:none}\n.ya-grab{width:38px;height:5px;border-radius:3px;background:color-mix(in srgb,var(--_fg) 20%,var(--_bg));margin:0 auto}\n.ya-overlay[data-closing] .ya-panel{animation:ya-sheet-out .2s ease-in forwards}\n.ya-overlay[data-closing] .ya-backdrop{animation:ya-fade-out .2s ease-in forwards}\n\n/* ---------- desktop: a panel anchored to the corner, like a chat window */\n@media (min-width:640px){\n.ya-overlay{align-items:flex-end;justify-content:flex-end;padding:0 20px calc(var(--_offset) + env(safe-area-inset-bottom))}\n.ya-overlay[data-launcher]{padding-bottom:calc(var(--_offset) + 68px + env(safe-area-inset-bottom))}\n.ya-overlay[data-pos=bottom-left]{justify-content:flex-start}\n.ya-backdrop{background:transparent;animation:none}\n.ya-panel{width:400px;max-width:calc(100vw - 40px);height:min(680px,calc(100vh - var(--_offset) - 110px));border-radius:calc(var(--_radius) + 8px);\nbox-shadow:0 0 0 1px var(--_border),0 24px 70px rgba(0,0,0,.22);padding-bottom:0;transform-origin:bottom right;animation:ya-pop-in .28s cubic-bezier(.16,1,.3,1)}\n.ya-overlay[data-pos=bottom-left] .ya-panel{transform-origin:bottom left}\n.ya-overlay[data-closing] .ya-panel{animation:ya-pop-out .18s ease-in forwards}\n.ya-grab-zone{display:none}\n}\n\n/* ---------- header */\n.ya-head{display:flex;align-items:center;gap:10px;padding:12px 12px 10px 18px;flex:none;touch-action:none}\n.ya-head-back{padding-left:8px}\n.ya-head-text{flex:1;min-width:0}\n.ya-h{font-size:17px;font-weight:700;letter-spacing:-.015em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.25}\n.ya-sub{font-size:12.5px;color:var(--_muted);margin-top:1px}\n.ya-icon-btn{width:34px;height:34px;border-radius:999px;display:grid;place-items:center;color:var(--_muted);flex:none;background:var(--_surface)}\n.ya-icon-btn:hover{color:var(--_fg)}\n.ya-head-back .ya-icon-btn:first-child{background:none}\n.ya-link{display:inline-flex;align-items:center;gap:2px;font-size:14px;font-weight:600;color:var(--_accent);padding:6px 8px;border-radius:10px;flex:none}\n.ya-link svg{width:15px;height:15px}\n.ya-link:hover{background:var(--_tint)}\n.ya-avatar{display:block;flex:none;border-radius:24%;object-fit:cover;background:var(--_surface)}\n\n/* ---------- body, lists */\n.ya-body{flex:1;min-height:0;overflow-y:auto;padding:6px 16px 18px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}\n.ya-list{list-style:none;display:flex;flex-direction:column;gap:8px}\n.ya-row{display:flex;gap:12px;align-items:center;padding:10px 12px;border-radius:var(--_radius);background:var(--_surface)}\n.ya-row-sm{padding:8px 10px;gap:10px}\n.ya-row-main{flex:1;min-width:0;display:block;padding:2px 0}\n.ya-row-title{font-weight:600;font-size:15px;line-height:1.35;overflow-wrap:anywhere;display:block}\n.ya-row-sm .ya-row-title{font-size:14.5px}\n.ya-meta{display:flex;align-items:center;gap:8px;margin-top:5px;font-size:12.5px;color:var(--_muted);flex-wrap:wrap}\n.ya-meta svg{width:13px;height:13px}\n.ya-meta span{display:inline-flex;align-items:center;gap:4px}\n\n.ya-vote{flex:none;width:46px;padding:6px 0 5px;border-radius:calc(var(--_radius) - 4px);background:var(--_bg);border:1px solid var(--_border);display:flex;flex-direction:column;align-items:center;font-weight:700;font-size:14px;line-height:1.2;color:var(--_fg);transition:transform .12s,background .15s,border-color .15s,color .15s;font-variant-numeric:tabular-nums}\n.ya-vote-sm{width:40px;padding:4px 0 3px;font-size:13px}\n.ya-vote svg{width:16px;height:16px}\n.ya-vote-sm svg{width:14px;height:14px}\n.ya-vote:hover{border-color:var(--_accent)}\n.ya-vote[aria-pressed=true]{background:var(--_accent);border-color:var(--_accent);color:var(--_accent-fg)}\n.ya-vote:active,.ya-bigvote:active,.ya-btn:active,.ya-fab:active,.ya-send:active,.ya-askbar:active,.ya-pillbtn:active,.ya-iconbtn:active{transform:scale(.95)}\n\n.ya-pill{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:999px;font-size:12px;font-weight:650;background:var(--_bg);color:var(--_muted);white-space:nowrap}\n.ya-pill[data-s=planned]{background:var(--_tint);color:var(--_accent)}\n.ya-pill[data-s=in_progress]{background:color-mix(in srgb,var(--_amber) 16%,transparent);color:var(--_amber)}\n.ya-pill[data-s=shipped]{background:color-mix(in srgb,var(--_green) 15%,transparent);color:var(--_green)}\n\n/* ---------- home: chat */\n.ya-chat{display:flex;flex-direction:column;gap:10px;padding-top:4px}\n.ya-bubble{max-width:86%;padding:10px 14px;border-radius:20px;font-size:15px;line-height:1.4;overflow-wrap:anywhere;animation:ya-bubble .3s cubic-bezier(.2,.9,.3,1.2);display:flex;flex-direction:column;gap:6px;align-items:flex-start}\n.ya-bubble b{font-weight:650}\n.ya-bubble-in{align-self:flex-start;background:var(--_surface);border-bottom-left-radius:6px}\n.ya-bubble-out{align-self:flex-end;background:var(--_accent);color:var(--_accent-fg);border-bottom-right-radius:6px;white-space:pre-wrap}\n.ya-bubble-win{background:color-mix(in srgb,var(--_green) 12%,var(--_bg))}\n.ya-bubble-error{background:color-mix(in srgb,#e5484d 12%,var(--_bg))}\n.ya-bubble-link{font-size:14px;font-weight:650;color:var(--_accent);padding:2px 0}\n.ya-bubble-img{display:block;width:100%;max-width:220px;border-radius:12px;margin-bottom:2px;box-shadow:0 0 0 1px color-mix(in srgb,var(--_accent-fg) 25%,transparent)}\n.ya-bubble-news{position:relative;align-self:stretch;max-width:100%;gap:8px}\n.ya-news{list-style:none;width:100%;display:flex;flex-direction:column}\n.ya-news button{display:flex;align-items:center;gap:10px;width:100%;padding:8px 0;border-top:1px solid color-mix(in srgb,var(--_fg) 9%,transparent);text-align:left}\n.ya-news li:first-child button{border-top:0}\n.ya-news > li > button > svg:last-child{color:var(--_muted);width:16px;height:16px}\n.ya-news-text{flex:1;min-width:0;display:flex;flex-direction:column}\n.ya-news-title{font-size:14.5px;font-weight:600;line-height:1.3}\n.ya-news-you{font-size:12px;font-weight:650;color:var(--_green)}\n/* A short burst from the corner. Hidden by default, so reduced motion (animation off) shows nothing. */\n.ya-confetti{position:absolute;top:14px;right:18px;width:0;height:0;pointer-events:none}\n.ya-confetti i{position:absolute;left:-3px;top:-3px;width:6px;height:9px;border-radius:2px;opacity:0;animation:ya-confetti .95s cubic-bezier(.2,.7,.3,1) both}\n.ya-typing{flex-direction:row;gap:4px;padding:14px 16px}\n.ya-typing span{width:7px;height:7px;border-radius:50%;background:var(--_muted);animation:ya-dot 1s infinite ease-in-out}\n.ya-typing span:nth-child(2){animation-delay:.15s}\n.ya-typing span:nth-child(3){animation-delay:.3s}\n.ya-chip{align-self:center;margin-top:6px;font-size:13.5px;font-weight:600;color:var(--_accent);padding:8px 14px;border-radius:999px;background:var(--_tint)}\n.ya-section{margin-top:12px}\n.ya-section-head{display:flex;align-items:center;justify-content:space-between;margin:0 0 8px}\n.ya-section-head h3{font-size:13px;font-weight:650;color:var(--_muted)}\n.ya-shipped{list-style:none;display:flex;flex-direction:column}\n.ya-shipped button{display:flex;align-items:center;gap:10px;width:100%;padding:9px 2px;border-bottom:1px solid var(--_border)}\n.ya-shipped li:last-child button{border-bottom:0}\n.ya-shipped-dot{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;background:color-mix(in srgb,var(--_green) 16%,transparent);color:var(--_green);flex:none}\n.ya-shipped-title{flex:1;min-width:0;font-size:14.5px;font-weight:550;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ya-shipped-when{font-size:12.5px;color:var(--_muted);flex:none}\n.ya-note{font-size:13.5px;color:var(--_muted);margin-top:10px}\n\n.ya-composer-wrap{flex:none;padding:8px 12px 12px;background:var(--_bg);border-top:1px solid var(--_border)}\n.ya-tray{padding:10px;margin-bottom:8px;border-radius:calc(var(--_radius) + 2px);background:var(--_tint);animation:ya-tray .22s cubic-bezier(.2,.9,.3,1)}\n.ya-tray-h{font-size:13px;font-weight:650;margin:0 2px 8px}\n.ya-tray .ya-row{background:var(--_bg)}\n.ya-composer{display:flex;align-items:flex-end;gap:8px;padding:5px 5px 5px 16px;border-radius:24px;background:var(--_surface);border:1.5px solid transparent;transition:border-color .15s}\n.ya-composer:focus-within{border-color:color-mix(in srgb,var(--_accent) 55%,transparent)}\n.ya-composer-bar{flex:none;margin:8px 12px 12px}\n.ya-composer-input{flex:1;min-width:0;border:0;outline:none;background:none;resize:none;font:inherit;font-size:16px;line-height:1.4;color:var(--_fg);padding:7px 0;margin:0;min-height:calc(1.4em + 14px);max-height:132px;overflow-y:auto}\n.ya-composer-input::placeholder{color:var(--_muted);opacity:1}\n.ya-composer-input:focus-visible{outline:none}\n.ya-send{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;background:var(--_accent);color:var(--_accent-fg);flex:none;transition:opacity .15s,transform .12s}\n.ya-send svg{width:18px;height:18px}\n.ya-send:disabled{opacity:.3}\n.ya-shots{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;animation:ya-tray .22s cubic-bezier(.2,.9,.3,1)}\n.ya-shot{display:flex;align-items:center;gap:8px;padding:4px 4px 4px 4px;border-radius:14px;background:var(--_surface);font-size:13px;font-weight:600;max-width:100%}\n.ya-shot img{display:block;width:40px;height:40px;border-radius:10px;object-fit:cover;object-position:top;flex:none;box-shadow:0 0 0 1px var(--_border)}\n.ya-shot span{padding-right:2px}\n.ya-shot-x{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;color:var(--_muted);flex:none}\n.ya-shot-x:hover{color:var(--_fg);background:var(--_border)}\n.ya-shot-x svg{width:13px;height:13px}\n.ya-tools{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:8px;min-height:32px}\n.ya-tool{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px 0 9px;border-radius:999px;background:var(--_tint);color:var(--_accent);font-size:13.5px;font-weight:650;transition:transform .12s,opacity .15s;flex:none}\n.ya-tool svg{width:16px;height:16px}\n.ya-tool:disabled{opacity:.4}\n.ya-tool:active{transform:scale(.96)}\n.ya-switch-row{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--_muted);padding:4px 0 4px 8px;min-width:0;animation:ya-tray .2s ease-out}\n.ya-switch-row[aria-checked=true]{color:var(--_fg)}\n.ya-switch{position:relative;width:34px;height:20px;border-radius:999px;background:color-mix(in srgb,var(--_fg) 18%,var(--_bg));flex:none;transition:background .18s}\n.ya-switch::after{content:\"\";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .2s cubic-bezier(.3,1.3,.5,1)}\n[aria-checked=true] > .ya-switch{background:var(--_accent)}\n[aria-checked=true] > .ya-switch::after{transform:translateX(14px)}\n.ya-mark{text-align:center;font-size:11.5px;color:var(--_muted);margin-top:8px}\n\n\n.ya-bubble-kicker{font-size:12.5px;font-weight:650;color:var(--_muted)}\n.ya-detail-meta{display:flex;align-items:center;gap:8px}\n.ya-ref{font-size:12px;font-weight:650;color:var(--_muted);font-variant-numeric:tabular-nums;letter-spacing:.02em}\n.ya-thread{display:flex;flex-direction:column;gap:12px;margin-top:8px}\n.ya-msg{display:flex;gap:8px;align-items:flex-end;max-width:92%}\n.ya-msg .ya-avatar{border-radius:50%;margin-bottom:2px}\n.ya-msg-body{display:flex;flex-direction:column;gap:3px;min-width:0}\n.ya-msg-body .ya-bubble{max-width:100%;animation:none}\n.ya-msg-out{align-self:flex-end;flex-direction:column;align-items:flex-end;gap:3px}\n.ya-msg-out .ya-bubble{max-width:100%;animation:none}\n.ya-msg-meta{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--_muted);padding:0 4px}\n.ya-msg-meta b{color:var(--_fg);font-weight:650}\n/* ---------- board, detail */\n.ya-tabs{display:flex;gap:2px;margin:0 16px 8px;padding:3px;background:var(--_surface);border-radius:calc(var(--_radius) - 2px);flex:none}\n.ya-tab{flex:1;padding:7px 0;border-radius:calc(var(--_radius) - 5px);font-size:14px;font-weight:600;color:var(--_muted);text-align:center;transition:background .15s,color .15s}\n.ya-tab[aria-selected=true]{background:var(--_bg);color:var(--_fg);box-shadow:0 1px 3px rgba(0,0,0,.1)}\n.ya-foot{padding:12px 16px 14px;border-top:1px solid var(--_border);display:flex;flex-direction:column;gap:9px;flex:none;background:var(--_bg)}\n.ya-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:48px;padding:0 18px;border-radius:var(--_radius);background:var(--_accent);color:var(--_accent-fg);font-weight:650;font-size:15px;width:100%;transition:opacity .15s,transform .12s;white-space:nowrap}\n.ya-btn svg{width:18px;height:18px}\n.ya-btn:disabled{opacity:.4}\n.ya-btn-sm{height:38px;width:auto;padding:0 14px;font-size:14px;border-radius:calc(var(--_radius) - 3px)}\n.ya-btn-ghost{background:var(--_surface);color:var(--_fg)}\n.ya-callout{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:var(--_radius);font-size:14px;margin-top:14px;line-height:1.4;background:color-mix(in srgb,var(--_green) 12%,var(--_bg))}\n.ya-callout svg{width:18px;height:18px;margin-top:1px;color:var(--_green)}\n.ya-callout b{font-weight:650}\n.ya-detail-title{font-size:21px;font-weight:700;letter-spacing:-.015em;margin:10px 0 8px;overflow-wrap:anywhere;line-height:1.28}\n.ya-text{white-space:pre-wrap;overflow-wrap:anywhere;font-size:15px;color:var(--_fg)}\n.ya-text-muted{color:var(--_muted)}\n.ya-bigvote{margin-top:16px;display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 16px 0 12px;border-radius:999px;border:1px solid var(--_border);font-weight:650;font-size:14.5px;transition:transform .12s,background .15s,color .15s;font-variant-numeric:tabular-nums}\n.ya-bigvote svg{width:17px;height:17px}\n.ya-bigvote[aria-pressed=true]{background:var(--_accent);border-color:var(--_accent);color:var(--_accent-fg)}\n.ya-attachments{display:flex;flex-direction:column;gap:8px;margin-top:12px}\n.ya-attachments a{display:block;border-radius:var(--_radius);overflow:hidden;box-shadow:0 0 0 1px var(--_border)}\n.ya-attachments img{display:block;width:100%;height:auto;max-height:340px;object-fit:cover;object-position:top}\n.ya-early{display:flex;align-items:center;gap:12px;width:100%;margin-top:12px;padding:10px 14px 10px 12px;border-radius:var(--_radius);background:var(--_surface);animation:ya-tray .22s cubic-bezier(.2,.9,.3,1)}\n.ya-early .ya-card-icon{width:32px;height:32px}\n.ya-early[aria-checked=true] .ya-card-icon{background:var(--_accent);color:var(--_accent-fg)}\n.ya-credit{display:block;margin-top:2px;color:var(--_muted)}\n.ya-section-h{font-size:13px;font-weight:650;color:var(--_muted);margin:26px 0 4px}\n.ya-comment{padding:11px 0;border-bottom:1px solid var(--_border)}\n.ya-comment:last-child{border-bottom:0}\n.ya-comment-who{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:650;margin-bottom:3px}\n.ya-comment-who time{font-weight:400;color:var(--_muted)}\n.ya-team{font-size:11px;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--_accent);color:var(--_accent-fg)}\n.ya-empty{text-align:center;padding:44px 16px;color:var(--_muted)}\n.ya-empty b{display:block;color:var(--_fg);font-size:16px;margin-bottom:4px}\n.ya-skel{height:58px;border-radius:var(--_radius);background:var(--_surface);animation:ya-pulse 1.3s ease-in-out infinite}\n\n/* ---------- launcher, toast */\n.ya-fab{position:fixed;z-index:2147483650;bottom:calc(var(--_offset) + env(safe-area-inset-bottom));right:20px;height:56px;min-width:56px;padding:0;border-radius:999px;background:var(--_accent);color:var(--_accent-fg);display:flex;align-items:center;justify-content:center;gap:8px;font-weight:650;font-size:15px;box-shadow:0 10px 30px color-mix(in srgb,var(--_accent) 35%,rgba(0,0,0,.25));transition:transform .15s}\n.ya-fab-label{padding:0 20px 0 16px}\n.ya-fab-icon{display:grid;place-items:center}\n.ya-fab svg{width:26px;height:26px}\n.ya-fab[data-open] svg{width:22px;height:22px}\n.ya-fab[data-pos=bottom-left]{right:auto;left:20px}\n.ya-fab .ya-dot{position:absolute;top:4px;right:4px}\n.ya-fab-label .ya-dot{position:static}\n@media (max-width:639px){.ya-fab[data-open]{display:none}}\n.ya-dot{width:10px;height:10px;border-radius:50%;background:#ff3b30;box-shadow:0 0 0 2px var(--_bg)}\n\n.ya-toast{position:fixed;z-index:2147483550;right:20px;bottom:calc(var(--_offset) + 68px + env(safe-area-inset-bottom));width:min(370px,calc(100vw - 32px));background:var(--_bg);color:var(--_fg);border:1px solid var(--_border);border-radius:calc(var(--_radius) + 6px);box-shadow:0 20px 60px rgba(0,0,0,.25);padding:16px 16px 14px;animation:ya-pop .45s cubic-bezier(.34,1.36,.64,1)}\n.ya-toast[data-pos=bottom-left]{right:auto;left:20px}\n.ya-toast[data-trigger=none]{bottom:calc(var(--_offset) + env(safe-area-inset-bottom))}\n@media (max-width:480px){.ya-toast,.ya-toast[data-pos=bottom-left]{left:16px;right:16px;width:auto}}\n.ya-toast-top{display:flex;align-items:center;justify-content:space-between;gap:8px}\n.ya-toast-kicker{font-size:12.5px;font-weight:650;color:var(--_muted)}\n.ya-toast-title{font-size:17px;font-weight:750;letter-spacing:-.01em;margin-top:3px;overflow-wrap:anywhere;line-height:1.3}\n.ya-live{display:inline-flex;align-items:center;gap:6px;font-size:14px;font-weight:700;color:var(--_green)}\n.ya-toast .ya-live{margin-top:8px}\n.ya-live svg{width:15px;height:15px}\n.ya-toast-note{font-size:13.5px;color:var(--_muted);margin-top:6px;overflow-wrap:anywhere}\n.ya-toast-actions{display:flex;gap:8px;margin-top:12px}\n.ya-toast-quote{color:var(--_fg);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}\n.ya-toast .ya-icon-btn{width:30px;height:30px;margin:-6px -6px 0 0;background:none}\n\n/* ---------- inline entry points */\n.ya-askbar{display:flex;align-items:center;gap:12px;width:100%;padding:8px 8px 8px 10px;border-radius:999px;background:var(--_bg);border:1px solid var(--_border);color:var(--_muted);font-size:15.5px;text-align:left;box-shadow:0 1px 2px rgba(0,0,0,.04);transition:border-color .15s,transform .12s}\n.ya-askbar:hover{border-color:color-mix(in srgb,var(--_accent) 50%,var(--_border))}\n.ya-askbar .ya-avatar{border-radius:30%}\n.ya-askbar-glyph{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;background:var(--_tint);color:var(--_accent);flex:none}\n.ya-askbar-glyph svg{width:18px;height:18px}\n.ya-askbar-text{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ya-askbar-send{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--_accent);color:var(--_accent-fg);flex:none}\n.ya-askbar-send svg{width:17px;height:17px}\n.ya-badge{min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:#ff3b30;color:#fff;font-size:12px;font-weight:700;display:inline-grid;place-items:center;flex:none}\n\n.ya-card{background:var(--_bg);border-radius:calc(var(--_radius) + 6px);padding:16px;display:flex;flex-direction:column;gap:12px}\n.ya-card-head{display:flex;align-items:center;gap:12px}\n.ya-card-icon{width:36px;height:36px;border-radius:30%;display:grid;place-items:center;background:var(--_tint);color:var(--_accent);flex:none}\n.ya-card-icon svg{width:19px;height:19px}\n.ya-card-title{font-size:16px;font-weight:700;letter-spacing:-.01em}\n.ya-card-sub{font-size:13px;color:var(--_muted);margin-top:1px}\n.ya-card-win{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_green) 12%,var(--_bg));font-size:14px;text-align:left}\n.ya-card-win > span:nth-child(2){flex:1;min-width:0}\n.ya-card-win b{font-weight:650}\n.ya-card-actions{display:flex;gap:8px}\n.ya-card-actions .ya-btn{flex:1}\n\n.ya-pillbtn{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 16px 0 13px;border-radius:999px;background:var(--_tint);color:var(--_accent);font-weight:650;font-size:14.5px;transition:transform .12s}\n.ya-pillbtn svg{width:18px;height:18px}\n.ya-pillbtn .ya-badge{margin-right:-6px}\n.ya-iconbtn{position:relative;width:40px;height:40px;border-radius:50%;display:grid;place-items:center;background:var(--_surface);color:var(--_fg);transition:transform .12s}\n.ya-iconbtn svg{width:21px;height:21px}\n.ya-iconbtn .ya-dot{position:absolute;top:1px;right:1px;width:9px;height:9px}\n.ya-menurow{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;border-radius:var(--_radius);background:var(--_bg);text-align:left;color:var(--_fg)}\n.ya-menurow > svg{color:var(--_muted);width:17px;height:17px}\n.ya-menurow .ya-card-icon{width:32px;height:32px}\n.ya-menurow-text{flex:1;min-width:0;display:flex;flex-direction:column}\n.ya-menurow-label{font-size:15.5px;font-weight:600}\n.ya-menurow-sub{font-size:13px;color:var(--_muted)}\n\n.ya-askabout{display:inline-flex;align-items:center;gap:6px;font-size:13.5px;line-height:1.3;color:var(--_muted);padding:2px 0;border-radius:6px;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;transition:color .15s,text-decoration-color .15s}\n.ya-askabout svg{width:14px;height:14px;color:var(--_accent)}\n.ya-askabout:hover{color:var(--_fg);text-decoration-color:currentColor}\n.ya-askforit{display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 8px;font-size:14.5px;color:var(--_muted);padding:4px 0;text-align:left}\n.ya-askforit b{white-space:nowrap;display:inline-flex;align-items:center;gap:1px;font-weight:650;color:var(--_accent);padding:3px 6px 3px 12px;border-radius:999px;background:var(--_tint);transition:transform .12s}\n.ya-askforit b svg{width:15px;height:15px}\n.ya-askforit:active b{transform:scale(.96)}\n\n/* ---------- show us: draw on the page */\n.ya-capture{position:fixed;inset:0;z-index:2147483640;animation:ya-fade .18s ease-out}\n.ya-capture-sample{position:absolute;color:var(--_accent);width:0;height:0;overflow:hidden}\n.ya-capture-surface{position:absolute;inset:0;background:rgba(8,10,20,.2);cursor:crosshair;touch-action:none;-webkit-user-select:none;user-select:none}\n.ya-capture-box{position:absolute;border:3px solid var(--_accent);border-radius:8px;background:var(--_tint);box-shadow:0 0 0 2px rgba(255,255,255,.92);pointer-events:none}\n.ya-capture-hint{position:absolute;top:calc(14px + env(safe-area-inset-top));left:50%;transform:translateX(-50%);max-width:calc(100vw - 24px);white-space:nowrap;padding:9px 16px;border-radius:999px;background:var(--_bg);color:var(--_fg);font-size:14px;font-weight:650;text-align:center;box-shadow:0 6px 24px rgba(0,0,0,.25);pointer-events:none;animation:ya-pop .35s cubic-bezier(.34,1.36,.64,1)}\n.ya-capture-bar{position:absolute;left:50%;transform:translateX(-50%);bottom:calc(18px + env(safe-area-inset-bottom));display:flex;gap:8px;padding:8px;border-radius:calc(var(--_radius) + 8px);background:var(--_bg);box-shadow:0 10px 40px rgba(0,0,0,.3),0 0 0 1px var(--_border)}\n.ya-capture-bar .ya-btn{min-width:84px}\n.ya-capture[data-busy] .ya-capture-surface{cursor:progress}\n\n.ya-embed{position:relative;display:flex;flex-direction:column;background:var(--_bg);border-radius:calc(var(--_radius) + 6px);overflow:hidden;border:1px solid var(--_border)}\n\n.ya-sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n\n@keyframes ya-sheet-in{from{transform:translateY(100%)}}\n@keyframes ya-sheet-out{to{transform:translateY(100%)}}\n@keyframes ya-pop-in{from{transform:translateY(12px) scale(.96);opacity:0}}\n@keyframes ya-pop-out{to{transform:translateY(8px) scale(.97);opacity:0}}\n@keyframes ya-fade{from{opacity:0}}\n@keyframes ya-fade-out{to{opacity:0}}\n@keyframes ya-pop{from{transform:translateY(14px) scale(.96);opacity:0}}\n@keyframes ya-bubble{from{transform:translateY(8px) scale(.97);opacity:0}}\n@keyframes ya-tray{from{transform:translateY(6px);opacity:0}}\n@keyframes ya-dot{0%,80%,100%{transform:translateY(0);opacity:.5}40%{transform:translateY(-4px);opacity:1}}\n@keyframes ya-confetti{0%{opacity:1;transform:translate(0,0) rotate(0) scale(.6)}70%{opacity:1}100%{opacity:0;transform:translate(var(--x),var(--y)) rotate(var(--r)) scale(1)}}\n@keyframes ya-pulse{50%{opacity:.5}}\n@media (prefers-reduced-motion:reduce){.ya-scope *{animation:none!important;transition:none!important}}\n";
2
+ export declare function injectStyles(): void;
@@ -0,0 +1,32 @@
1
+ export type Appearance = {
2
+ /** "auto" follows the host page (a `.dark` class, data-theme, or its background). */
3
+ mode?: "auto" | "light" | "dark";
4
+ /** Brand colour for buttons, votes and links. Any CSS colour, including `var(--your-token)`. */
5
+ accent?: string;
6
+ accentForeground?: string;
7
+ background?: string;
8
+ foreground?: string;
9
+ muted?: string;
10
+ surface?: string;
11
+ border?: string;
12
+ radius?: string | number;
13
+ fontFamily?: string;
14
+ /** Set false to ignore the host's shadcn-style tokens (--primary, --background, …). */
15
+ inherit?: boolean;
16
+ };
17
+ type Tokens = {
18
+ mode: "light" | "dark";
19
+ accent: string;
20
+ accentForeground?: string;
21
+ background: string;
22
+ foreground: string;
23
+ muted?: string;
24
+ surface?: string;
25
+ border?: string;
26
+ radius: string;
27
+ fontFamily: string;
28
+ };
29
+ export declare function hostIsDark(): boolean;
30
+ export declare function resolveTokens(appearance?: Appearance): Tokens;
31
+ export declare function tokenStyle(t: Tokens): Record<string, string>;
32
+ export {};
@@ -0,0 +1,9 @@
1
+ import { type Route } from "./context";
2
+ type NavProps = {
3
+ route: Route;
4
+ setRoute: (r: Route) => void;
5
+ onClose?: () => void;
6
+ };
7
+ /** Renders the current screen. Shared by the overlay sheet and the embedded page. */
8
+ export declare function Navigator({ route, setRoute, onClose }: NavProps): import("react").JSX.Element;
9
+ export {};
package/package.json CHANGED
@@ -1,6 +1,67 @@
1
1
  {
2
2
  "name": "@youasked/react",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.1",
4
+ "description": "Feature requests your users can vote on, and a 'you asked, it's live' moment when you ship.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./server": {
17
+ "types": "./dist/server.d.ts",
18
+ "import": "./dist/server.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "build": "node build.mjs && tsc -p tsconfig.json --emitDeclarationOnly",
28
+ "typecheck": "tsc -p tsconfig.json --noEmit",
29
+ "playground": "esbuild playground/main.tsx --bundle --splitting --format=esm --jsx=automatic --entry-names=bundle --outdir=playground/out",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "peerDependencies": {
33
+ "react": ">=18",
34
+ "react-dom": ">=18"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "^19.2.0",
38
+ "@types/react-dom": "^19.2.0",
39
+ "esbuild": "^0.25.0",
40
+ "modern-screenshot": "^4.7.0",
41
+ "react": "^19.2.0",
42
+ "react-dom": "^19.2.0",
43
+ "typescript": "^5.9.3"
44
+ },
45
+ "author": "Aden Teo",
46
+ "homepage": "https://youasked.adenteo.workers.dev",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/youasked/youasked.git",
50
+ "directory": "packages/react"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/youasked/youasked/issues"
54
+ },
55
+ "keywords": [
56
+ "react",
57
+ "nextjs",
58
+ "feature-requests",
59
+ "feedback",
60
+ "widget",
61
+ "roadmap",
62
+ "changelog"
63
+ ],
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }