resume-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev 3f16b2375723
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 70bace54357d4b57b674108f
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/ui.tsx
// Small shared pieces on the kit: dialog (a bottom sheet on phones), ask() for confirmations, dropdown menu,
// toast with an optional action, copy-to-clipboard, share and file download. Each one animates in and out.
import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type ReactNode } from "react";

/** A sentence a person can read for a failed write or read. */
export function explain(err: unknown): string {
  const e = err as { message?: string; status?: number; decline?: { message?: string } };
  if (e?.decline?.message) return e.decline.message;
  const msg = String(e?.message || err || "");
  if (/network|fetch|Failed to fetch|offline/i.test(msg) || (typeof navigator !== "undefined" && navigator.onLine === false)) return "You seem to be offline. Check your connection and try again.";
  if (/denied|403|forbidden/i.test(msg)) return "That change was not allowed.";
  return msg || "Something went wrong. Try again.";
}

const FOCUSABLE = "a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), summary, [tabindex]:not([tabindex='-1'])";
type Slot = ReactNode | ((close: () => void) => ReactNode);
const fill = (slot: Slot, close: () => void) => (typeof slot === "function" ? slot(close) : slot);

/** A dialog. onClose runs once its exit animation ends; children and footer can take a close function. */
export function Dialog({ title, onClose, children, footer }: { title: string; onClose: () => void; children: Slot; footer?: Slot }) {
  const [leaving, setLeaving] = useState(false);
  const box = useRef<HTMLDivElement>(null);
  const close = () => setLeaving(true);
  useEffect(() => {
    const prev = document.activeElement as HTMLElement | null;
    document.body.style.overflow = "hidden";
    // autoFocus inside wins; otherwise the first field, otherwise the dialog itself.
    if (!box.current?.contains(document.activeElement)) (box.current?.querySelector<HTMLElement>(".dialog-body :is(input, textarea, select)") ?? box.current)?.focus();
    return () => {
      document.body.style.overflow = "";
      prev?.focus?.();
    };
  }, []);
  const onKey = (e: ReactKeyboardEvent) => {
    if (e.key === "Escape") { e.stopPropagation(); close(); }
    if (e.key !== "Tab" || !box.current) return;
    const items = [...box.current.querySelectorAll<HTMLElement>(FOCUSABLE)];
    if (!items.length) return;
    const [a, z] = [items[0], items[items.length - 1]];
    if (e.shiftKey && document.activeElement === a) { e.preventDefault(); z.focus(); }
    else if (!e.shiftKey && document.activeElement === z) { e.preventDefault(); a.focus(); }
  };
  return (
    <div className={`dialog-backdrop${leaving ? " leaving" : ""}`} onMouseDown={(e) => { if (e.target === e.currentTarget) close(); }} onKeyDown={onKey}>
      <div className="dialog" role="dialog" aria-modal="true" aria-labelledby="dialog-title" tabIndex={-1} ref={box}
        onAnimationEnd={(e) => { if (leaving && e.target === e.currentTarget) onClose(); }}>
        <div className="dialog-head">
          <h2 className="dialog-title" id="dialog-title">{title}</h2>
          <button className="btn btn-quiet btn-icon btn-sm" type="button" onClick={close} aria-label="Close">
            <svg width="18" height="18" viewBox="0 0 20 20" aria-hidden="true"><path d="M5 5l10 10M15 5 5 15" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" /></svg>
          </button>
        </div>
        <div className="dialog-body">{fill(children, close)}</div>
        {footer && <div className="dialog-foot">{fill(footer, close)}</div>}
      </div>
    </div>
  );
}

interface Ask { title: string; body?: ReactNode; confirm: string; cancel?: string; danger?: boolean; resolve: (ok: boolean) => void }
let pushAsk: ((a: Ask) => void) | null = null;

/** Asks a yes-or-no question in a dialog. Resolves true when the person confirms. */
export function ask(q: Omit<Ask, "resolve">): Promise<boolean> {
  return new Promise((resolve) => (pushAsk ? pushAsk({ ...q, resolve }) : resolve(window.confirm(q.title))));
}

/** Mount once: shows ask() dialogs. */
export function AskHost() {
  const [q, setQ] = useState<Ask | null>(null);
  const answer = useRef(false);
  useEffect(() => {
    pushAsk = (next) => { answer.current = false; setQ(next); };
    return () => { pushAsk = null; };
  }, []);
  if (!q) return null;
  return (
    <Dialog title={q.title} onClose={() => { q.resolve(answer.current); setQ(null); }} footer={(close) => (
      <>
        <button className="btn btn-line" type="button" autoFocus={q.danger} onClick={close}>{q.cancel ?? "Cancel"}</button>
        <button className={`btn${q.danger ? " btn-danger-solid" : ""}`} type="button" autoFocus={!q.danger} onClick={() => { answer.current = true; close(); }}>{q.confirm}</button>
      </>
    )}>
      {q.body && <p className="muted">{q.body}</p>}
    </Dialog>
  );
}

interface Toast { id: number; text: string; action?: { label: string; run: () => void }; leaving?: boolean }
let pushToast: ((t: Omit<Toast, "id">) => void) | null = null;

/** A short message at the bottom of the screen; with an action (Undo), it stays a little longer. */
export function toast(text: string, action?: Toast["action"]) { pushToast?.({ text, action }); }

export function Toaster() {
  const [t, setT] = useState<Toast | null>(null);
  useEffect(() => {
    let timer: number | undefined;
    let n = 0;
    pushToast = (next) => {
      const id = ++n;
      setT({ ...next, id });
      window.clearTimeout(timer);
      timer = window.setTimeout(() => setT((cur) => (cur?.id === id ? { ...cur, leaving: true } : cur)), next.action ? 6000 : 2600);
    };
    return () => { pushToast = null; window.clearTimeout(timer); };
  }, []);
  if (!t) return null;
  return (
    <div className={`toast${t.leaving ? " leaving" : ""}`} role="status" key={t.id} onAnimationEnd={() => { if (t.leaving) setT(null); }}>
      <span>{t.text}</span>
      {t.action && <button className="toast-action" type="button" onClick={() => { t.action!.run(); setT({ ...t, action: undefined, leaving: true }); }}>{t.action.label}</button>}
    </div>
  );
}

export async function copy(text: string, done = "Copied.") {
  try {
    await navigator.clipboard.writeText(text);
    toast(done);
  } catch {
    window.prompt("Copy this:", text);
  }
}

export async function share(url: string, title: string) {
  if (navigator.share && matchMedia("(pointer: coarse)").matches) {
    try { await navigator.share({ title, url }); return; } catch { /* cancelled */ }
  }
  await copy(url, "Link copied.");
}

/** Hands a file to the browser as a download. */
export function saveFile(name: string, blob: Blob) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = name;
  document.body.appendChild(a);
  a.click();
  a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 10_000);
}

export type MenuItem = { label: ReactNode; onSelect: () => void; danger?: boolean; checked?: boolean; hint?: string } | "-" | { heading: string };

/** A button that opens a short menu. up opens it above the button (for bars at the bottom of the screen).
 * items can be a function, read only while the menu is open. */
export function Menu({ label, items, disabled, end, up, className = "btn btn-line", ariaLabel }: {
  label: ReactNode; items: MenuItem[] | (() => MenuItem[]); disabled?: boolean; end?: boolean; up?: boolean; className?: string; ariaLabel?: string;
}) {
  const [state, setState] = useState<"closed" | "open" | "leaving">("closed");
  const root = useRef<HTMLDivElement>(null);
  const button = useRef<HTMLButtonElement>(null);
  const close = (refocus = false) => {
    setState((s) => (s === "open" ? "leaving" : s));
    if (refocus) button.current?.focus();
  };
  useEffect(() => {
    if (state !== "open") return;
    const away = (e: Event) => { if (!root.current?.contains(e.target as Node)) close(); };
    document.addEventListener("pointerdown", away);
    root.current?.querySelector<HTMLElement>(".dropdown-menu [role=menuitem], .dropdown-menu [role=menuitemradio]")?.focus();
    return () => document.removeEventListener("pointerdown", away);
  }, [state]);
  const onKey = (e: ReactKeyboardEvent) => {
    if (state !== "open") return;
    if (e.key === "Escape" || e.key === "Tab") { if (e.key === "Escape") e.preventDefault(); close(e.key === "Escape"); return; }
    if (e.key !== "ArrowDown" && e.key !== "ArrowUp" && e.key !== "Home" && e.key !== "End") return;
    e.preventDefault();
    const all = [...(root.current?.querySelectorAll<HTMLElement>(".dropdown-menu button") ?? [])];
    const i = all.indexOf(document.activeElement as HTMLElement);
    const next = e.key === "Home" ? 0 : e.key === "End" ? all.length - 1 : (i + (e.key === "ArrowDown" ? 1 : -1) + all.length) % all.length;
    all[next]?.focus();
  };
  return (
    <div className="dropdown" ref={root} onKeyDown={onKey}>
      <button ref={button} className={className} type="button" aria-haspopup="menu" aria-expanded={state === "open"} aria-label={ariaLabel}
        onClick={() => setState((s) => (s === "open" ? "leaving" : "open"))} disabled={disabled}>
        {label}
      </button>
      {state !== "closed" && (
        <div className={`dropdown-menu${end ? " dropdown-menu-end" : ""}${up ? " dropdown-menu-up" : ""}${state === "leaving" ? " leaving" : ""}`} role="menu"
          onAnimationEnd={() => { if (state === "leaving") setState("closed"); }}>
          {(typeof items === "function" ? items() : items).map((it, i) => it === "-" ? <hr key={i} /> : "heading" in it ? <p key={i} className="menu-heading">{it.heading}</p> : (
            <button key={i} type="button" role={it.checked != null ? "menuitemradio" : "menuitem"} aria-checked={it.checked} className={it.danger ? "danger" : undefined}
              onClick={() => { close(true); it.onSelect(); }}>
              {it.checked != null && <span className="menu-check" aria-hidden="true">{it.checked ? <Check /> : null}</span>}
              <span className="menu-label">{it.label}{it.hint && <small>{it.hint}</small>}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

export const Check = () => <svg width="16" height="16" viewBox="0 0 20 20" aria-hidden="true"><path d="m4.5 10.5 3.5 3.5 7.5-8" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /></svg>;
export const Chevron = () => <svg width="14" height="14" viewBox="0 0 20 20" aria-hidden="true"><path d="m5 8 5 5 5-5" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /></svg>;
export const Dots = () => <svg width="18" height="18" viewBox="0 0 20 20" aria-hidden="true"><circle cx="4.5" cy="10" r="1.4" fill="currentColor" /><circle cx="10" cy="10" r="1.4" fill="currentColor" /><circle cx="15.5" cy="10" r="1.4" fill="currentColor" /></svg>;
export const DownloadIcon = () => <svg width="16" height="16" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v10m0 0 4-4m-4 4L6 9M4 16h12" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" /></svg>;

/** The shared resume page while it opens: the same frame as the page, so nothing jumps when it arrives. */
export function ResumeSkeleton() {
  return (
    <div className="doc" aria-busy="true" aria-label="Opening the resume">
      <div className="doc-head">
        <div className="wrap doc-head-inner">
          <div className="doc-head-text">
            <span className="skeleton skeleton-text" style={{ width: 70 }} />
            <span className="skeleton" style={{ width: "min(420px, 80%)", height: 40, marginTop: 10 }} />
            <span className="skeleton skeleton-text" style={{ width: 180, marginTop: 12 }} />
          </div>
        </div>
      </div>
      <div className="wrap doc-body">
        <div className="doc-paper"><span className="skeleton sheet-skeleton" /></div>
      </div>
    </div>
  );
}

Change history

Quality pass: several resumes, cover letters, phone-readable shared pages
3f16b23757 · 5 hours ago
Bounded source sync
b7eb5b26b5 · 1 day ago
Bounded source sync
adae97536e · 1 day ago
Bounded source sync
3b0cf36b39 · 1 day ago