@8ux-co/eelzap 0.10.1 → 0.10.2

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 @@
1
+ {"version":3,"sources":["../src/preview/site/api.ts","../src/preview/site/drag.ts","../src/preview/site/draft-session.ts","../src/preview/site/suggestion.ts","../src/preview/site/session.ts","../src/preview/site/suggest.ts"],"sourcesContent":["import type { SiteContext } from './config'\n\n/**\n * The site tools' calls to Zap's public API with the site client's\n * bearer (ADR 041 §3 to §5). The browser sends `Origin`; Zap checks it\n * against the site's preview origins and answers CORS to that origin only.\n *\n * Every answer becomes one of a few outcomes the UI words:\n *\n * - `expired` (401): the hour is up or the token was revoked; sign in again.\n * - `refused`: a network error. A request Zap refuses for a wrong origin,\n * another site or Live mode off carries NO CORS headers, so the page sees a\n * network error, not a 403; the UI says «No puedes editar ni comentar en\n * este sitio».\n * - `forbidden` (a readable 403: no Zap seat, or «Editar» turned off for this\n * site on the save-to-draft route).\n * - `rate` (429) with `Retry-After` seconds.\n * - `unchanged` (409 `NO_CHANGE`): «Editar» saved what the draft already holds.\n * - `invalid` for anything else.\n *\n * Creates are idempotent: the caller passes the `Idempotency-Key`, kept for\n * one payload so a retry after a 429 or a dropped answer cannot open two\n * threads.\n */\n\nexport type ApiFailure =\n | { ok: false; kind: 'expired' | 'refused' | 'forbidden' | 'invalid' | 'unchanged' }\n | { ok: false; kind: 'rate'; retryAfter: number }\n\nexport type ApiResult<T> = { ok: true; data: T } | ApiFailure\n\nexport interface FieldInfo {\n type: string\n label: string\n /** ENUM: the options in order, by id (what a save sends) and label (what shows). */\n options?: Array<{ id: string; label: string }>\n /** NUMBER, INTEGER, CURRENCY: the field's constraints, when it has them. */\n min?: number\n max?: number\n step?: number\n /** CURRENCY: the ISO 4217 code a value is in (its amount travels in minor units). */\n currency?: string\n}\n\n/**\n * A field's value as «Editar» reads and saves it beside text: an ENUM's\n * option id, a number (CURRENCY in minor units), `YYYY-MM-DD` for a DATE, an\n * ISO string for a DATETIME, a boolean, or null when empty.\n */\nexport type RawValue = string | number | boolean | null\n\nexport interface OnPageAnchor {\n fieldKey: string | null\n tag: string | null\n selector: string | null\n rect: { x: number; y: number; w: number; h: number } | null\n /** A pin placed on a point of the page (fractions of the whole document). */\n spot: { x: number; y: number } | null\n}\n\nexport interface OnPageComment {\n id: string\n status: 'OPEN'\n isChangeRequest: boolean\n createdAt: string\n author: { name: string | null } | null\n excerpt: string | null\n anchors: OnPageAnchor[]\n}\n\nexport interface OnPage {\n /**\n * The caller's own name and email, and `editorUrl`: the absolute Zap editor\n * URL of the record this page is, or null (optional: older Zaps omit both).\n */\n viewer: { name: string | null; email?: string | null; editorUrl?: string | null }\n /** Whether «Editar» is on for this site (the ADMIN's `liveEditing` switch). */\n liveEditing: boolean\n fields: Record<string, Record<string, FieldInfo>>\n /**\n * The tagged records that are not the record this page is, by ref, to\n * their name: their fields read «… en Configuración» (optional: older\n * Zaps omit it).\n */\n records?: Record<string, string>\n /**\n * The current value (the draft's, else the published one) of each ENUM,\n * NUMBER, INTEGER, CURRENCY, DATE, DATETIME and BOOLEAN field of the tagged\n * records, by ref and field key: what «Editar» opens with, since the page\n * shows them formatted (optional: older Zaps omit it). Never text.\n */\n values?: Record<string, Record<string, RawValue>>\n /** Each tagged record's editor in Zap, by ref, for «Abrir en Zap» on its fields. */\n editorUrls?: Record<string, string>\n comments: OnPageComment[]\n truncated: boolean\n}\n\n/** An element anchor (with its field when tagged), or a point of the page. */\nexport type ApiAnchor =\n | {\n field?: { key: string; locale?: string | null }\n dom: {\n tag?: string\n selector?: string\n textQuote?: { exact: string; prefix: string; suffix: string }\n rect: { x: number; y: number; w: number; h: number }\n viewport: { w: number; h: number }\n }\n }\n | { spot: { x: number; y: number }; viewport: { w: number; h: number } }\n\nexport interface CreateBody {\n collection?: string\n slug?: string\n document?: string\n /** «Solicitar cambio»: a change request, assigned by Zap to the record's Responsable. */\n isChangeRequest: boolean\n locale?: string\n /** The page the anchors were made on; element anchors need it. */\n pageUrl: string\n anchors: ApiAnchor[]\n body: string\n proposedValues?: Array<{ fieldKey: string; locale?: string; value: RawValue }>\n}\n\n/** «Editar» saves to the draft: always a resolved change request, so no flag. */\nexport type DraftBody = Omit<CreateBody, 'isChangeRequest'>\n\nconst BASE = '/api/public/v1/comments'\n\nasync function call<T>(\n ctx: Pick<SiteContext, 'win' | 'zapOrigin'>,\n token: string,\n path: string,\n init: { method: 'GET' | 'POST'; body?: unknown; idempotencyKey?: string },\n): Promise<ApiResult<T>> {\n const headers: Record<string, string> = { Authorization: `Bearer ${token}` }\n if (init.body !== undefined) headers['Content-Type'] = 'application/json'\n if (init.idempotencyKey) headers['Idempotency-Key'] = init.idempotencyKey\n let response: Response\n try {\n response = await ctx.win.fetch(`${ctx.zapOrigin}${path}`, {\n method: init.method,\n headers,\n credentials: 'omit',\n body: init.body === undefined ? undefined : JSON.stringify(init.body),\n })\n } catch {\n return { ok: false, kind: 'refused' }\n }\n if (response.status === 401) return { ok: false, kind: 'expired' }\n if (response.status === 403) return { ok: false, kind: 'forbidden' }\n if (response.status === 429) {\n const seconds = Number.parseInt(response.headers.get('Retry-After') ?? '', 10)\n return { ok: false, kind: 'rate', retryAfter: seconds > 0 ? Math.min(seconds, 3600) : 30 }\n }\n // 409 NO_CHANGE: the value already is the stored one (save-to-draft); any\n // other 409 (a duplicate of a unique value) is a failure.\n if (response.status === 409) {\n const body = (await response.json().catch(() => null)) as { error?: { code?: unknown } } | null\n if (body?.error?.code === 'NO_CHANGE') return { ok: false, kind: 'unchanged' }\n }\n if (!response.ok) return { ok: false, kind: 'invalid' }\n try {\n return { ok: true, data: (await response.json()) as T }\n } catch {\n return { ok: false, kind: 'invalid' }\n }\n}\n\nexport function fetchOnPage(\n ctx: Pick<SiteContext, 'win' | 'zapOrigin'>,\n token: string,\n pageUrl: string,\n refs: readonly string[],\n): Promise<ApiResult<OnPage>> {\n const query = new URLSearchParams({ url: pageUrl })\n if (refs.length > 0) query.set('refs', refs.slice(0, 20).join(','))\n return call<OnPage>(ctx, token, `${BASE}/on-page?${query.toString()}`, { method: 'GET' })\n}\n\n/** The part of the create answer the toast reads: who the request went to. */\nexport interface CreateAnswer {\n thread: { id: string; assignee?: { name: string | null } | null }\n}\n\nexport function createComment(\n ctx: Pick<SiteContext, 'win' | 'zapOrigin'>,\n token: string,\n body: CreateBody,\n idempotencyKey: string,\n): Promise<ApiResult<CreateAnswer>> {\n return call(ctx, token, BASE, { method: 'POST', body, idempotencyKey })\n}\n\nexport function saveToDraft(\n ctx: Pick<SiteContext, 'win' | 'zapOrigin'>,\n token: string,\n body: DraftBody,\n idempotencyKey: string,\n): Promise<ApiResult<{ thread: { id: string }; draftVersionId: string }>> {\n return call(ctx, token, `${BASE}/save-to-draft`, { method: 'POST', body, idempotencyKey })\n}\n\n/** A random Idempotency-Key (a v4-shaped UUID). */\nexport function newIdempotencyKey(win: Window): string {\n const native = (win.crypto as Crypto & { randomUUID?: () => string }).randomUUID\n if (typeof native === 'function') return native.call(win.crypto)\n const bytes = win.crypto.getRandomValues(new Uint8Array(16))\n bytes[6] = (bytes[6]! & 0x0f) | 0x40\n bytes[8] = (bytes[8]! & 0x3f) | 0x80\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`\n}\n","import { el, icon, TOKENS as T } from './ui'\n\n/**\n * Moving the live site's toolbar (the `suggest` chunk's «Navegar», «Editar»,\n * «Comentar» pill) by a grip at its far left.\n *\n * - **Where it sits.** Nothing stored: the default bottom centre of the\n * `.bottom` stack, untouched (the zone sites leave free for it, signin.ts).\n * Once moved: the bar's top left, clamped to the viewport with a 16px\n * gutter on every layout, resize and orientation change.\n * - **What rides with it.** The cards stacked with the bar (the open\n * comments, the selection tray, the save status) open on the side with\n * more room, above or below, centred on the bar and kept inside the\n * viewport.\n * - **Remembered** per site origin in the page's `localStorage`, with\n * whether the bar is hidden (`{ x, y, hidden }`, every part optional);\n * every access may throw (private mode, blocked storage) and is caught. A\n * double click (or double tap) on the grip puts the bar back and forgets\n * the place.\n * - **Hidden** (SitioBarraEstados «Barra oculta»): the pill takes the bar's\n * place, the same stored point or the default bottom centre, under the same\n * clamp and resize rules. The pill itself is the grip (`grab`): a press\n * that moves 3px or more drags it and is not a click; the place it lands\n * is the bar's.\n * - **The account menu** rides in the stack too, right aligned under the\n * account chip, above the bar or below it as the cards are.\n * - **Pointer and keys.** Pointer events with capture and `touch-action:\n * none`; the arrow keys move it 16px (64px with Shift). Nothing the grip\n * receives reaches the site: its pointer, mouse, touch and click events\n * stop at the grip.\n */\n\nexport const BAR_STORAGE_KEY = 'eelzap:bar'\n\nconst GUTTER = 16\nconst STEP = 16\nconst BIG_STEP = 64\nconst GAP = 10\n/** A press that moves less than this is a click, not a drag. */\nconst SLOP = 3\nconst DOUBLE_MS = 400\n\ninterface Point {\n x: number\n y: number\n}\n\nexport interface BarDrag {\n /** The grip, one node for the bar's whole life: each render moves it into the new toolbar. */\n handle: HTMLButtonElement\n /** Whether the bar shows as the pill, remembered next to the place. */\n hidden(): boolean\n setHidden(value: boolean): void\n /** Make `node` (the pill) drag the stack too; its click after a drag is swallowed. */\n grab(node: HTMLElement): HTMLElement\n /** Lay out the stack again; call after every render of it. */\n place(): void\n destroy(): void\n}\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), Math.max(min, max))\n\nfunction storage(win: Window): Storage | null {\n try {\n return win.localStorage\n } catch {\n return null\n }\n}\n\nfunction read(win: Window): { pos: Point | null; hidden: boolean } {\n try {\n const value = JSON.parse(storage(win)?.getItem(BAR_STORAGE_KEY) ?? 'null') as\n | (Partial<Point> & { hidden?: unknown })\n | null\n return {\n pos:\n value && Number.isFinite(value.x) && Number.isFinite(value.y)\n ? { x: value.x!, y: value.y! }\n : null,\n hidden: value?.hidden === true,\n }\n } catch {\n return { pos: null, hidden: false }\n }\n}\n\nfunction write(win: Window, point: Point | null, hidden: boolean): void {\n try {\n const store = storage(win)\n if (point || hidden)\n store?.setItem(BAR_STORAGE_KEY, JSON.stringify({ ...point, hidden: hidden || undefined }))\n else store?.removeItem(BAR_STORAGE_KEY)\n } catch {\n // Storage full or blocked: the bar still moves, it just is not remembered.\n }\n}\n\nexport function barDrag(\n win: Window,\n doc: Document,\n stack: HTMLElement,\n label: string,\n tip: string,\n): BarDrag {\n const saved = read(win)\n let pos = saved.pos\n let hidden = saved.hidden\n let drag: {\n id: number\n px: number\n py: number\n from: Point\n moved: boolean\n node: HTMLElement\n } | null = null\n /** The press that just ended was a drag: its click is not one. */\n let dragged = false\n let lastTap = 0\n\n const viewport = (): [number, number] => {\n const root = doc.documentElement\n return [root.clientWidth || win.innerWidth, root.clientHeight || win.innerHeight]\n }\n const bar = () => stack.querySelector<HTMLElement>('.toolbar, .pill')\n const rectOf = (node: HTMLElement): Point => {\n const rect = node.getBoundingClientRect()\n return { x: rect.left, y: rect.top }\n }\n\n function place(): void {\n const toolbar = bar()\n const cards = Array.from(stack.children) as HTMLElement[]\n const [vw, vh] = viewport()\n if (!pos || !toolbar) {\n stack.removeAttribute('style')\n stack.removeAttribute('data-below')\n for (const card of cards) {\n card.style.marginLeft = ''\n card.style.maxHeight = ''\n }\n placeMenu(toolbar, vw)\n return\n }\n const w = toolbar.offsetWidth\n const h = toolbar.offsetHeight\n const x = clamp(pos.x, GUTTER, vw - w - GUTTER)\n const y = clamp(pos.y, GUTTER, vh - h - GUTTER)\n // The cards open on the side with more room.\n const below = vh - y - h > y\n const room = (below ? vh - y - h : y) - GAP - GUTTER\n Object.assign(stack.style, {\n padding: '0',\n alignItems: 'flex-start',\n flexDirection: below ? 'column-reverse' : 'column',\n top: below ? `${y}px` : 'auto',\n bottom: below ? 'auto' : `${vh - y - h}px`,\n })\n stack.toggleAttribute('data-below', below)\n for (const card of cards) {\n if (card.classList.contains('toast') || card.classList.contains('menu')) continue\n if (card.classList.contains('list')) card.style.maxHeight = `min(50vh, ${room}px)`\n const cw = card.offsetWidth\n card.style.marginLeft = `${card === toolbar ? x : clamp(x + (w - cw) / 2, GUTTER / 2, vw - cw - GUTTER / 2)}px`\n }\n placeMenu(toolbar, vw)\n }\n\n /** The account menu's right edge under the account chip (35px in from the bar's right edge). */\n function placeMenu(toolbar: HTMLElement | null, vw: number): void {\n const menu = stack.querySelector<HTMLElement>('.menu')\n if (!menu || !toolbar) return\n const left =\n stack.getBoundingClientRect().left +\n (parseFloat(win.getComputedStyle(stack).paddingLeft) || 0)\n const mw = menu.offsetWidth\n menu.style.alignSelf = 'flex-start'\n menu.style.marginLeft = `${clamp(toolbar.getBoundingClientRect().right - 35 - mw, GUTTER / 2, vw - mw - GUTTER / 2) - left}px`\n }\n\n /** Move to `point`, clamped, and remember where the bar really landed. */\n function moveTo(point: Point, save: boolean): void {\n pos = point\n place()\n const toolbar = bar()\n if (toolbar) pos = rectOf(toolbar)\n if (save) write(win, pos, hidden)\n }\n\n function reset(): void {\n pos = null\n write(win, null, hidden)\n place()\n }\n\n const onMove = (event: PointerEvent) => {\n if (!drag || event.pointerId !== drag.id) return\n const dx = event.clientX - drag.px\n const dy = event.clientY - drag.py\n if (!drag.moved && Math.hypot(dx, dy) < SLOP) return\n drag.moved = true\n event.preventDefault()\n pos = { x: drag.from.x + dx, y: drag.from.y + dy }\n place()\n }\n const onUp = (event: PointerEvent) => {\n if (!drag || event.pointerId !== drag.id) return\n const { moved, node } = drag\n drag = null\n node.removeAttribute('data-dragging')\n if (moved && pos) {\n moveTo(pos, true)\n lastTap = 0\n // The click that follows this pointerup comes in the same task.\n dragged = true\n win.setTimeout(() => (dragged = false))\n } else if (node === handle && event.type === 'pointerup') {\n // Two presses in a row without moving: back to the default place.\n const now = Date.now()\n if (now - lastTap < DOUBLE_MS) {\n lastTap = 0\n reset()\n } else lastTap = now\n }\n }\n\n const stop = (event: Event) => event.stopPropagation()\n function begin(e: PointerEvent, node: HTMLElement): void {\n const toolbar = bar()\n if (e.button !== 0 || !toolbar) return\n drag = {\n id: e.pointerId,\n px: e.clientX,\n py: e.clientY,\n from: rectOf(toolbar),\n moved: false,\n node,\n }\n node.setAttribute('data-dragging', '')\n try {\n node.setPointerCapture(e.pointerId)\n } catch {\n // An inactive pointer: the window listeners still follow it.\n }\n }\n const handle = el(doc, 'button', {\n class: 'grip',\n attrs: { type: 'button', 'aria-label': label, title: tip },\n on: {\n pointerdown: (event) => {\n event.stopPropagation()\n begin(event as PointerEvent, handle)\n },\n keydown: (event) => {\n const e = event as KeyboardEvent\n const step = e.shiftKey ? BIG_STEP : STEP\n const delta: Record<string, [number, number]> = {\n ArrowLeft: [-step, 0],\n ArrowRight: [step, 0],\n ArrowUp: [0, -step],\n ArrowDown: [0, step],\n }\n const move = delta[e.key]\n const toolbar = bar()\n if (!move || !toolbar) return\n e.preventDefault()\n e.stopPropagation()\n const from = rectOf(toolbar)\n moveTo({ x: from.x + move[0], y: from.y + move[1] }, true)\n },\n },\n })\n for (const type of [\n 'pointerup',\n 'dblclick',\n 'mousedown',\n 'mouseup',\n 'click',\n 'touchstart',\n 'touchend',\n ]) {\n handle.addEventListener(type, stop)\n }\n handle.append(icon(doc, 'grip'))\n\n // Capture on the window: the grip stops its own events from bubbling, and a\n // render mid-drag may take it out of the page.\n const onResize = () => place()\n win.addEventListener('pointermove', onMove, true)\n win.addEventListener('pointerup', onUp, true)\n win.addEventListener('pointercancel', onUp, true)\n win.addEventListener('resize', onResize)\n win.addEventListener('orientationchange', onResize)\n\n return {\n handle,\n grab(node) {\n node.addEventListener('pointerdown', (event) => begin(event as PointerEvent, node))\n node.addEventListener(\n 'click',\n (event) => {\n if (dragged) event.stopImmediatePropagation()\n },\n true,\n )\n return node\n },\n place,\n hidden: () => hidden,\n setHidden(value) {\n hidden = value\n write(win, pos, hidden)\n },\n destroy() {\n win.removeEventListener('pointermove', onMove, true)\n win.removeEventListener('pointerup', onUp, true)\n win.removeEventListener('pointercancel', onUp, true)\n win.removeEventListener('resize', onResize)\n win.removeEventListener('orientationchange', onResize)\n },\n }\n}\n\n/** The grip's own styles; the bar's shared hover treatment lives with the bar (suggest.ts). */\nexport const DRAG_CSS = `\n.grip { width: 20px; height: 30px; justify-content: center; border-radius: 7px; color: ${T.muted};\n cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }\n.grip[data-dragging], .pill[data-dragging] { cursor: grabbing; }\n.pill { touch-action: none; user-select: none; -webkit-user-select: none; }\n.bottom[data-below] .seg[data-tip]:hover::after { bottom: auto; top: 34px; }\n`\n","import { isDraftRoutePath } from '../protocol'\nimport type { SiteContext } from './config'\n\n/**\n * «Editar» on the live site through a short draft-mode session (ADR 041\n * amendment 2026-10-06; zap-cms-v2 item 13, option a).\n *\n * A published page carries no tags: stega and `data-zap` are rendered only in\n * Next's draft mode, and only the browser holding the draft cookie gets them.\n * So when the person presses Editar on an untagged page, the bar:\n *\n * 1. asks Zap for a draft session (`POST /api/public/v1/preview/session`, the\n * site-client token in `Authorization`, the page's draft route and path in\n * the body, `credentials: 'omit'`);\n * 2. checks the answer is the site's own draft route on THIS origin (Zap built\n * it from the verified `Origin`; checked again so a confused answer cannot\n * send the tab elsewhere);\n * 3. remembers in `sessionStorage` that Editar should reopen on this path, and\n * until when this tab is in draft mode;\n * 4. navigates the tab there. The site's existing route validates the token\n * with Zap, sets the draft cookie and redirects back to the page, which\n * renders tagged; the bar comes back (the tab still holds its token) and\n * reopens Editar.\n *\n * A page already tagged needs none of this. A page still untagged while this\n * tab is in its draft session simply has no fields, and says so. Signing out\n * revokes the session's preview tokens at Zap and drops the draft cookie\n * through the site's exit route (`{draftRoute}/exit`, the SDK's\n * `createDraftModeExitRoute`), then reloads the page published.\n *\n * Comentar never needs draft mode: nothing here runs for it.\n */\n\nexport const DRAFT_SESSION_PATH = '/api/public/v1/preview/session'\n\n/** Editar should reopen after the reload, on this path, if it happens soon. */\nexport const EDIT_INTENT_KEY = 'eelzap:edit-intent'\n/** This tab entered draft mode through a session, until `exp`. */\nexport const DRAFT_SESSION_KEY = 'eelzap:draft-session'\n\n/** An intent older than this is stale (the navigation never landed). */\nconst INTENT_MAX_AGE_MS = 2 * 60_000\n\nexport const DRAFT_SESSION_MESSAGES = {\n es: {\n preparing: 'Preparando la edición…',\n noRoute:\n 'Este sitio no tiene la ruta de vista previa que Editar necesita. Usa Comentar o ábrelo desde Zap.',\n failed: 'No pudimos preparar la página para editar. Inténtalo de nuevo o usa Comentar.',\n rate: (seconds: number) =>\n `Demasiados intentos. Vuelve a intentarlo en ${seconds} ${seconds === 1 ? 'segundo' : 'segundos'}.`,\n },\n en: {\n preparing: 'Getting the page ready to edit…',\n noRoute:\n 'This site does not have the preview route Edit needs. Use Comment or open it from Zap.',\n failed: 'We could not get the page ready to edit. Try again or use Comment.',\n rate: (seconds: number) =>\n `Too many tries. Try again in ${seconds} ${seconds === 1 ? 'second' : 'seconds'}.`,\n },\n} as const\n\nexport type DraftSessionFailure =\n | { ok: false; reason: 'no-route' | 'expired' | 'refused' | 'failed' }\n | { ok: false; reason: 'rate'; retryAfter: number }\n\nexport type DraftSessionResult = { ok: true; url: string; expiresAt: number } | DraftSessionFailure\n\ntype Ctx = Pick<SiteContext, 'win' | 'zapOrigin' | 'draftRoute'>\n\nfunction storage(win: Window): Storage | null {\n try {\n return win.sessionStorage\n } catch {\n return null\n }\n}\n\nfunction readJson(win: Window, key: string): Record<string, unknown> | null {\n try {\n const raw = storage(win)?.getItem(key)\n if (!raw) return null\n const value = JSON.parse(raw) as unknown\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null\n } catch {\n return null\n }\n}\n\nfunction write(win: Window, key: string, value: unknown): void {\n try {\n storage(win)?.setItem(key, JSON.stringify(value))\n } catch {\n // Blocked storage: Editar just does not reopen by itself after the reload.\n }\n}\n\nfunction remove(win: Window, key: string): void {\n try {\n storage(win)?.removeItem(key)\n } catch {\n // Nothing to clear.\n }\n}\n\n/** The page as the draft route should return to it: path, query and hash. */\nexport function currentPath(win: Window): string {\n const { pathname, search, hash } = win.location\n return `${pathname}${search}${hash}`\n}\n\n/** True while this tab is inside a draft session it entered (the cookie's life). */\nexport function inDraftSession(win: Window, now = Date.now()): boolean {\n const value = readJson(win, DRAFT_SESSION_KEY)\n return (\n !!value &&\n typeof value.exp === 'number' &&\n value.exp > now &&\n value.origin === win.location.origin\n )\n}\n\n/** Reopen Editar after this page reloads (a saved value the site formats itself). */\nexport function rememberEditIntent(win: Window, now = Date.now()): void {\n write(win, EDIT_INTENT_KEY, { path: win.location.pathname, at: now })\n}\n\n/**\n * Whether Editar should reopen now: an intent left on this very path in the\n * last two minutes. Read once: the intent is removed either way.\n */\nexport function takeEditIntent(win: Window, now = Date.now()): boolean {\n const value = readJson(win, EDIT_INTENT_KEY)\n remove(win, EDIT_INTENT_KEY)\n return (\n !!value &&\n value.path === win.location.pathname &&\n typeof value.at === 'number' &&\n now - value.at >= 0 &&\n now - value.at < INTENT_MAX_AGE_MS\n )\n}\n\n/**\n * The URL Zap answered, accepted only when it is this page's own origin and\n * the announced draft route, carrying a token and a path: anything else is\n * a failure, never a navigation.\n */\nexport function acceptSessionUrl(raw: unknown, win: Window, draftRoute: string): string | null {\n if (typeof raw !== 'string') return null\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n if (url.origin !== win.location.origin || url.pathname !== draftRoute) return null\n if (!/^zpt_[A-Za-z0-9_-]{43}$/.test(url.searchParams.get('token') ?? '')) return null\n const path = url.searchParams.get('path') ?? ''\n if (!path.startsWith('/') || path.startsWith('//')) return null\n return url.toString()\n}\n\n/**\n * Ask Zap for a draft session for this page. On success the intent and the\n * session are remembered; the caller navigates (`win.location.assign`).\n */\nexport async function requestDraftSession(\n ctx: Ctx,\n token: string,\n now = Date.now,\n): Promise<DraftSessionResult> {\n const { win } = ctx\n const draftRoute = ctx.draftRoute\n if (!isDraftRoutePath(draftRoute)) return { ok: false, reason: 'no-route' }\n let response: Response\n try {\n response = await win.fetch(`${ctx.zapOrigin}${DRAFT_SESSION_PATH}`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n credentials: 'omit',\n body: JSON.stringify({ draftRoute, path: currentPath(win) }),\n })\n } catch {\n return { ok: false, reason: 'refused' }\n }\n if (response.status === 401) return { ok: false, reason: 'expired' }\n if (response.status === 429) {\n const seconds = Number.parseInt(response.headers.get('Retry-After') ?? '', 10)\n return { ok: false, reason: 'rate', retryAfter: seconds > 0 ? Math.min(seconds, 3600) : 30 }\n }\n if (!response.ok) return { ok: false, reason: 'failed' }\n let body: { url?: unknown; expiresAt?: unknown } | null\n try {\n body = (await response.json()) as typeof body\n } catch {\n return { ok: false, reason: 'failed' }\n }\n const url = acceptSessionUrl(body?.url, win, draftRoute)\n if (!url) return { ok: false, reason: 'failed' }\n const at = now()\n const parsed = typeof body?.expiresAt === 'string' ? Date.parse(body.expiresAt) : NaN\n const expiresAt = Number.isFinite(parsed) ? parsed : at + 10 * 60_000\n write(win, EDIT_INTENT_KEY, { path: win.location.pathname, at })\n write(win, DRAFT_SESSION_KEY, { exp: expiresAt, origin: win.location.origin })\n return { ok: true, url, expiresAt }\n}\n\n/** The site's draft-exit route by the SDK's convention: `{draftRoute}/exit`. */\nexport function draftExitUrl(win: Window, draftRoute: string): string {\n const url = new URL(`${draftRoute.replace(/\\/+$/, '')}/exit`, win.location.origin)\n url.searchParams.set('path', currentPath(win))\n return url.toString()\n}\n\n/**\n * Sign-out: revoke this token's draft sessions at Zap, then, when the page\n * is in draft mode (`tagged`, or this tab entered a session), drop the draft\n * cookie through the site's exit route and reload published. Resolves true\n * when it reloads. Never throws: signing out must work whatever answers.\n */\nexport async function leaveDraftSession(\n ctx: Ctx,\n token: string,\n tagged: boolean,\n): Promise<boolean> {\n const { win } = ctx\n const entered = inDraftSession(win)\n remove(win, EDIT_INTENT_KEY)\n remove(win, DRAFT_SESSION_KEY)\n if (!entered && !tagged) return false\n try {\n await win.fetch(`${ctx.zapOrigin}${DRAFT_SESSION_PATH}`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${token}` },\n credentials: 'omit',\n })\n } catch {\n // The tokens die with their ten minutes anyway.\n }\n if (!isDraftRoutePath(ctx.draftRoute)) return false\n try {\n // Same origin, so the route's Set-Cookie (both cookies expired, partitioned)\n // applies; its 307 back to the page is not followed.\n const response = await win.fetch(draftExitUrl(win, ctx.draftRoute), {\n method: 'GET',\n credentials: 'same-origin',\n redirect: 'manual',\n cache: 'no-store',\n })\n if (response.type !== 'opaqueredirect' && !response.ok) return false\n } catch {\n return false\n }\n win.location.reload()\n return true\n}\n","import { cleanStega } from '../../stega'\nimport { findAnchorElement, normalizeText } from '../anchor'\nimport type { OverlayPin } from '../overlay'\nimport { isRecordRef, parseRecordRef, type DomAnchor, type PageAnchor } from '../protocol'\nimport type { TagIndex, TaggedElement } from '../tags'\nimport type {\n ApiAnchor,\n CreateBody,\n DraftBody,\n FieldInfo,\n OnPage,\n OnPageAnchor,\n RawValue,\n} from './api'\n\n/**\n * What «Editar» and «Comentar» send, decided in the page (zap-cms-v2 §3.3,\n * §3.4). Pure functions over the DOM and the `on-page` answer, so each rule is\n * a spec:\n *\n * - **What can be edited or proposed.** Only ONE tagged element, never on\n * `data-zap-html` (rich text). «Editar»: TEXT or LONG_TEXT in place\n * (`contenteditable`); URL, NUMBER, INTEGER, CURRENCY, DATE and DATETIME in\n * a native input; ENUM in a list of its options; BOOLEAN in a switch. Every\n * other type opens «Este campo se edita en Zap». A proposal in «Comentar»\n * stays TEXT, LONG_TEXT, NUMBER or URL (`SUGGESTIBLE_TYPES`). The field\n * types come from Zap's `on-page` read (the site's schema for the records\n * tagged on the page), never from the page's markup.\n * - **Which record** a thread lands on: the element's own tag, else the\n * nearest `data-zap-entry`, else the record the page tags most.\n * - **Anchors** are the package's own (`buildAnchor`), clamped to the request\n * schema's limits, with the `field` layer only for the target record; or a\n * point of the page (`spotAnchor`).\n * - **The payloads.** «Comentar»: a plain comment, or with «Solicitar cambio»\n * a change request, which alone may carry a proposed value. «Editar»: the\n * new value, saved to the draft. The page's address goes once, as `pageUrl`.\n * - **The pins**: the open threads made on this page with an element or a\n * point, oldest first, numbered from 1, as the editor's Comentarios list\n * numbers them (`numberPins` in Zap).\n */\n\nexport const SUGGESTIBLE_TYPES = ['TEXT', 'LONG_TEXT', 'NUMBER', 'URL'] as const\n\nexport type EditKind = 'text' | 'input' | 'choice' | 'switch'\n\n/** Edited in a native input (`inputSpec`). */\nconst INPUT_TYPES = new Set(['URL', 'NUMBER', 'INTEGER', 'CURRENCY', 'DATE', 'DATETIME'])\n\n/** Whether «Comentar» may carry a proposed value for this field («Proponer texto»). */\nexport function proposableField(tagged: TaggedElement | null, field: FieldInfo | null): boolean {\n return (\n !!tagged &&\n !!field &&\n !tagged.html &&\n (SUGGESTIBLE_TYPES as readonly string[]).includes(field.type)\n )\n}\n\n/** How «Editar» edits a field on the page, or null: the field is edited in Zap. */\nexport function editKindFor(\n tagged: TaggedElement | null,\n field: FieldInfo | null | undefined,\n): EditKind | null {\n if (!tagged || !field || tagged.html) return null\n if (field.type === 'TEXT' || field.type === 'LONG_TEXT') return 'text'\n if (INPUT_TYPES.has(field.type)) return 'input'\n if (field.type === 'ENUM') return field.options?.length ? 'choice' : null\n if (field.type === 'BOOLEAN') return 'switch'\n return null\n}\n\n/** A currency's minor-unit digits (COP and USD 2, JPY 0); 2 when the code is unknown. */\n/**\n * ISO 4217 minor units: how many digits `amountMinor` carries for a currency.\n * A fixed table, never `Intl`: CLDR's display digits differ (it shows COP with\n * no decimals), while Zap stores COP, like USD, in hundredths.\n */\nconst ZERO_DIGITS = new Set([\n 'BIF',\n 'CLP',\n 'DJF',\n 'GNF',\n 'ISK',\n 'JPY',\n 'KMF',\n 'KRW',\n 'PYG',\n 'RWF',\n 'UGX',\n 'UYI',\n 'VND',\n 'VUV',\n 'XAF',\n 'XOF',\n 'XPF',\n])\nconst THREE_DIGITS = new Set(['BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND'])\n\nexport function currencyDigits(code: string | undefined): number {\n const upper = (code ?? '').toUpperCase()\n if (ZERO_DIGITS.has(upper)) return 0\n if (THREE_DIGITS.has(upper)) return 3\n return 2\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0')\n\n/**\n * The native input for a field: its `type`, the constraints (INTEGER steps\n * by 1; CURRENCY is typed in MAJOR units, so its step is one minor unit)\n * and the text a stored value shows as. CURRENCY's value travels in minor\n * units: 4600000 COP shows as 46000.00.\n */\nexport function inputSpec(\n field: FieldInfo,\n value: RawValue | undefined,\n): { type: string; text: string; min?: number; max?: number; step?: number | 'any' } {\n const digits = currencyDigits(field.currency)\n const limits = { min: field.min, max: field.max }\n const number = typeof value === 'number' && Number.isFinite(value) ? value : null\n switch (field.type) {\n case 'NUMBER':\n return {\n type: 'number',\n text: number === null ? '' : String(number),\n ...limits,\n step: field.step ?? 'any',\n }\n case 'INTEGER':\n return { type: 'number', text: number === null ? '' : String(number), ...limits, step: 1 }\n case 'CURRENCY':\n return {\n type: 'number',\n text: number === null ? '' : (number / 10 ** digits).toFixed(digits),\n ...limits,\n step: field.step ?? 10 ** -digits,\n }\n case 'DATE':\n return { type: 'date', text: typeof value === 'string' ? value.slice(0, 10) : '' }\n case 'DATETIME': {\n const at = typeof value === 'string' ? new Date(value) : null\n return {\n type: 'datetime-local',\n text:\n at && Number.isFinite(at.getTime())\n ? `${at.getFullYear()}-${pad(at.getMonth() + 1)}-${pad(at.getDate())}T${pad(at.getHours())}:${pad(at.getMinutes())}`\n : '',\n }\n }\n default:\n return { type: 'text', text: typeof value === 'string' ? value : '' }\n }\n}\n\n/**\n * What an input holds, as the value a save sends (`RawValue`): empty is null\n * (cleared), a NUMBER any finite number, an INTEGER a whole one, CURRENCY its\n * minor units, a DATE `YYYY-MM-DD`, a DATETIME the local time as ISO.\n */\nexport function parseInput(\n field: FieldInfo,\n raw: string,\n): { ok: true; value: RawValue } | { ok: false } {\n const text = cleanStega(raw).trim()\n if (field.type === 'URL') return { ok: true, value: normalizeText(text) }\n if (text === '') return { ok: true, value: null }\n const number = Number(text.replace(',', '.'))\n switch (field.type) {\n case 'NUMBER':\n return Number.isFinite(number) ? { ok: true, value: number } : { ok: false }\n case 'INTEGER':\n return Number.isInteger(number) ? { ok: true, value: number } : { ok: false }\n case 'CURRENCY':\n return Number.isFinite(number)\n ? { ok: true, value: Math.round(number * 10 ** currencyDigits(field.currency)) }\n : { ok: false }\n case 'DATE':\n return /^\\d{4}-\\d{2}-\\d{2}$/.test(text) && Number.isFinite(Date.parse(text))\n ? { ok: true, value: text }\n : { ok: false }\n case 'DATETIME': {\n const at = new Date(text)\n return Number.isFinite(at.getTime()) ? { ok: true, value: at.toISOString() } : { ok: false }\n }\n default:\n return { ok: true, value: text }\n }\n}\n\n/**\n * The same stored value: text without markers and whitespace collapsed, a\n * DATETIME to the minute (the input has no seconds), the rest exactly.\n */\nexport function sameRaw(type: string, a: RawValue | undefined, b: RawValue): boolean {\n const before = a ?? null\n if (typeof before === 'string' && typeof b === 'string') {\n if (type === 'DATETIME') {\n return Math.floor(Date.parse(before) / 60_000) === Math.floor(Date.parse(b) / 60_000)\n }\n return normalizeText(before) === normalizeText(b)\n }\n return before === b\n}\n\n/** The field of a tagged element, from the `on-page` schema. */\nexport function fieldOf(\n data: Pick<OnPage, 'fields'> | null,\n tagged: TaggedElement | null,\n): FieldInfo | null {\n if (!data || !tagged) return null\n const field = data.fields?.[tagged.recordRef]?.[tagged.fieldKey]\n return field && typeof field.type === 'string' ? field : null\n}\n\n/** The record a thread about `element` belongs to, or null when the page names none. */\nexport function recordFor(element: Element, index: TagIndex): string | null {\n const tagged = index.closest(element)\n if (tagged) return tagged.recordRef\n const entry = element.closest('[data-zap-entry]')?.getAttribute('data-zap-entry')?.trim()\n if (entry && isRecordRef(entry)) return entry\n const counts = new Map<string, number>()\n for (const row of index.summary()) {\n counts.set(row.recordRef, (counts.get(row.recordRef) ?? 0) + row.count)\n }\n let best: string | null = null\n let most = 0\n for (const [ref, count] of counts) {\n if (count > most) {\n best = ref\n most = count\n }\n }\n return best\n}\n\n/** The page's address for anchors and the `on-page` read: no hash, at most 2048 chars. */\nexport function currentPageUrl(win: Window): string {\n const { origin, pathname, search } = win.location\n return `${origin}${pathname}${search}`.slice(0, 2048)\n}\n\nconst unit = (value: number) => (Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 0)\nconst whole = (value: number, max: number) =>\n Number.isFinite(value) ? Math.min(max, Math.max(1, Math.round(value))) : 1\n\ntype ElementAnchor = Extract<ApiAnchor, { dom: unknown }>\n\n/** A page anchor as the public API takes it: keys, not ids; null layers left out. */\nexport function toApiAnchor(anchor: PageAnchor, recordRef: string): ElementAnchor {\n const dom = anchor.dom\n const out: ElementAnchor = {\n dom: {\n ...(dom.tag && dom.tag.length <= 500 ? { tag: dom.tag } : {}),\n ...(dom.selector ? { selector: dom.selector } : {}),\n ...(dom.textQuote\n ? {\n textQuote: {\n exact: dom.textQuote.exact.slice(0, 500),\n prefix: dom.textQuote.prefix.slice(-32),\n suffix: dom.textQuote.suffix.slice(0, 32),\n },\n }\n : {}),\n rect: { x: unit(dom.rect.x), y: unit(dom.rect.y), w: unit(dom.rect.w), h: unit(dom.rect.h) },\n viewport: { w: whole(dom.viewport.w, 100_000), h: whole(dom.viewport.h, 1_000_000) },\n },\n }\n if (anchor.field && anchor.field.recordRef === recordRef) {\n out.field = {\n key: anchor.field.key,\n ...(anchor.field.locale ? { locale: anchor.field.locale } : {}),\n }\n }\n return out\n}\n\nexport function recordKeys(\n recordRef: string,\n): Pick<CreateBody, 'collection' | 'slug' | 'document'> {\n const parsed = parseRecordRef(recordRef)\n if (!parsed) return {}\n return parsed.kind === 'document'\n ? { document: parsed.key }\n : { collection: parsed.collection, slug: parsed.slug }\n}\n\nexport interface Proposal {\n fieldKey: string\n locale: string | null\n value: RawValue\n}\n\n/**\n * The «Comentar» body. A proposal goes only with a change request; the\n * comment (trimmed) is the body, or the proposed value's text when there is\n * no comment.\n */\nexport function buildCreateBody(input: {\n recordRef: string\n pageUrl: string\n anchors: ApiAnchor[]\n comment: string\n isChangeRequest: boolean\n proposal: Proposal | null\n}): CreateBody {\n const proposal = input.isChangeRequest ? input.proposal : null\n const comment = input.comment.trim()\n const body: CreateBody = {\n ...recordKeys(input.recordRef),\n isChangeRequest: input.isChangeRequest,\n pageUrl: input.pageUrl,\n anchors: input.anchors.slice(0, 20),\n body: (comment || (proposal ? String(proposal.value) : '')).slice(0, 10_000),\n }\n if (proposal) Object.assign(body, proposedPart(proposal))\n return body\n}\n\n/** The «Editar» body: the new value, saved to the record's draft. */\nexport function buildDraftBody(input: {\n recordRef: string\n pageUrl: string\n anchors: ApiAnchor[]\n proposal: Proposal\n /** The thread's text when the value is not (an option's label, «Sí»); else the value. */\n display?: string\n}): DraftBody {\n return {\n ...recordKeys(input.recordRef),\n pageUrl: input.pageUrl,\n anchors: input.anchors.slice(0, 20),\n body: (input.display ?? String(input.proposal.value ?? '')).slice(0, 10_000) || ' ',\n ...proposedPart(input.proposal),\n }\n}\n\nfunction proposedPart(proposal: Proposal): Pick<CreateBody, 'locale' | 'proposedValues'> {\n const locale = proposal.locale\n return {\n ...(locale ? { locale } : {}),\n proposedValues: [\n { fieldKey: proposal.fieldKey, ...(locale ? { locale } : {}), value: proposal.value },\n ],\n }\n}\n\n/**\n * Two parsed values are the same edit: numbers by value, text without stega\n * markers and with whitespace collapsed (`normalizeText`), so a field left\n * as it was, read back from a preview page, never counts as a change.\n */\nexport function sameValue(a: string | number, b: string | number): boolean {\n if (typeof a === 'number' || typeof b === 'number') return a === b\n return normalizeText(a) === normalizeText(b)\n}\n\nconst LINE_BLOCKS = new Set(['div', 'p', 'li'])\n\n/**\n * The text an inline edit left in `element`, as typed: its text nodes, `<br>`\n * and a new block (what Enter makes in a contenteditable) as line breaks.\n * Never `innerText`: it applies CSS, so a field shown with `text-transform:\n * uppercase` read back in capitals and every edit of it looked like a change.\n */\nexport function editableText(element: Element): string {\n let out = ''\n const walk = (node: Node) => {\n for (let child = node.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3) {\n out += (child as Text).data\n } else if (child.nodeType === 1) {\n const name = (child as Element).localName\n if (name === 'br') {\n out += '\\n'\n continue\n }\n if (LINE_BLOCKS.has(name) && out !== '' && !out.endsWith('\\n')) out += '\\n'\n walk(child)\n }\n }\n }\n walk(element)\n return out\n}\n\n/** The value typed for `kind`, parsed for its field type; `invalid` when a number is not one. */\nexport function parseProposed(\n type: string,\n raw: string,\n): { ok: true; value: string | number } | { ok: false } {\n // Text read from the page in preview carries stega markers; never send one.\n raw = cleanStega(raw)\n if (type === 'NUMBER') {\n const text = raw.trim().replace(',', '.')\n const value = Number(text)\n return text !== '' && Number.isFinite(value) ? { ok: true, value } : { ok: false }\n }\n if (type === 'TEXT' || type === 'URL') return { ok: true, value: normalizeText(raw) }\n return { ok: true, value: raw.replace(/\\r\\n?/g, '\\n').trim() }\n}\n\n/** A point of the page, from a click at viewport `(x, y)`, as fractions of the whole document. */\nexport function spotAnchor(x: number, y: number, doc: Document, win: Window): ApiAnchor {\n const root = doc.documentElement\n const w = Math.max(root.scrollWidth, 1)\n const h = Math.max(root.scrollHeight, 1)\n return {\n spot: { x: unit((x + win.scrollX) / w), y: unit((y + win.scrollY) / h) },\n viewport: { w: whole(w, 100_000), h: whole(h, 1_000_000) },\n }\n}\n\n/** An anchor the page can show: a point, or an element (the editor's `onPageAnchor`). */\nfunction onPage(anchor: OnPageAnchor): boolean {\n return !!(anchor?.spot || anchor?.rect || anchor?.tag || anchor?.selector)\n}\n\n/**\n * The numbered pins of the page's open threads. Numbers go to every thread\n * with an on-page anchor, oldest first, so «2» here is «2» in Zap; a pin is\n * drawn at the thread's point, else at the first of its elements still on the\n * page (a thread whose element is gone keeps its number and draws nothing).\n * Never throws: stored selectors only reach `safeQueryAll`.\n */\nexport function pinsFor<R extends { id: string; createdAt: string; anchors: OnPageAnchor[] }>(\n threads: readonly R[],\n index: TagIndex,\n doc: Document,\n win: Window,\n): { pins: OverlayPin[]; numbers: Map<string, number> } {\n const numbers = new Map<string, number>()\n const pins: OverlayPin[] = []\n const numbered = threads\n .filter((thread) => Array.isArray(thread.anchors) && thread.anchors.some(onPage))\n .sort(\n (a, b) => String(a.createdAt).localeCompare(String(b.createdAt)) || a.id.localeCompare(b.id),\n )\n numbered.forEach((thread, i) => {\n const n = i + 1\n numbers.set(thread.id, n)\n const spot = thread.anchors.find((anchor) => anchor?.spot)?.spot\n if (spot && Number.isFinite(spot.x) && Number.isFinite(spot.y)) {\n pins.push({ id: thread.id, n, spot: { x: unit(spot.x), y: unit(spot.y) } })\n return\n }\n for (const anchor of thread.anchors) {\n if (!onPage(anchor) || anchor.spot) continue\n const element = findAnchorElement(asDomAnchor(anchor), index, doc, win)\n if (element && element !== doc.body && element !== doc.documentElement) {\n pins.push({ id: thread.id, n, element })\n return\n }\n }\n })\n return { pins: pins.slice(0, 50), numbers }\n}\n\n/** No rectangle fallback: a pin on a guessed element is worse than none. */\nconst NOWHERE = { x: -1, y: -1, w: 0, h: 0 }\n\nfunction asDomAnchor(anchor: OnPageAnchor): DomAnchor {\n const tag = typeof anchor?.tag === 'string' && anchor.tag.length <= 500 ? anchor.tag : null\n const selector =\n typeof anchor?.selector === 'string' && anchor.selector.length <= 1024 ? anchor.selector : null\n return { tag, selector, textQuote: null, rect: NOWHERE, viewport: { w: 1, h: 1 } }\n}\n","import type { ApiResult } from './api'\nimport type { SiteContext } from './config'\nimport { readTokenAnswer } from './oauth'\nimport {\n accessLive,\n clearToken,\n EXPIRY_MARGIN_MS,\n refreshLive,\n writeToken,\n type SiteToken,\n} from './token'\n\n/**\n * The site client's token lifecycle (ADR 041 amendment 2026-10-06; Zap item\n * 32): ONE place that knows whether the bar can still talk to Zap, shared by\n * the on-page read, comments, «Editar»'s saves and the draft-session\n * exchange.\n *\n * - **A valid token** for each call (`ensure`): the stored access token while\n * it has more than 30 seconds left, else a renewal first.\n * - **Renewal** (`refresh`) spends the refresh token at Nest\n * (`grant_type=refresh_token`, `client_id`, no cookies; Nest answers CORS to\n * this origin and rotates the refresh token). One renewal at a time: calls\n * that need it while one is running wait for the same answer.\n * - **A 401 retries once** (`call`): renew, then the same request with the\n * new token. A second 401, or a renewal that fails, is the expired state.\n * - **Ahead of time**: a timer renews two minutes before the hour ends, so a\n * person typing in a field never meets the wall; when the tab becomes\n * visible again (timers sleep with the tab) the same check runs at once.\n * Renewing touches nothing on the page: the bar keeps its state and an\n * inline edit in progress is not re-rendered.\n * - **Expired** (`onExpired`, once): the refresh is gone (no refresh token,\n * past its eight hours, consent revoked or past its 30 days, another\n * origin). The stored tokens are forgotten and the bar shows «Tu sesión de\n * Zap expiró» with «Volver a entrar». It is never «No puedes editar ni\n * comentar»: that card is for a 403 (no seat, or the site refused).\n */\n\n/** Renew this long before the access token's hour ends. */\nexport const REFRESH_LEAD_MS = 2 * 60_000\n\nexport interface TokenSession {\n /** The current access token (possibly near its end; prefer `call`). */\n token(): string\n /** True once renewal failed: the bar shows the expired state. */\n readonly expired: boolean\n /** A token good for the next call, renewing first when needed; null when expired. */\n ensure(): Promise<string | null>\n /** Renew now. Resolves true with a fresh token stored. Single flight. */\n refresh(): Promise<boolean>\n /**\n * Run `request` with a valid token; on a 401, renew and run it once more.\n * An expired session answers `{ ok: false, kind: 'expired' }` without\n * calling.\n */\n call<T>(request: (token: string) => Promise<ApiResult<T>>): Promise<ApiResult<T>>\n /** Stop the timers and the visibility listener. */\n destroy(): void\n}\n\nexport interface TokenSessionHooks {\n /** Renewal failed for good: show the expired state. Called once. */\n onExpired(): void\n}\n\nexport interface TokenSessionDeps {\n now?: () => number\n setTimeout?: (fn: () => void, ms: number) => unknown\n clearTimeout?: (handle: unknown) => void\n}\n\ntype Ctx = Pick<SiteContext, 'win' | 'doc' | 'authOrigin' | 'clientId' | 'siteId'>\n\nexport function createTokenSession(\n ctx: Ctx,\n stored: SiteToken,\n hooks: TokenSessionHooks,\n deps: TokenSessionDeps = {},\n): TokenSession {\n const { win, doc } = ctx\n const now = deps.now ?? (() => Date.now())\n const setT = deps.setTimeout ?? ((fn: () => void, ms: number) => win.setTimeout(fn, ms))\n const clearT = deps.clearTimeout ?? ((handle: unknown) => win.clearTimeout(handle as number))\n\n let current: SiteToken = stored\n let expired = false\n let destroyed = false\n let inflight: Promise<boolean> | null = null\n let timer: unknown = null\n\n function markExpired(): void {\n if (expired || destroyed) return\n expired = true\n stop()\n clearToken(win)\n hooks.onExpired()\n }\n\n async function renew(): Promise<boolean> {\n if (!refreshLive(current, now()) || !current.refresh) return false\n let response: Response\n try {\n response = await win.fetch(`${ctx.authOrigin}/api/oauth/token`, {\n method: 'POST',\n credentials: 'omit',\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: current.refresh,\n client_id: ctx.clientId,\n }),\n })\n } catch {\n return false\n }\n if (!response.ok) return false\n try {\n const next = await readTokenAnswer(response, ctx.siteId, now())\n // Rotation answers a new refresh token; without one, keep nothing stale.\n current = next\n writeToken(win, next)\n return true\n } catch {\n return false\n }\n }\n\n function refresh(): Promise<boolean> {\n if (expired || destroyed) return Promise.resolve(false)\n inflight ??= renew().finally(() => {\n inflight = null\n if (!destroyed && !expired) schedule()\n })\n return inflight\n }\n\n /** Renew if the hour is about to end (or has); expire if that fails past the margin. */\n async function check(): Promise<void> {\n if (expired || destroyed) return\n if (current.exp - REFRESH_LEAD_MS > now()) {\n schedule()\n return\n }\n const ok = await refresh()\n if (!ok && !accessLive(current, now())) markExpired()\n else if (!ok) {\n // Still a little hour left: try once more at the margin, then give up.\n stop()\n timer = setT(() => void lastTry(), Math.max(0, current.exp - EXPIRY_MARGIN_MS - now()))\n }\n }\n\n async function lastTry(): Promise<void> {\n if (!(await refresh())) markExpired()\n }\n\n function stop(): void {\n if (timer !== null) clearT(timer)\n timer = null\n }\n\n function schedule(): void {\n stop()\n if (expired || destroyed) return\n timer = setT(() => void check(), Math.max(0, current.exp - REFRESH_LEAD_MS - now()))\n }\n\n const onVisible = () => {\n if (doc.visibilityState === 'visible') void check()\n }\n doc.addEventListener('visibilitychange', onVisible)\n\n async function ensure(): Promise<string | null> {\n if (expired) return null\n if (accessLive(current, now())) return current.token\n if (await refresh()) return current.token\n markExpired()\n return null\n }\n\n async function call<T>(request: (token: string) => Promise<ApiResult<T>>): Promise<ApiResult<T>> {\n const token = await ensure()\n if (token === null) return { ok: false, kind: 'expired' }\n const first = await request(token)\n if (first.ok || first.kind !== 'expired') return first\n // A 401 with time left: revoked, or the clock disagrees. Renew and retry once.\n if (await refresh()) {\n const second = await request(current.token)\n if (!second.ok && second.kind === 'expired') markExpired()\n return second\n }\n markExpired()\n return first\n }\n\n // A session that arrives with its hour already spent renews at once.\n void check()\n\n return {\n token: () => current.token,\n get expired() {\n return expired\n },\n ensure,\n refresh,\n call,\n destroy() {\n destroyed = true\n stop()\n doc.removeEventListener('visibilitychange', onVisible)\n },\n }\n}\n\nexport const SESSION_MESSAGES = {\n es: {\n expiredTitle: 'Tu sesión de Zap expiró',\n expiredBody: 'Vuelve a entrar para seguir editando y comentando.',\n signInAgain: 'Volver a entrar',\n },\n en: {\n expiredTitle: 'Your Zap session expired',\n expiredBody: 'Sign in again to keep editing and commenting.',\n signInAgain: 'Sign in again',\n },\n} as const\n","import { buildAnchor, normalizeText } from '../anchor'\nimport { Overlay, OVERLAY_HOST_TAG, reveal as scrollTo, type OverlayPin } from '../overlay'\nimport type { OverlayMode } from '../protocol'\nimport { observeTags, tagGuard, TagIndex, type PauseReason, type TaggedElement } from '../tags'\nimport {\n createComment,\n fetchOnPage,\n newIdempotencyKey,\n saveToDraft,\n type ApiAnchor,\n type ApiFailure,\n type FieldInfo,\n type OnPage,\n type OnPageComment,\n type RawValue,\n} from './api'\nimport type { ChunkHandle, SiteContext, StartOptions } from './config'\nimport { barDrag, DRAG_CSS } from './drag'\nimport {\n DRAFT_SESSION_MESSAGES,\n inDraftSession,\n leaveDraftSession,\n requestDraftSession,\n rememberEditIntent,\n takeEditIntent,\n} from './draft-session'\nimport { SUGGEST_MESSAGES } from './messages'\nimport { isShortcut } from './shortcut'\nimport {\n buildCreateBody,\n buildDraftBody,\n currentPageUrl,\n editableText,\n editKindFor,\n fieldOf,\n inputSpec,\n parseInput,\n parseProposed,\n pinsFor,\n proposableField,\n recordFor,\n sameRaw,\n sameValue,\n spotAnchor,\n toApiAnchor,\n type EditKind,\n type Proposal,\n} from './suggestion'\nimport { createTokenSession, SESSION_MESSAGES } from './session'\nimport { clearToken, readSession } from './token'\nimport { el, icon, initials, kbd, mountHost, TOKENS as T, type IconName } from './ui'\n\n/**\n * The `suggest` chunk: «Editar» and «Comentar» on the live site (zap-cms-v2\n * §3.4, owner 2026-10-05; boards SitioBarra, SitioEditar, SitioSugerencia,\n * SitioEnviado, SitioRenovacion), loaded only once this tab holds a site\n * client token. The file keeps its old name so the CDN chunk keeps its own.\n *\n * - **Toolbar** (SitioBarraEstados): the grip, Navegar, Editar and Comentar,\n * the page's open comments, the account chip and the hide arrow. Navegar\n * intercepts nothing and still shows the pins.\n * - **Account menu**: who you are, «Abrir en Zap» (the editor of the record\n * this page is, Zap's `viewer.editorUrl`, else Zap's home) and\n * «Cerrar sesión en Zap», which forgets the token as Salir did. A menu\n * button: arrows, Home and End move, Escape closes back to the chip, an\n * outside press or Tab closes it.\n * - **Paused** (the runaway guard, `tags.ts` `tagGuard`): a page over the\n * tagged cap at boot, or whose tagged count keeps growing on its own, stops\n * being followed: no more scans or pins, Editar and Comentar off, and a\n * quiet «Vista previa pausada» card over the bar with «Recargar» (the\n * pill says it in its label).\n * - **Hidden**: the hide arrow or Shift Z (the site's shortcut; never while\n * typing, editing or writing a comment) folds the bar into a pill with the\n * bolt and the open count, in the bar's place; a click or Shift Z brings it\n * back. Remembered per origin with the bar's place (`drag.ts`).\n * - **Editar** (only while the site's ADMIN leaves `liveEditing` on; off, the\n * tool shows disabled with «Desactivado por un administrador»): the overlay\n * outlines tagged fields; a click on a TEXT or LONG_TEXT field makes it\n * editable in place; URL, NUMBER, INTEGER, CURRENCY (in major units),\n * DATE and DATETIME open a native input with the field's constraints, an\n * ENUM its options, a BOOLEAN a switch, each in a card beside the element\n * that takes focus and gives it back. Leaving the field, Enter or a pick\n * saves the new value straight to the record's draft through Zap's save\n * path and says «Guardado en el borrador»; Escape puts it back; the same\n * value saves nothing. A value the site formats itself reloads the page in\n * place after the save (`showSaved`). Rich text, media and any other type\n * say «Este campo se edita en Zap» with «Abrir en Zap» (the owning record,\n * at the field) and «Comentar». Nothing reaches the site's visitors until\n * an ADMIN publishes in Zap.\n * - **Comentar**: the overlay outlines any element and consumes the click; a\n * click opens the composer anchored to that element, or to the point\n * clicked when the element is most of the page. Shift, Cmd or Ctrl click\n * gathers several elements for one comment. «Solicitar cambio» makes it a\n * change request, which Zap assigns to the record's Responsable; on a single\n * tagged text field it may carry «Proponer texto».\n * - **Pins**: the page's open comments (Zap's `on-page` read) as the\n * overlay's numbered gold pins, the same numbers as the editor's list; a\n * pin, or the count, opens the list.\n *\n * Everything renders in closed shadow roots as text (`ui.ts`, the overlay's\n * pins are `textContent` numbers). Excerpts, names and labels from Zap are\n * set with `textContent`; stored selectors only ever reach `safeQueryAll`.\n */\n\ntype Mode = 'navigate' | 'edit' | 'comment'\n\nconst OVERLAY_MODE: Record<Mode, OverlayMode> = {\n navigate: 'off',\n edit: 'inspect',\n comment: 'select',\n}\n\n/** The pin of the comment being written, never a thread id. */\nconst PENDING_PIN = 'eelzap:pending'\n\n/** An element taking at least this share of the viewport is commented as a point. */\nconst LARGE_SHARE = 0.5\n\nconst TOAST_MS = 8000\n/** «Guardado en el borrador» shows this long before a value the site formats reloads the page. */\nconst RELOAD_AFTER_SAVE_MS = 700\nconst SAVED_MS = 4000\n\ninterface Composer {\n elements: Element[]\n /** The point clicked, in viewport pixels, when the comment is on a point. */\n point: { x: number; y: number } | null\n pin: OverlayPin | null\n recordRef: string\n pageUrl: string\n anchors: ApiAnchor[]\n /** The one tagged text field a proposal may change, else null. */\n tagged: TaggedElement | null\n field: FieldInfo | null\n before: string\n card: HTMLElement\n textarea: HTMLTextAreaElement\n request: boolean\n proposing: boolean\n proposal: HTMLInputElement | HTMLTextAreaElement | null\n error: HTMLElement\n sendButton: HTMLButtonElement\n busy: boolean\n idempotency: { payload: string; key: string } | null\n}\n\ninterface Editing {\n element: HTMLElement\n tagged: TaggedElement\n field: FieldInfo\n kind: EditKind\n recordRef: string\n pageUrl: string\n anchors: ApiAnchor[]\n before: string\n /** ENUM, BOOLEAN, numbers and dates: the stored value the editor opened with. */\n raw: RawValue | undefined\n /** ENUM and BOOLEAN: what is picked now. */\n picked: RawValue | undefined\n /** Where focus goes back when the editor closes. */\n returnFocus: Element | null\n /** Put the element back exactly as it was. */\n revert: () => void\n /** Stop editing, keeping what was typed. */\n keep: () => void\n card: HTMLElement | null\n input: HTMLInputElement | null\n done: boolean\n}\n\nexport function start(ctx: SiteContext, options: StartOptions = {}): ChunkHandle {\n const { win, doc } = ctx\n const stored = readSession(win, ctx.siteId)\n if (!stored) {\n void ctx.open('signin', { reason: 'expired' })\n return { destroy() {} }\n }\n // The token lifecycle (`session.ts`): every call gets a valid token, a 401\n // renews once and retries, and the hour is renewed ahead of time.\n const auth = createTokenSession(ctx, stored, { onExpired: () => expire() })\n const sm = SESSION_MESSAGES[ctx.locale]\n const m = SUGGEST_MESSAGES[ctx.locale]\n const dm = DRAFT_SESSION_MESSAGES[ctx.locale]\n // Editar asked for a draft session on this page and the tab came back in\n // draft mode: reopen Editar once the page read says it is allowed.\n let reopenEdit = takeEditIntent(win)\n /**\n * The flag says this tab is in a draft session, but the page came back\n * untagged (the site's dev server restarted and its draft cookie no longer\n * counts): the exchange runs again, once. Never on a load that an exchange\n * (or a save) itself brought, so it cannot loop.\n */\n let retryDraft = !reopenEdit\n\n const host = mountHost(doc, CSS + DRAG_CSS)\n const layer = el(doc, 'div', { class: 'layer' })\n const marks = el(doc, 'div', { class: 'marks' })\n const bottom = el(doc, 'div', { class: 'bottom' })\n // One tooltip for the bar's buttons, outside the toolbar: its horizontal scroll would clip it.\n const tip = el(doc, 'div', { class: 'tip', attrs: { role: 'tooltip' } })\n layer.append(marks, bottom, tip)\n const drag = barDrag(win, doc, bottom, m.move, m.moveTip)\n const key = ctx.shortcut ? ctx.shortcut.toUpperCase() : null\n host.root.append(layer)\n\n let mode: Mode = 'navigate'\n let selection: Element[] = []\n let data: OnPage | null = null\n let refused = false\n /** The session ran out and could not be renewed: «Volver a entrar». */\n let expired = false\n let composer: Composer | null = null\n let editing: Editing | null = null\n let list: OnPageComment[] | null = null\n let toast: { title: string; body: string; error?: boolean } | null = null\n /** «Este campo se edita en Zap» beside the field clicked in Editar, until closed. */\n let info: { tagged: TaggedElement; card: HTMLElement } | null = null\n let toastTimer: number | null = null\n let status: 'saving' | 'saved' | 'preparing' | null = null\n let statusTimer: number | null = null\n let frame: number | null = null\n let destroyed = false\n let pins: OverlayPin[] = []\n let numbers = new Map<string, number>()\n let lastClick = { x: 0, y: 0, additive: false }\n let menuOpen = false\n /** The `data-action` to focus after the next render. */\n let focusNext: string | null = null\n /** The next render shows the bar or the pill coming in (a toggle). */\n let entering = false\n let paused: PauseReason | null = null\n\n // Before the overlay installs its own capture listeners, so this one runs\n // first and still sees clicks the overlay consumes: where, and whether the\n // person was gathering elements.\n const onClickFirst = (event: MouseEvent) => {\n lastClick = {\n x: event.clientX,\n y: event.clientY,\n additive: event.shiftKey || event.metaKey || event.ctrlKey,\n }\n }\n win.addEventListener('click', onClickFirst, true)\n // A press anywhere on the page closes the account menu. Presses inside the\n // shadow root reach the window as the host; the layer sorts those out.\n const onPressFirst = (event: PointerEvent) => {\n if (event.target === host.host) return\n if (menuOpen) setMenu(false)\n // A press on the page leaves an open editor (saved, as leaving a text\n // field is) and closes «Este campo se edita en Zap».\n if (editing?.card && !editing.done) commitEdit(editing)\n if (info) closeInfo()\n }\n win.addEventListener('pointerdown', onPressFirst, true)\n layer.addEventListener('pointerdown', (event) => {\n if (!menuOpen) return\n const keep = Array.from(bottom.querySelectorAll('.menu, [data-action=\"account\"]'))\n if (!keep.some((node) => node.contains(event.target as Node))) setMenu(false)\n })\n\n const index = new TagIndex(doc)\n index.scan()\n const overlay = new Overlay({\n doc,\n win,\n index,\n pinsWhenOff: true,\n ignore: (target) => target === host.host,\n onInspect: (tagged) => beginEdit(tagged),\n onSelect: (elements) => onSelect(elements),\n onPin: ({ id }) => {\n if (id === PENDING_PIN) return\n const found = data?.comments.find((comment) => comment.id === id)\n if (!found) return\n list = [found]\n // A pin on the page while the bar is folded: the bar comes back with the thread.\n if (drag.hidden()) setHidden(false, false)\n else renderBottom()\n },\n })\n overlay.mount()\n // Both hosts sit at the top z-index, so document order decides: the bar\n // and its cards (this host) after the overlay's boxes, chips and pins.\n doc.documentElement.appendChild(host.host)\n\n // The runaway guard: a page over the cap is never observed; one that keeps\n // growing on its own stops being followed.\n const check = tagGuard()\n let stopObserving = () => {}\n const atBoot = check(index.elements.length, true)\n if (atBoot) {\n // Before the bar's first render, which shows it; the tools start on Navegar.\n paused = atBoot\n console.warn(`eelzap: preview paused (${atBoot})`)\n } else\n stopObserving = observeTags(\n doc.documentElement,\n (page) => {\n index.scan()\n const reason = check(index.elements.length, page)\n if (reason) pause(reason)\n else placePins()\n },\n {\n ignore: (node) => {\n const own = overlay.hostElement\n return node === host.host || (!!own && (node === own || own.contains(node)))\n },\n },\n )\n\n function pause(reason: PauseReason): void {\n if (paused) return\n paused = reason\n stopObserving()\n console.warn(`eelzap: preview paused (${reason})`)\n if (destroyed) return\n // Pins would drift on a page no longer followed: take them down.\n overlay.setPins([])\n setMode('navigate')\n }\n\n // ── Loading the page's context ──────────────────────────────────────────\n\n async function load(): Promise<void> {\n const refs = Array.from(new Set(index.elements.map((tagged) => tagged.recordRef)))\n const result = await auth.call((token) => fetchOnPage(ctx, token, currentPageUrl(win), refs))\n if (destroyed) return\n if (!result.ok) {\n onFailure(result)\n return\n }\n const first = data === null\n data = result.data\n // Labels by key for the page's own records; by tag, with «en …», for\n // fields of another record (a site-wide document in the header).\n const labels: Record<string, string> = {}\n const foreign: Record<string, [string, string]> = {}\n for (const [ref, fields] of Object.entries(data.fields ?? {})) {\n const name = data.records?.[ref]\n for (const [key, field] of Object.entries(fields)) {\n if (typeof field?.label !== 'string') continue\n if (name) foreign[`${ref}#${key}`] = [field.label, m.inRecord(name)]\n else labels[key] = field.label\n }\n }\n overlay.setLabels(labels, foreign)\n if (!data.liveEditing && mode === 'edit') setMode('navigate')\n if (reopenEdit) {\n reopenEdit = false\n if (canEdit()) setMode('edit')\n }\n if (first && options.reason === 'renewed') {\n const name = data.viewer?.name\n setToast({ title: m.renewed, body: name ? m.renewedAs(name) : m.renewedBody })\n }\n renderBottom()\n placePins()\n }\n\n function onFailure(failure: ApiFailure, during: 'read' | 'comment' | 'edit' = 'read'): void {\n if (failure.kind === 'expired') {\n expire()\n return\n }\n if (failure.kind === 'forbidden' && during === 'edit') {\n // «Editar» was turned off since the page read: the tool goes disabled.\n if (data) data.liveEditing = false\n setMode('navigate')\n setToast({ title: m.editOff, body: m.editOffBody, error: true })\n return\n }\n if (failure.kind === 'refused' || failure.kind === 'forbidden') {\n refused = true\n closeComposer()\n overlay.setMode('off')\n overlay.setPins([])\n renderBottom()\n return\n }\n const message = failure.kind === 'rate' ? m.rateLimited(failure.retryAfter) : m.failed\n if (during === 'comment' && composer) showError(message)\n else\n setToast({ title: during === 'edit' ? m.saveFailed : m.failed, body: message, error: true })\n }\n\n function expire(): void {\n clearToken(win)\n if (expired || destroyed) return\n // «Tu sesión de Zap expiró» with «Volver a entrar», not the refused card:\n // the person has access, their hour (and its renewal) ran out.\n expired = true\n closeComposer()\n overlay.setMode('off')\n renderBottom()\n }\n\n /** «Volver a entrar»: the sign-in starts inside this click, so the popup is allowed. */\n function signInAgain(): void {\n void ctx.open('signin', { reason: 'expired', signIn: true })\n }\n\n // ── Toolbar, tray, list, status, toast ──────────────────────────────────\n\n function canEdit(): boolean {\n return !!data?.liveEditing\n }\n\n function setMode(next: Mode): void {\n if ((next === 'edit' && !canEdit()) || (paused && next !== 'navigate')) return\n if (status === 'preparing') return\n // A page rendered outside draft mode carries no tags (no stega, empty\n // `attrs`): Editar first takes the tab through a draft session\n // (`draft-session.ts`), unless this tab is already in one.\n if (next === 'edit' && !index.elements.length && (retryDraft || !inDraftSession(win))) {\n retryDraft = false\n void prepareEdit()\n return\n }\n endEdit()\n closeComposer()\n closeInfo()\n mode = next\n selection = []\n overlay.clearSelection()\n overlay.setMode(OVERLAY_MODE[next])\n // In draft mode and still untagged: the page has no fields, so it says why.\n if (next === 'edit' && !index.elements.length)\n setToast({ title: m.noFields, body: m.noFieldsBody })\n renderBottom()\n }\n\n /**\n * Editar on an untagged page: exchange the site-client token for a draft\n * session and take the tab through the site's draft route; the page comes\n * back tagged and Editar reopens. On failure, the «no fields» empty state\n * with the reason.\n */\n async function prepareEdit(): Promise<void> {\n setStatus('preparing')\n const token = await auth.ensure()\n if (token === null || destroyed) return\n const result = await requestDraftSession(ctx, token)\n if (destroyed) return\n if (result.ok) {\n // Stays «Preparando la edición…» until the page unloads.\n win.location.assign(result.url)\n return\n }\n setStatus(null)\n if (result.reason === 'expired') {\n expire()\n return\n }\n const body =\n result.reason === 'no-route'\n ? dm.noRoute\n : result.reason === 'rate'\n ? dm.rate(result.retryAfter)\n : dm.failed\n setToast({ title: m.noFields, body, error: result.reason !== 'no-route' })\n }\n\n function renderBottom(): void {\n if (destroyed) return\n hideTip()\n // A render replaces the bar: keep focus on the same control.\n const active = host.root.activeElement?.getAttribute('data-action')\n const hidden = drag.hidden()\n const children: HTMLElement[] = []\n if (toast) children.push(toastCard(toast))\n if (expired) {\n children.push(expiredCard())\n bottom.replaceChildren(...children)\n drag.place()\n marks.replaceChildren()\n return\n }\n if (refused) {\n children.push(refusedCard())\n bottom.replaceChildren(...children)\n drag.place()\n marks.replaceChildren()\n return\n }\n if (paused && !hidden) children.push(pausedCard(paused))\n if (list && !hidden) children.push(listCard(list))\n if (selection.length > 0 && !composer && !hidden) children.push(trayCard())\n if (status) {\n children.push(\n el(doc, 'div', { class: 'card status', attrs: { role: 'status' } }, [\n status === 'saved' ? icon(doc, 'check', 14) : null,\n status === 'saved' ? m.saved : status === 'preparing' ? dm.preparing : m.saving,\n ]),\n )\n }\n if (menuOpen && !hidden) children.push(menuCard())\n const bar = hidden ? pill() : toolbar()\n if (entering) bar.setAttribute('data-enter', '')\n entering = false\n children.push(bar)\n bottom.replaceChildren(...children)\n drag.place()\n drawMarks()\n const want = focusNext ?? active\n focusNext = null\n if (want)\n bottom.querySelector<HTMLElement>(`[data-action=\"${want}\"]`)?.focus({ preventScroll: true })\n }\n\n function openCount(): [number, string] {\n const open = data?.comments.length ?? 0\n return [open, data?.truncated ? `${open}+` : String(open)]\n }\n\n function setMenu(open: boolean, focus: string | null = null): void {\n if (menuOpen === open && !focus) return\n menuOpen = open\n focusNext = focus\n renderBottom()\n }\n\n /** Bar to pill and back. `fromUi`: focus follows to the other control. */\n function setHidden(value: boolean, fromUi: boolean): void {\n if (refused || drag.hidden() === value) return\n if (value) {\n endEdit()\n closeComposer()\n selection = []\n overlay.clearSelection()\n list = null\n menuOpen = false\n }\n drag.setHidden(value)\n overlay.setMode(value ? 'off' : OVERLAY_MODE[mode])\n focusNext = fromUi ? (value ? 'show' : 'hide') : null\n entering = true\n renderBottom()\n }\n\n /** The bar's tooltip (SitioBarraEstados) with the shortcut's key chip, on hover and keyboard focus. */\n function withTip(target: HTMLElement, text: string, end: boolean): HTMLElement {\n const show = () => {\n tip.replaceChildren(text)\n if (key) tip.append(kbd(doc, 'Shift', key))\n tip.classList.add('on')\n const rect = target.getBoundingClientRect()\n const vw = doc.documentElement.clientWidth || win.innerWidth\n const w = tip.offsetWidth\n // Over the bar: 8px off its edge (the hide arrow sits 7px inside it), under it when the bar opens down.\n const gap = end ? 15 : 8\n const x = end ? rect.right + 7 - w : rect.left + (rect.width - w) / 2\n tip.style.left = `${Math.min(Math.max(x, 8), vw - w - 8)}px`\n tip.style.top = bottom.hasAttribute('data-below')\n ? `${rect.bottom + gap}px`\n : `${rect.top - gap - tip.offsetHeight}px`\n }\n const focus = () => {\n try {\n if (target.matches(':focus-visible')) show()\n } catch {\n show()\n }\n }\n for (const [type, handler] of [\n ['mouseenter', show],\n ['focus', focus],\n ['mouseleave', hideTip],\n ['blur', hideTip],\n ['pointerdown', hideTip],\n ] as const) {\n target.addEventListener(type, handler)\n }\n if (key) target.setAttribute('aria-keyshortcuts', `Shift+${key}`)\n return target\n }\n\n function hideTip(): void {\n tip.classList.remove('on')\n }\n\n function avatar(name: string | null, large = false): HTMLElement {\n return el(doc, 'span', {\n class: large ? 'avatar lg' : 'avatar',\n attrs: { 'aria-hidden': 'true' },\n text: initials(name),\n })\n }\n\n function menuCard(): HTMLElement {\n const name = data?.viewer?.name ?? null\n const email = data?.viewer?.email ?? null\n const item = (action: string, label: string, glyph: IconName, run: () => void) =>\n el(\n doc,\n 'button',\n {\n class: 'mi',\n attrs: { type: 'button', role: 'menuitem', tabindex: '-1', 'data-action': action },\n on: {\n click: run,\n pointerenter: (event) => (event.currentTarget as HTMLElement).focus(),\n },\n },\n [icon(doc, glyph), label],\n )\n return el(\n doc,\n 'div',\n {\n class: 'card menu',\n attrs: { role: 'menu', 'aria-label': m.accountMenu, tabindex: '-1', 'data-action': 'menu' },\n on: { keydown: onMenuKey },\n },\n [\n el(doc, 'div', { class: 'menu-head' }, [\n avatar(name, true),\n el(doc, 'div', { class: 'menu-who' }, [\n el(doc, 'span', { class: 'menu-name', text: name ?? m.someone }),\n email ? el(doc, 'span', { class: 'menu-mail', text: email }) : null,\n ]),\n ]),\n el(doc, 'div', { class: 'sep', attrs: { role: 'separator' } }),\n item('open-zap', m.openInZap, 'external', () => {\n setMenu(false, 'account')\n win.open(zapUrl(data?.viewer?.editorUrl, ctx.zapOrigin), '_blank', 'noopener')\n }),\n el(doc, 'div', { class: 'sep', attrs: { role: 'separator' } }),\n item('sign-out', m.signOut, 'exit', exit),\n ],\n )\n }\n\n function onMenuKey(event: Event): void {\n const e = event as KeyboardEvent\n if (e.key === 'Tab') {\n // Close, and let Tab move on from the chip.\n setMenu(false, 'account')\n return\n }\n const items = Array.from(bottom.querySelectorAll<HTMLElement>('.menu [role=\"menuitem\"]'))\n const at = items.indexOf(host.root.activeElement as HTMLElement)\n const to = (\n { ArrowDown: at + 1, ArrowUp: at < 0 ? -1 : at - 1, Home: 0, End: -1 } as Record<\n string,\n number\n >\n )[e.key]\n if (to === undefined) return\n e.preventDefault()\n items[(to + items.length) % items.length]?.focus()\n }\n\n function pill(): HTMLElement {\n const [open, shown] = openCount()\n // The pill drags like the grip (`drag.ts`); a press that did not move is the click.\n return withTip(\n drag.grab(\n el(\n doc,\n 'button',\n {\n class: 'card pill',\n attrs: {\n type: 'button',\n 'aria-label':\n m.showBar(open).replace(String(open), shown) + (paused ? `. ${m.paused}` : ''),\n 'data-action': 'show',\n },\n on: { click: () => setHidden(false, true) },\n },\n [\n icon(doc, 'zap', 20),\n el(doc, 'span', { class: 'pill-count' }, [icon(doc, 'thread', 14), shown]),\n ],\n ),\n ),\n m.show,\n false,\n )\n }\n\n function toolbar(): HTMLElement {\n const [open, shown] = openCount()\n const name = data?.viewer?.name ?? null\n const tool = (value: Mode, label: string, glyph: IconName) => {\n const off = (value === 'edit' && !canEdit()) || (!!paused && value !== 'navigate')\n // Disabled by the ADMIN: says so; still loading: just not yet.\n const why = paused && off ? m.paused : off && data ? m.editOff : null\n return el(\n doc,\n 'button',\n {\n class: 'seg',\n attrs: {\n type: 'button',\n 'aria-pressed': String(mode === value),\n 'aria-disabled': off ? 'true' : null,\n title: why,\n 'data-tip': why,\n 'data-mode': value,\n },\n on: { click: () => setMode(value) },\n },\n [icon(doc, glyph, 14), label],\n )\n }\n return el(\n doc,\n 'div',\n { class: 'card toolbar', attrs: { role: 'toolbar', 'aria-label': m.toolbar } },\n [\n drag.handle,\n el(doc, 'span', { class: 'divider', attrs: { 'aria-hidden': 'true' } }),\n icon(doc, 'zap', 20),\n el(doc, 'div', { class: 'segments', attrs: { role: 'group', 'aria-label': m.tools } }, [\n tool('navigate', m.navigate, 'pointer'),\n tool('edit', m.edit, 'pencil'),\n tool('comment', m.comment, 'commentPlus'),\n ]),\n el(doc, 'span', { class: 'divider', attrs: { 'aria-hidden': 'true' } }),\n el(\n doc,\n 'button',\n {\n class: 'tool strong',\n attrs: { type: 'button', 'aria-expanded': String(!!list), 'data-action': 'open-list' },\n on: {\n click: () => {\n list = list ? null : (data?.comments ?? [])\n renderBottom()\n },\n },\n },\n [icon(doc, 'thread'), m.open(open).replace(String(open), shown)],\n ),\n el(doc, 'span', { class: 'divider', attrs: { 'aria-hidden': 'true' } }),\n el(\n doc,\n 'button',\n {\n class: 'tool account',\n attrs: {\n type: 'button',\n 'aria-haspopup': 'menu',\n 'aria-expanded': String(menuOpen),\n 'aria-label': name ? m.account(name) : m.accountMenu,\n 'data-action': 'account',\n },\n on: {\n // A pointer opens onto the menu itself; Enter or Space onto its first item.\n click: (event) =>\n setMenu(\n !menuOpen,\n menuOpen ? 'account' : (event as MouseEvent).detail ? 'menu' : 'open-zap',\n ),\n keydown: (event) => {\n const k = (event as KeyboardEvent).key\n if (k !== 'ArrowDown' && k !== 'ArrowUp') return\n event.preventDefault()\n setMenu(true, k === 'ArrowUp' ? 'sign-out' : 'open-zap')\n },\n },\n },\n [avatar(name), icon(doc, 'chevron', 13)],\n ),\n withTip(\n el(\n doc,\n 'button',\n {\n class: 'tool hide',\n attrs: { type: 'button', 'aria-label': m.hide, 'data-action': 'hide' },\n on: { click: () => setHidden(true, true) },\n },\n [icon(doc, 'eyeOff', 16)],\n ),\n m.hide,\n true,\n ),\n ],\n )\n }\n\n function trayCard(): HTMLElement {\n return el(doc, 'div', { class: 'card tray', attrs: { role: 'status' } }, [\n el(doc, 'span', { text: m.selected(selection.length) }),\n el(doc, 'button', {\n class: 'btn btn-outline',\n text: m.clearSelection,\n attrs: { type: 'button' },\n on: {\n click: () => {\n selection = []\n overlay.clearSelection()\n renderBottom()\n },\n },\n }),\n el(doc, 'button', {\n class: 'btn btn-primary',\n text: m.comment,\n attrs: { type: 'button', 'data-action': 'comment-selection' },\n on: {\n click: () => {\n const elements = selection\n selection = []\n overlay.clearSelection()\n openComposer(elements, null)\n },\n },\n }),\n ])\n }\n\n function listCard(comments: OnPageComment[]): HTMLElement {\n return el(\n doc,\n 'div',\n { class: 'card list sheet', attrs: { role: 'dialog', 'aria-label': m.openTitle } },\n [\n el(doc, 'div', { class: 'head' }, [\n el(doc, 'h2', { text: m.openTitle }),\n closeButton(m.dismiss, () => {\n list = null\n renderBottom()\n }),\n ]),\n comments.length === 0\n ? el(doc, 'p', { class: 'muted', text: m.noneOpen })\n : el(\n doc,\n 'ul',\n {},\n comments.map((comment) => {\n const n = numbers.get(comment.id)\n return el(doc, 'li', {}, [\n el(\n doc,\n 'button',\n {\n class: 'item',\n attrs: { type: 'button', 'data-comment': comment.id },\n on: { click: () => reveal(comment.id) },\n },\n [\n n ? el(doc, 'span', { class: 'num', text: String(n) }) : null,\n el(doc, 'span', { class: 'item-text' }, [\n el(doc, 'span', { class: 'who', text: comment.author?.name || m.someone }),\n comment.isChangeRequest\n ? el(doc, 'span', { class: 'flag', text: m.changeRequest })\n : null,\n el(doc, 'span', { class: 'what', text: comment.excerpt ?? '' }),\n ]),\n ],\n ),\n ])\n }),\n ),\n ],\n )\n }\n\n /** Scroll to a thread's pin. */\n function reveal(id: string): void {\n const pin = pins.find((entry) => entry.id === id)\n if (pin?.element) scrollTo(win, pin.element)\n else if (pin?.spot) {\n const root = doc.documentElement\n win.scrollTo?.({\n top: Math.max(0, pin.spot.y * root.scrollHeight - win.innerHeight / 2),\n behavior: 'smooth',\n })\n }\n }\n\n function toastCard(value: { title: string; body: string; error?: boolean }): HTMLElement {\n return el(\n doc,\n 'div',\n {\n class: value.error ? 'card toast toast-error' : 'card toast',\n attrs: { role: 'status', 'aria-live': 'polite' },\n },\n [\n icon(doc, value.error ? 'alert' : 'check', 18),\n el(doc, 'div', { class: 'toast-text' }, [\n el(doc, 'span', { class: 'title', text: value.title }),\n el(doc, 'span', { class: 'muted', text: value.body }),\n ]),\n closeButton(m.dismiss, () => setToast(null)),\n ],\n )\n }\n\n /** The guard's pause (the editor banner's words), quiet: the refused card's layout, a muted icon. */\n function pausedCard(reason: PauseReason): HTMLElement {\n return el(doc, 'div', { class: 'card refused paused', attrs: { role: 'status' } }, [\n icon(doc, 'alert', 18),\n el(doc, 'div', { class: 'toast-text' }, [\n el(doc, 'span', { class: 'title', text: m.paused }),\n el(doc, 'span', {\n class: 'muted',\n text: reason === 'cap' ? m.pausedCap : m.pausedRunaway,\n }),\n ]),\n el(doc, 'button', {\n class: 'tool',\n text: m.reload,\n attrs: { type: 'button', 'data-action': 'reload' },\n on: { click: () => win.location.reload() },\n }),\n ])\n }\n\n /** The session ran out (item 32): not a refusal, so the way back is one click. */\n function expiredCard(): HTMLElement {\n return el(doc, 'div', { class: 'card refused', attrs: { role: 'alert' } }, [\n icon(doc, 'alert', 18),\n el(doc, 'div', { class: 'toast-text' }, [\n el(doc, 'span', { class: 'title', text: sm.expiredTitle }),\n el(doc, 'span', { class: 'muted', text: sm.expiredBody }),\n ]),\n el(\n doc,\n 'button',\n {\n class: 'tool',\n attrs: { type: 'button', 'data-action': 'sign-in-again' },\n on: { click: signInAgain },\n },\n [icon(doc, 'eel'), sm.signInAgain],\n ),\n ])\n }\n\n function refusedCard(): HTMLElement {\n return el(doc, 'div', { class: 'card refused', attrs: { role: 'alert' } }, [\n icon(doc, 'alert', 18),\n el(doc, 'div', { class: 'toast-text' }, [\n el(doc, 'span', { class: 'title', text: m.refusedTitle }),\n el(doc, 'span', { class: 'muted', text: m.refusedBody }),\n ]),\n el(\n doc,\n 'button',\n { class: 'tool', attrs: { type: 'button', 'data-action': 'exit' }, on: { click: exit } },\n [icon(doc, 'exit'), m.exit],\n ),\n ])\n }\n\n function closeButton(label: string, onClick: () => void): HTMLElement {\n return el(\n doc,\n 'button',\n {\n class: 'iconbtn',\n attrs: { type: 'button', 'aria-label': label, title: label },\n on: { click: onClick },\n },\n [icon(doc, 'x')],\n )\n }\n\n function setToast(value: typeof toast): void {\n toast = value\n if (toastTimer !== null) win.clearTimeout(toastTimer)\n toastTimer = value ? win.setTimeout(() => setToast(null), TOAST_MS) : null\n renderBottom()\n }\n\n function setStatus(value: typeof status): void {\n status = value\n if (statusTimer !== null) win.clearTimeout(statusTimer)\n statusTimer = value === 'saved' ? win.setTimeout(() => setStatus(null), SAVED_MS) : null\n renderBottom()\n }\n\n function exit(): void {\n // Drop this tab's draft session too (revoked at Zap, the cookie through\n // the site's exit route, then a published reload) when it has one.\n void leaveDraftSession(ctx, auth.token(), index.elements.length > 0)\n clearToken(win)\n ctx.close()\n }\n\n // ── Pins and marks ──────────────────────────────────────────────────────\n\n function placePins(): void {\n if (destroyed || refused || paused || !data) return\n const placed = pinsFor(data.comments ?? [], index, doc, win)\n pins = placed.pins\n numbers = placed.numbers\n overlay.setPins(composer?.pin ? [...pins, composer.pin] : pins)\n }\n\n /** The soft gold outline around what is being edited or commented (SitioEditar). */\n function drawMarks(): void {\n const targets = editing ? [editing.element] : (composer?.elements ?? [])\n marks.replaceChildren(\n ...targets\n .filter((element) => element.isConnected)\n .map((element) => {\n const rect = element.getBoundingClientRect()\n const box = el(doc, 'div', { class: 'mark' })\n box.style.left = `${rect.left - 3}px`\n box.style.top = `${rect.top - 3}px`\n box.style.width = `${rect.width + 6}px`\n box.style.height = `${rect.height + 6}px`\n // The field's chip stays above an element edited in a card (SitioEditarOpcion).\n if (editing?.card)\n box.append(\n el(doc, 'span', {\n class: 'mark-chip',\n text: editing.field.label || editing.tagged.fieldKey,\n }),\n )\n return box\n }),\n )\n }\n\n function schedule(): void {\n if (frame !== null) return\n const raf = win.requestAnimationFrame?.bind(win) ?? ((fn: () => void) => win.setTimeout(fn, 16))\n frame = raf(() => {\n frame = null\n drawMarks()\n if (composer) position(composer.card, anchorRect(composer))\n if (editing?.card)\n position(editing.card, editing.element.getBoundingClientRect(), editing.card.offsetWidth)\n if (info) position(info.card, info.tagged.element.getBoundingClientRect(), 300)\n }) as number\n }\n\n /**\n * Place a card (an editor, «Este campo se edita en Zap», the composer)\n * beside what it is about: 10px under it, else over it, clear of the\n * viewport's edges AND of the bar (or the pill) wherever it was dragged.\n * Each side is tried as is, then shifted sideways past the bar; when none\n * is clear, the first that fits the viewport wins.\n */\n function position(\n card: HTMLElement,\n rect: Pick<DOMRect, 'left' | 'top' | 'bottom'>,\n preferred = 420,\n ): void {\n const vw = win.innerWidth\n const vh = win.innerHeight\n const width = Math.min(preferred, vw - 16)\n // Measured at its final width: text wraps there.\n card.style.width = `${width}px`\n const height = card.offsetHeight || 260\n const bar = bottom.querySelector('.toolbar, .pill')?.getBoundingClientRect()\n const clampX = (x: number) => Math.min(Math.max(8, x), Math.max(8, vw - width - 8))\n const hits = (x: number, y: number) =>\n !!bar &&\n x < bar.right + 8 &&\n x + width > bar.left - 8 &&\n y < bar.bottom + 8 &&\n y + height > bar.top - 8\n const fits = (y: number) => y >= 8 && y + height <= vh - 8\n let place: [number, number] | null = null\n for (const y of [rect.bottom + 10, rect.top - height - 10]) {\n if (!fits(y)) continue\n for (const x of [\n clampX(rect.left),\n clampX((bar?.right ?? 0) + 8),\n clampX((bar?.left ?? 0) - 8 - width),\n ]) {\n if (!hits(x, y)) {\n place = [x, y]\n break\n }\n }\n if (place) break\n }\n if (!place) {\n const y = fits(rect.bottom + 10) ? rect.bottom + 10 : Math.max(8, rect.top - height - 10)\n place = [clampX(rect.left), y]\n }\n card.style.left = `${place[0]}px`\n card.style.top = `${place[1]}px`\n }\n\n // ── Comentar ────────────────────────────────────────────────────────────\n\n function onSelect(elements: Element[]): void {\n if (mode !== 'comment' || composer) return\n if (elements.length === 0) {\n if (selection.length > 0) {\n selection = []\n renderBottom()\n }\n return\n }\n if (lastClick.additive || elements.length > 1) {\n selection = elements\n renderBottom()\n return\n }\n const element = elements[0]!\n overlay.clearSelection()\n if (isLarge(element)) openComposer([], { x: lastClick.x, y: lastClick.y }, element)\n else openComposer([element], null)\n }\n\n /** Most of the viewport: a wrapper, not the thing the person pointed at. */\n function isLarge(element: Element): boolean {\n const rect = element.getBoundingClientRect()\n const area = Math.max(1, win.innerWidth * win.innerHeight)\n return (rect.width * rect.height) / area >= LARGE_SHARE\n }\n\n function anchorRect(session: Composer): Pick<DOMRect, 'left' | 'top' | 'bottom'> {\n const first = session.elements[0]\n if (first) return first.getBoundingClientRect()\n const point = session.point ?? { x: 0, y: 0 }\n return { left: point.x, top: point.y, bottom: point.y }\n }\n\n function openComposer(\n elements: Element[],\n point: { x: number; y: number } | null,\n owner?: Element,\n ): void {\n if (refused || (elements.length === 0 && !point)) return\n const recordRef = recordFor(elements[0] ?? owner ?? doc.body, index)\n if (!recordRef) {\n setToast({ title: m.failed, body: m.noRecord, error: true })\n return\n }\n list = null\n const pageUrl = currentPageUrl(win)\n const anchors: ApiAnchor[] = point\n ? [spotAnchor(point.x, point.y, doc, win)]\n : elements\n .slice(0, 20)\n .map((element) => toApiAnchor(buildAnchor(element, index, pageUrl, doc, win), recordRef))\n const single = elements.length === 1 ? elements[0]! : null\n const own = single ? index.get(single) : null\n const tagged = own && own.recordRef === recordRef ? own : null\n const field = fieldOf(data, tagged)\n const proposable = proposableField(tagged, field)\n const target = single as HTMLElement | null\n const before =\n field?.type === 'URL' && target?.localName === 'a'\n ? (target.getAttribute('href') ?? '')\n : normalizeText(target?.textContent ?? '')\n const spotPin = point ? anchors[0] : null\n\n const textarea = el(doc, 'textarea', {\n class: 'composer',\n attrs: {\n 'aria-label': m.commentLabel,\n rows: '3',\n maxlength: '10000',\n placeholder: m.commentPlaceholder,\n },\n })\n const error = el(doc, 'p', { class: 'error', attrs: { role: 'alert' } })\n const sendButton = el(\n doc,\n 'button',\n {\n class: 'btn btn-primary',\n attrs: { type: 'button', 'data-action': 'send' },\n on: { click: () => void submit() },\n },\n [icon(doc, 'commentPlus', 16), m.comment],\n )\n const title = tagged\n ? el(doc, 'span', { class: 'chip' }, [\n icon(doc, 'field', 12),\n field?.label || tagged.fieldKey,\n ])\n : el(doc, 'h2', {\n text: elements.length > 1 ? m.selected(elements.length) : m.commentTitle,\n })\n const extra = el(doc, 'div', { class: 'extra' })\n const card = el(\n doc,\n 'div',\n { class: 'card popover sheet', attrs: { role: 'dialog', 'aria-label': m.newComment } },\n [\n el(doc, 'div', { class: 'head' }, [title, closeButton(m.close, closeComposer)]),\n el(doc, 'div', { class: 'content' }, [\n textarea,\n extra,\n error,\n // A dialog footer: a full-bleed rule, Cancelar and the primary (OWNER-PASS 19).\n el(doc, 'div', { class: 'foot' }, [\n el(doc, 'button', {\n class: 'btn btn-outline',\n text: m.cancel,\n attrs: { type: 'button' },\n on: { click: closeComposer },\n }),\n sendButton,\n ]),\n ]),\n ],\n )\n layer.append(card)\n\n composer = {\n elements,\n point,\n pin:\n spotPin && 'spot' in spotPin\n ? { id: PENDING_PIN, n: (numbers.size || 0) + 1, spot: spotPin.spot }\n : null,\n recordRef,\n pageUrl,\n anchors,\n tagged: proposable ? tagged : null,\n field: proposable ? field : null,\n before,\n card,\n textarea,\n request: false,\n proposing: false,\n proposal: null,\n error,\n sendButton,\n busy: false,\n idempotency: null,\n }\n renderExtra(extra)\n textarea.addEventListener('input', refreshSend)\n // Enter sends, Shift+Enter breaks the line, as the editor's comment box and\n // Swarm's; the Enter that commits an IME candidate never sends.\n textarea.addEventListener('keydown', (event) => {\n if (event.key !== 'Enter' || event.shiftKey || event.isComposing || event.keyCode === 229) {\n return\n }\n event.preventDefault()\n if (!sendButton.disabled) void submit()\n })\n overlay.setMode('off')\n placePins()\n refreshSend()\n renderBottom()\n position(card, anchorRect(composer))\n textarea.focus()\n }\n\n /** «Solicitar cambio», who receives it, and «Proponer texto» (SitioSugerencia). */\n function renderExtra(extra: HTMLElement): void {\n const session = composer\n if (!session) return\n const toggle = el(\n doc,\n 'button',\n {\n class: 'check',\n attrs: {\n type: 'button',\n role: 'checkbox',\n 'aria-checked': String(session.request),\n 'data-action': 'request-change',\n },\n on: {\n click: () => {\n session.request = !session.request\n if (!session.request) {\n session.proposing = false\n session.proposal = null\n }\n renderExtra(extra)\n refreshSend()\n },\n },\n },\n [el(doc, 'span', { class: 'box', attrs: { 'aria-hidden': 'true' } }), m.requestChange],\n )\n const parts: Array<HTMLElement | null> = [toggle]\n if (session.request) {\n parts.push(el(doc, 'p', { class: 'muted small', text: m.recipient }))\n parts.push(el(doc, 'p', { class: 'muted small', text: m.requestHelp }))\n if (session.tagged && session.field && !session.proposing) {\n parts.push(\n el(\n doc,\n 'button',\n {\n class: 'btn btn-outline propose',\n attrs: { type: 'button', 'data-action': 'propose' },\n on: {\n click: () => {\n session.proposing = true\n renderExtra(extra)\n refreshSend()\n session.proposal?.focus()\n },\n },\n },\n [icon(doc, 'pencil', 14), m.propose],\n ),\n )\n }\n if (session.tagged && session.field && session.proposing) {\n const label = session.field.label || session.tagged.fieldKey\n const input =\n session.field.type === 'LONG_TEXT'\n ? el(doc, 'textarea', {\n class: 'value',\n attrs: { 'aria-label': m.proposal, rows: '3', maxlength: '10000' },\n })\n : el(doc, 'input', {\n class: 'value',\n attrs: {\n 'aria-label': m.proposal,\n type: 'text',\n inputmode: session.field.type === 'NUMBER' ? 'decimal' : null,\n },\n })\n input.value = session.proposal?.value ?? session.before\n input.addEventListener('input', refreshSend)\n session.proposal = input\n parts.push(\n el(doc, 'div', { class: 'proposal' }, [\n el(doc, 'div', { class: 'head' }, [\n el(doc, 'span', { class: 'small strong-text', text: `${m.proposalFor} ${label}` }),\n closeButton(m.removeProposal, () => {\n session.proposing = false\n session.proposal = null\n renderExtra(extra)\n refreshSend()\n }),\n ]),\n session.before\n ? el(doc, 'p', { class: 'muted small before' }, [\n `${m.now} `,\n el(doc, 'span', { class: 'strong-text', text: session.before }),\n ])\n : null,\n input,\n ]),\n )\n }\n }\n extra.replaceChildren(...parts.filter((part): part is HTMLElement => part !== null))\n }\n\n /** The proposal typed, null when none or unchanged, `invalid` for a number that is not one. */\n function proposalOf(session: Composer): Proposal | null | 'invalid' {\n if (!session.request || !session.proposing || !session.proposal) return null\n if (!session.tagged || !session.field) return null\n const parsed = parseProposed(session.field.type, session.proposal.value)\n if (!parsed.ok) return 'invalid'\n const before = parseProposed(session.field.type, session.before)\n if (before.ok && sameValue(before.value, parsed.value)) return null\n return { fieldKey: session.tagged.fieldKey, locale: session.tagged.locale, value: parsed.value }\n }\n\n function refreshSend(): void {\n const session = composer\n if (!session) return\n const proposal = proposalOf(session)\n const comment = session.textarea.value.trim()\n // The primary names what it does: «Comentar», or «Solicitar cambio» once flagged.\n session.sendButton.replaceChildren(\n icon(doc, session.request ? 'pencil' : 'commentPlus', 16),\n session.busy ? m.sending : session.request ? m.requestChange : m.comment,\n )\n // Text, or a parsed proposal that is not empty: either makes a body.\n const proposed = proposal && proposal !== 'invalid' && String(proposal.value) !== ''\n session.sendButton.disabled = session.busy || proposal === 'invalid' || (!comment && !proposed)\n session.error.textContent =\n proposal === 'invalid' ? m.invalidNumber : (session.error.dataset.sticky ?? '')\n }\n\n function showError(message: string): void {\n if (!composer) return\n composer.error.dataset.sticky = message\n composer.error.textContent = message\n }\n\n async function submit(): Promise<void> {\n const session = composer\n if (!session || session.busy) return\n const proposal = proposalOf(session)\n if (proposal === 'invalid') return\n const body = buildCreateBody({\n recordRef: session.recordRef,\n pageUrl: session.pageUrl,\n anchors: session.anchors,\n comment: session.textarea.value,\n isChangeRequest: session.request,\n proposal,\n })\n if (!body.body) return\n // One key per payload: a retry of the same request is the same request.\n const payload = JSON.stringify(body)\n if (session.idempotency?.payload !== payload) {\n session.idempotency = { payload, key: newIdempotencyKey(win) }\n }\n session.busy = true\n delete session.error.dataset.sticky\n refreshSend()\n const key = session.idempotency.key\n const result = await auth.call((token) => createComment(ctx, token, body, key))\n if (destroyed || composer !== session) return\n session.busy = false\n if (!result.ok) {\n refreshSend()\n onFailure(result, 'comment')\n return\n }\n closeComposer()\n const assignee = result.data?.thread?.assignee?.name\n setToast(\n body.isChangeRequest\n ? {\n title: m.sentRequest,\n body: m.sentRequestBody(\n typeof assignee === 'string' && assignee ? assignee : null,\n !!body.proposedValues,\n ),\n }\n : { title: m.sentComment, body: m.sentCommentBody },\n )\n void load()\n }\n\n function closeComposer(): void {\n const session = composer\n if (!session) return\n composer = null\n session.card.remove()\n if (!refused) {\n overlay.setMode(OVERLAY_MODE[mode])\n placePins()\n }\n renderBottom()\n }\n\n // ── Editar ──────────────────────────────────────────────────────────────\n\n function beginEdit(tagged: TaggedElement): void {\n if (mode !== 'edit' || refused || !canEdit()) return\n if (editing && !editing.done) {\n if (editing.element === tagged.element) return\n commitEdit(editing)\n }\n const field = fieldOf(data, tagged)\n const kind = editKindFor(tagged, field)\n if (!kind || !field) {\n // Rich text, media and the rest: no editor on the page, a way there instead.\n openInfoCard(tagged)\n return\n }\n closeInfo()\n const element = tagged.element as HTMLElement\n const pageUrl = currentPageUrl(win)\n // The anchor BEFORE any edit: its text quote is what was published.\n const anchors = [toApiAnchor(buildAnchor(element, index, pageUrl, doc, win), tagged.recordRef)]\n const before =\n field.type === 'URL' && element.localName === 'a'\n ? (element.getAttribute('href') ?? '')\n : normalizeText(element.textContent ?? '')\n // The page shows these formatted («1.750 msnm», «Sí»): the editor opens on\n // the stored value Zap sent; an older Zap sends none, and a NUMBER then\n // reads the page's text as before.\n const stored = data?.values?.[tagged.recordRef]?.[tagged.fieldKey]\n const legacy =\n field.type === 'NUMBER' && stored === undefined ? parseProposed('NUMBER', before) : null\n const raw: RawValue | undefined = legacy?.ok ? legacy.value : stored\n const inline = kind === 'text' ? beginInlineEdit(element) : null\n const session: Editing = {\n element,\n tagged,\n field,\n kind,\n recordRef: tagged.recordRef,\n pageUrl,\n anchors,\n before,\n raw,\n picked: raw,\n returnFocus: doc.activeElement,\n revert: inline?.revert ?? (() => {}),\n keep: inline?.keep ?? (() => {}),\n card: null,\n input: null,\n done: false,\n }\n editing = session\n if (inline) {\n element.addEventListener('blur', () => commitEdit(session), { once: true })\n element.focus?.()\n } else if (kind === 'choice') {\n openChoiceCard(session)\n } else if (kind === 'switch') {\n openSwitchCard(session)\n } else {\n openInputCard(session)\n }\n renderBottom()\n }\n\n /**\n * The editor beside the element (SitioEditarOpcion, Numero, Fecha, SiNo):\n * `body` and the key hint «Enter guarda · Esc cancela», 10px under the\n * element so the field's chip stays above it, flipped above when there is\n * no room. No buttons: Enter (or a pick) saves, Escape cancels, a press\n * outside saves as leaving a text field does.\n */\n function openValueCard(\n session: Editing,\n body: HTMLElement,\n focus: HTMLElement,\n width: number,\n ): void {\n const label = session.field.label || session.tagged.fieldKey\n const card = el(\n doc,\n 'div',\n {\n class: 'card editor',\n attrs: { role: 'dialog', 'aria-label': label },\n on: {\n keydown: (event) => {\n const e = event as KeyboardEvent\n // Enter saves from an input or the switch; an option's Enter picks it (a click).\n if (e.key !== 'Enter' || (e.target as Element).getAttribute('role') === 'option') return\n e.preventDefault()\n commitEdit(session)\n },\n },\n },\n [\n body,\n el(doc, 'div', { class: 'keys' }, [\n kbd(doc, 'Enter'),\n m.enterSaves,\n kbd(doc, 'Esc'),\n m.escCancels,\n ]),\n ],\n )\n card.style.width = `${width}px`\n session.card = card\n layer.append(card)\n position(card, session.element.getBoundingClientRect(), width)\n focus.focus()\n }\n\n /** URL, numbers and dates: a native input with the field's constraints; the page is not touched. */\n function openInputCard(session: Editing): void {\n const { field } = session\n const spec =\n field.type === 'URL'\n ? { type: 'url', text: session.before, min: undefined, max: undefined, step: undefined }\n : inputSpec(field, session.raw)\n const input = el(doc, 'input', {\n class: 'value',\n attrs: {\n 'aria-label': field.label || session.tagged.fieldKey,\n type: spec.type,\n min: spec.min === undefined ? null : String(spec.min),\n max: spec.max === undefined ? null : String(spec.max),\n step: spec.step === undefined ? null : String(spec.step),\n },\n })\n input.value = spec.text\n session.input = input\n const unit = field.type === 'CURRENCY' ? (field.currency ?? null) : null\n openValueCard(\n session,\n unit\n ? el(doc, 'div', { class: 'with-unit' }, [\n input,\n el(doc, 'span', { class: 'muted', text: unit }),\n ])\n : input,\n input,\n field.type === 'URL' ? 280 : 220,\n )\n }\n\n /** ENUM: its options, a check on the current one; a pick saves at once (arrows move). */\n function openChoiceCard(session: Editing): void {\n const buttons = (session.field.options ?? []).map((option) =>\n el(\n doc,\n 'button',\n {\n class: 'option',\n attrs: {\n type: 'button',\n role: 'option',\n 'aria-selected': String(option.id === session.raw),\n tabindex: '-1',\n },\n on: {\n click: () => {\n session.picked = option.id\n commitEdit(session)\n },\n },\n },\n [\n el(doc, 'span', { class: 'option-label', text: option.label }),\n option.id === session.raw ? icon(doc, 'tick', 14) : null,\n ],\n ),\n )\n const first =\n buttons.find((button) => button.getAttribute('aria-selected') === 'true') ?? buttons[0]!\n first.tabIndex = 0\n const list = el(\n doc,\n 'div',\n {\n class: 'options',\n attrs: { role: 'listbox', 'aria-label': m.options(session.field.label) },\n on: {\n keydown: (event) => {\n const e = event as KeyboardEvent\n const at = buttons.indexOf(host.root.activeElement as HTMLButtonElement)\n const to = (\n { ArrowDown: at + 1, ArrowUp: at - 1, Home: 0, End: buttons.length - 1 } as Record<\n string,\n number\n >\n )[e.key]\n if (to === undefined) return\n e.preventDefault()\n buttons[Math.min(buttons.length - 1, Math.max(0, to))]?.focus()\n },\n },\n },\n buttons,\n )\n openValueCard(session, list, first, 230)\n }\n\n /** BOOLEAN: the field's name and a switch (Space or a click flips it); Enter saves. */\n function openSwitchCard(session: Editing): void {\n session.picked = session.raw === true\n const label = session.field.label || session.tagged.fieldKey\n const toggle = el(\n doc,\n 'button',\n {\n class: 'switch',\n attrs: {\n type: 'button',\n role: 'switch',\n 'aria-checked': String(session.picked),\n 'aria-label': label,\n },\n on: {\n click: () => {\n session.picked = !session.picked\n toggle.setAttribute('aria-checked', String(session.picked))\n },\n },\n },\n [el(doc, 'span', { class: 'knob' })],\n )\n openValueCard(\n session,\n el(doc, 'div', { class: 'switch-row' }, [\n el(doc, 'span', { class: 'title', text: label }),\n toggle,\n ]),\n toggle,\n 220,\n )\n }\n\n /**\n * «Este campo se edita en Zap» (SitioEditarEnZap): rich text, media and any\n * other type, beside the element, with the field named and two ways on:\n * its record's editor in Zap at this field, or Comentar on the element.\n * Quiet, not an error.\n */\n function openInfoCard(tagged: TaggedElement): void {\n closeInfo()\n const field = fieldOf(data, tagged)\n const label = field?.label || tagged.fieldKey\n const card = el(\n doc,\n 'div',\n { class: 'card info', attrs: { role: 'dialog', 'aria-label': m.editInZap } },\n [\n icon(doc, 'info', 16),\n el(doc, 'div', { class: 'toast-text' }, [\n el(doc, 'span', { class: 'title', text: m.editInZap }),\n el(doc, 'span', {\n class: 'muted',\n text: m.editInZapBody(label, field?.type ?? '', tagged.recordRef.startsWith('doc:')),\n }),\n el(doc, 'div', { class: 'actions start' }, [\n el(\n doc,\n 'button',\n {\n class: 'btn btn-outline',\n attrs: { type: 'button', 'data-action': 'open-field' },\n on: {\n click: () => {\n closeInfo()\n win.open(fieldEditorUrl(tagged), '_blank', 'noopener')\n },\n },\n },\n [icon(doc, 'external', 14), m.openInZap],\n ),\n el(\n doc,\n 'button',\n {\n class: 'btn btn-ghost',\n attrs: { type: 'button', 'data-action': 'comment-field' },\n on: {\n click: () => {\n closeInfo()\n setMode('comment')\n if (mode === 'comment') openComposer([tagged.element], null)\n },\n },\n },\n [icon(doc, 'commentPlus', 14), m.comment],\n ),\n ]),\n ]),\n ],\n )\n info = { tagged, card }\n layer.append(card)\n position(card, tagged.element.getBoundingClientRect(), 300)\n }\n\n function closeInfo(): void {\n info?.card.remove()\n info = null\n }\n\n /**\n * The editor of the record that OWNS the field, at that field (`?field=`,\n * Zap's locate): `editorUrls` by ref; an older Zap sends only the page's\n * own record, used when the field is that record's; else Zap's home.\n */\n function fieldEditorUrl(tagged: TaggedElement): string {\n const own = !data?.records?.[tagged.recordRef]\n const base =\n data?.editorUrls?.[tagged.recordRef] ?? (own ? data?.viewer?.editorUrl : null) ?? null\n const safe = zapUrl(base, ctx.zapOrigin)\n if (!base) return safe\n try {\n const url = new URL(safe)\n url.searchParams.set('field', tagged.fieldKey)\n return url.href\n } catch {\n return safe\n }\n }\n\n /** Make the element editable in place; how to put it back, or keep what was typed. */\n function beginInlineEdit(target: HTMLElement): { revert: () => void; keep: () => void } {\n const children = Array.from(target.childNodes)\n const texts: Array<[Text, string]> = []\n const walker = doc.createTreeWalker(target, 4 /* NodeFilter.SHOW_TEXT */)\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n texts.push([node as Text, (node as Text).data])\n }\n const hadAttribute = target.getAttribute('contenteditable')\n target.setAttribute('contenteditable', 'plaintext-only')\n if (target.contentEditable !== 'plaintext-only') target.setAttribute('contenteditable', 'true')\n target.setAttribute('spellcheck', 'true')\n const keep = () => {\n if (hadAttribute === null) target.removeAttribute('contenteditable')\n else target.setAttribute('contenteditable', hadAttribute)\n target.removeAttribute('spellcheck')\n }\n return {\n keep,\n revert: () => {\n keep()\n // The SAME nodes back, with their text: a framework holding them keeps working.\n target.replaceChildren(...children)\n for (const [node, text] of texts) node.data = text\n },\n }\n }\n\n function typedValue(session: Editing): string {\n if (session.input) return session.input.value\n return editableText(session.element)\n }\n\n function finishEdit(session: Editing, keepTyped: boolean): void {\n session.done = true\n if (keepTyped) session.keep()\n else session.revert()\n session.card?.remove()\n if (editing === session) editing = null\n renderBottom()\n // Focus goes back where it was before the editor opened.\n const back = session.returnFocus as HTMLElement | null\n if (session.card && back?.isConnected) back.focus?.({ preventScroll: true })\n }\n\n function cancelEdit(session: Editing): void {\n if (session.done) return\n finishEdit(session, false)\n }\n\n /** Save what was typed or picked to the draft, or put the element back when nothing changed. */\n function commitEdit(session: Editing): void {\n if (session.done) return\n const { field, kind } = session\n // Text and URL compare with what the page showed; the other types with\n // the stored value Zap sent (`sameRaw`).\n const text = kind === 'text' || field.type === 'URL'\n let value: RawValue\n if (text) {\n const parsed = parseProposed(field.type, typedValue(session))\n const before = parseProposed(field.type, session.before)\n if (parsed.ok && before.ok && sameValue(before.value, parsed.value)) {\n finishEdit(session, false)\n return\n }\n if (!parsed.ok) return invalid(session)\n value = parsed.value\n } else if (kind === 'input') {\n // A native number or date input the browser cannot parse (\"15,5\" where\n // the decimal mark is a point) reports an empty value: that is not a\n // clear, so never save it as one.\n if (session.input?.validity?.badInput) return invalid(session)\n const parsed = parseInput(field, typedValue(session))\n if (!parsed.ok) return invalid(session)\n value = parsed.value\n } else {\n value = session.picked ?? null\n }\n // Nothing changed (stega markers and whitespace aside): put the element\n // back and write nothing, no thread and no draft.\n if (!text && sameRaw(field.type, session.raw, value)) {\n finishEdit(session, false)\n return\n }\n finishEdit(session, true)\n void save(\n session,\n { fieldKey: session.tagged.fieldKey, locale: session.tagged.locale, value },\n kind === 'choice'\n ? field.options?.find((option) => option.id === value)?.label\n : kind === 'switch'\n ? value\n ? m.yes\n : m.no\n : undefined,\n )\n }\n\n function invalid(session: Editing): void {\n finishEdit(session, false)\n setToast({ title: m.saveFailed, body: m.invalidNumber, error: true })\n }\n\n async function save(session: Editing, proposal: Proposal, display?: string): Promise<void> {\n setStatus('saving')\n const body = buildDraftBody({\n recordRef: session.recordRef,\n pageUrl: session.pageUrl,\n anchors: session.anchors,\n proposal,\n display,\n })\n // One key for the retry after a renewal too: a 401 wrote nothing, and the\n // same key keeps a doubled answer from saving twice.\n const draftKey = newIdempotencyKey(win)\n const result = await auth.call((token) => saveToDraft(ctx, token, body, draftKey))\n if (destroyed) return\n if (!result.ok) {\n setStatus(null)\n // Zap already holds that value: nothing to save and nothing to undo.\n if (result.kind === 'unchanged') return\n // The page goes back to what is published; nothing was saved.\n session.revert()\n onFailure(result, 'edit')\n return\n }\n setStatus('saved')\n // The next editor on this field opens on what was just saved, not on the\n // page read's value (the page may not reload: an ENUM label in place).\n if (data && session.raw !== undefined)\n (data.values ??= {})[session.recordRef] = {\n ...data.values[session.recordRef],\n [session.tagged.fieldKey]: proposal.value,\n }\n showSaved(session, display)\n }\n\n /**\n * After a save the page shows the new value. Text is already there (typed\n * in place) and a URL lands in the link's `href` at the next read; an\n * ENUM's label is written into an element tagged by attribute that holds\n * only text. Everything the site formats itself (numbers, dates, a\n * currency, a yes or no, an ENUM inside markup or found by stega) needs the\n * page to render again: it reloads in place (the browser keeps the scroll,\n * the draft session keeps it on the draft) and Editar reopens.\n * The editor preview's rule (`needsRefresh` in Zap).\n */\n function showSaved(session: Editing, display: string | undefined): void {\n const { field, tagged, element } = session\n if (session.kind === 'text' || field.type === 'URL') return\n if (\n field.type === 'ENUM' &&\n display !== undefined &&\n tagged.source === 'attr' &&\n element.children.length === 0\n ) {\n element.textContent = display\n return\n }\n rememberEditIntent(win)\n win.setTimeout(() => win.location.reload(), RELOAD_AFTER_SAVE_MS)\n }\n\n function endEdit(): void {\n if (editing && !editing.done) commitEdit(editing)\n }\n\n // ── Page events ─────────────────────────────────────────────────────────\n\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') hideTip()\n if (menuOpen && event.key === 'Escape') {\n event.preventDefault()\n setMenu(false, 'account')\n return\n }\n // Shift Z: bar to pill and back, never while editing a field or writing a comment.\n if (ctx.shortcut && !editing && !composer && isShortcut(event, ctx.shortcut)) {\n setHidden(!drag.hidden(), !!host.root.activeElement)\n return\n }\n if (composer && event.key === 'Escape') {\n event.preventDefault()\n closeComposer()\n return\n }\n if (info && event.key === 'Escape') {\n event.preventDefault()\n closeInfo()\n return\n }\n const session = editing\n if (!session || session.done) return\n if (event.key === 'Escape') {\n event.preventDefault()\n cancelEdit(session)\n } else if (\n event.key === 'Enter' &&\n session.kind === 'text' &&\n event.target === session.element &&\n (session.field.type === 'TEXT' || event.metaKey || event.ctrlKey)\n ) {\n // A one-line field stays one line; Enter (Cmd or Ctrl Enter for long text) saves.\n event.preventDefault()\n commitEdit(session)\n }\n }\n /** Links and forms work in Navegar (or with the bar folded) only. */\n const blocks = () => mode !== 'navigate' && !drag.hidden()\n const onClick = (event: MouseEvent) => {\n // The element being edited may be (or sit in) a link: place the caret, never navigate.\n // The overlay consumes link clicks while it is on; this covers the\n // moments it is off in Editar or Comentar (the composer is open).\n if (\n (editing?.kind === 'text' &&\n !editing.done &&\n editing.element.contains(event.target as Node)) ||\n (blocks() && (event.target as Element).closest?.('a[href],area[href]'))\n ) {\n event.preventDefault()\n }\n }\n const onSubmit = (event: Event) => {\n if (blocks()) event.preventDefault()\n }\n win.addEventListener('keydown', onKey, true)\n win.addEventListener('click', onClick, true)\n win.addEventListener('submit', onSubmit, true)\n win.addEventListener('scroll', schedule, true)\n win.addEventListener('resize', schedule)\n\n overlay.setMode(drag.hidden() ? 'off' : OVERLAY_MODE[mode])\n renderBottom()\n void load()\n\n return {\n destroy() {\n endEdit()\n destroyed = true\n closeComposer()\n auth.destroy()\n if (toastTimer !== null) win.clearTimeout(toastTimer)\n if (statusTimer !== null) win.clearTimeout(statusTimer)\n win.removeEventListener('click', onClickFirst, true)\n win.removeEventListener('pointerdown', onPressFirst, true)\n win.removeEventListener('keydown', onKey, true)\n win.removeEventListener('click', onClick, true)\n win.removeEventListener('submit', onSubmit, true)\n win.removeEventListener('scroll', schedule, true)\n win.removeEventListener('resize', schedule)\n stopObserving()\n overlay.destroy()\n drag.destroy()\n host.destroy()\n },\n }\n}\n\n/**\n * «Abrir en Zap»: the record's editor URL when Zap sent one (http or https\n * only, never another scheme), else Zap's home.\n */\nexport function zapUrl(editorUrl: string | null | undefined, zapOrigin: string): string {\n const home = new URL('/', zapOrigin)\n try {\n const url = new URL(editorUrl ?? '')\n if (url.protocol === 'https:' || url.protocol === 'http:') return url.href\n } catch {\n // No URL, or not one: Zap's home.\n }\n return home.href\n}\n\n/** Exported for specs: the overlay's own host tag, which the site tools never draw over. */\nexport { OVERLAY_HOST_TAG }\n\nconst CSS = `\n.marks { position: fixed; inset: 0; pointer-events: none; }\n.mark { position: fixed; border-radius: 4px; outline: 2px solid rgba(207,135,0,.55); }\n.bottom { position: fixed; left: 0; right: 0; bottom: 22px; display: flex; flex-direction: column;\n align-items: center; gap: 10px; pointer-events: none; padding: 0 8px; }\n.bottom > .card { position: relative; }\n.toolbar { display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 4px; white-space: nowrap;\n max-width: 100%; overflow-x: auto; }\n.segments { display: inline-flex; gap: 2px; padding: 2px; border-radius: 7px; background: ${T.subtle};\n background: oklch(0.94 0.008 250); }\n.seg { position: relative; height: 28px; padding: 0 10px; border-radius: 5px; font-size: 12px; color: ${T.muted}; }\n.seg[aria-pressed=\"true\"] { background: ${T.bg}; color: ${T.fg}; box-shadow: 0 1px 2px rgba(15,23,42,.05); }\n.seg[aria-disabled=\"true\"] { opacity: .5; cursor: default; }\n.seg[data-tip]:hover::after { content: attr(data-tip); position: absolute; bottom: 34px; left: 50%;\n transform: translateX(-50%); padding: 6px 10px; border-radius: 9px; background: ${T.dark}; color: #FFFFFF;\n font-size: 12px; white-space: nowrap; }\n.tool { height: 30px; padding: 0 9px; border-radius: 9px; color: ${T.muted}; }\n/* Hover as the suite's SegmentedControl and ghost button (SitioBarraEstados): a tool on the track\n gets foreground text over white at 60%, no shadow; the bar's own buttons, on the white card, the\n ghost hover: foreground text over slate-100. Both keep the focus ring. */\n.seg:not([aria-pressed=\"true\"]):not([aria-disabled=\"true\"]):hover { background: rgba(255,255,255,.6); color: ${T.fg}; }\n.tool:hover, .grip:hover, .account[aria-expanded=\"true\"] { background: #F1F5F9; color: ${T.fg}; }\n.seg, .tool, .grip, .pill { transition: color .15s cubic-bezier(.4,0,.2,1), background-color .15s cubic-bezier(.4,0,.2,1); }\n.seg:focus-visible, .tool:focus-visible, .grip:focus-visible { box-shadow: 0 0 0 3px ${T.focus}; }\n/* The account chip and the hide arrow (SitioBarraEstados): ghost buttons, chevrons muted until hover. */\n.account { padding: 0 4px 0 2px; gap: 3px; }\n.hide { width: 30px; padding: 0; justify-content: center; }\n.avatar.lg { width: 32px; height: 32px; }\n.menu { width: 260px; padding: 4px; border-radius: 11px; outline: none;\n box-shadow: 0 10px 15px -3px rgba(15,23,42,.1), 0 4px 6px -4px rgba(15,23,42,.08); }\n.menu-head { display: flex; align-items: center; gap: 10px; padding: 8px 8px 10px; }\n.menu-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n.menu-name { font-weight: 500; }\n.menu-mail { font-size: 12px; color: ${T.muted}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.sep { height: 1px; background: ${T.border}; margin: 4px -4px; }\n.menu-head + .sep { margin-top: 0; }\n.mi { width: 100%; height: 32px; gap: 9px; padding: 0 8px; border-radius: 7px; font-weight: 400; color: ${T.fg}; }\n.mi > .icon { color: ${T.muted}; }\n.mi:focus, .mi:focus-visible { outline: none; background: #F1F5F9; box-shadow: none; }\n.pill { height: 44px; gap: 8px; padding: 0 12px 0 11px; border-radius: 999px; }\n.pill:hover { background: #F8FAFC; }\n.pill:focus-visible { box-shadow: 0 0 0 3px ${T.focus}, 0 20px 25px -5px rgba(15,23,42,.12); }\n.pill-count { display: inline-flex; align-items: center; gap: 4px; }\n.tip { position: fixed; display: inline-flex; align-items: center; gap: 8px; padding: 5px 6px 5px 9px;\n border-radius: 7px; background: #101828; color: #FFFFFF; font-weight: 500; font-size: 12px; line-height: 18px;\n white-space: nowrap; pointer-events: none; }\n.tip:not(.on) { display: none; }\n[data-enter] { animation: eelzap-in .16s cubic-bezier(.4,0,.2,1); }\n@keyframes eelzap-in { from { opacity: 0; transform: scale(.96); } }\n@media (prefers-reduced-motion: reduce) { .seg, .tool, .grip, .pill, .switch, .knob { transition: none; } [data-enter] { animation: none; } }\n.tool.strong { color: ${T.fg}; }\n.divider { width: 1px; height: 22px; background: ${T.border}; }\n.avatar { width: 26px; height: 26px; border-radius: 7px; background: #DBEAFE; color: #1D4ED8;\n display: inline-flex; align-items: center; justify-content: center; font-weight: 600; font-size: 12px; }\n.status { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px;\n font-size: 12px; font-weight: 500; }\n.status > .icon { color: #16A34A; }\n.tray { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 14px; }\n.list { width: min(420px, calc(100vw - 16px)); padding: 13px 10px 10px 15px; max-height: 50vh; overflow: auto; }\n.list ul { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }\n.item { width: 100%; text-align: left; align-items: flex-start; gap: 10px; padding: 8px; border-radius: 9px; }\n.item:hover { background: ${T.subtle}; }\n.num { flex-shrink: 0; width: 22px; height: 22px; border-radius: 999px 999px 999px 0; background: #CF8700;\n color: #FFFFFF; font-weight: 700; font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }\n.item-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n.who { font-weight: 600; font-size: 12px; }\n.flag { font-size: 11px; color: ${T.goldText}; }\n.what { font-weight: 400; color: ${T.muted}; overflow-wrap: anywhere; }\n.toast, .refused { width: min(340px, calc(100vw - 16px)); display: flex; gap: 11px; padding: 14px 12px 14px 16px;\n align-self: flex-end; margin-right: 16px; }\n.refused { align-self: center; margin-right: 0; width: min(420px, calc(100vw - 16px)); align-items: flex-start; }\n.toast > .icon { color: #16A34A; }\n.refused > .icon, .toast-error > .icon { color: ${T.danger}; }\n.paused > .icon, .info > .icon { color: ${T.muted}; }\n.editor { min-width: max-content; }\n.editor, .info { position: fixed; padding: 8px; border-radius: 7px;\n box-shadow: 0 4px 6px -1px rgba(15,23,42,.08), 0 2px 4px -2px rgba(15,23,42,.06); }\n.info { display: flex; gap: 10px; padding: 12px 14px; }\n.info > .icon { margin-top: 1px; }\n.info .title { font-weight: 500; }\n.info .muted { font-size: 12px; }\n.actions.start { justify-content: flex-start; margin-top: 10px; gap: 6px; }\n.actions.start .btn { height: 28px; gap: 7px; font-size: 12px; }\n.btn-ghost { border: 1px solid transparent; }\n.btn-ghost:hover { background: ${T.subtle}; }\n.keys { display: flex; align-items: center; gap: 5px; margin: 8px 2px 0; font-size: 12px; color: ${T.muted}; white-space: nowrap; }\n.editor input.value { height: 34px; border-radius: 8px; }\n.with-unit { display: flex; align-items: center; gap: 8px; }\n.options { display: flex; flex-direction: column; max-height: 260px; overflow: auto; }\n.option { width: 100%; height: 32px; gap: 8px; padding: 0 8px; border-radius: 6px; font-weight: 400; text-align: left; }\n.option:hover, .option:focus-visible { background: #F1F5F9; box-shadow: none; }\n.option-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n.switch-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 2px 2px 0; }\n.switch-row .title { font-weight: 500; }\n.switch { position: relative; width: 32px; height: 18px; border-radius: 999px; background: #CBD5E1; transition: background .15s; }\n.switch[aria-checked=\"true\"] { background: ${T.primary}; }\n.knob { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 999px; background: ${T.bg};\n box-shadow: 0 1px 2px rgba(0,0,0,.15); transition: left .15s; }\n.switch[aria-checked=\"true\"] .knob { left: 16px; }\n.mark-chip { position: absolute; right: -5px; top: -27px; display: inline-flex; align-items: center; height: 20px;\n padding: 0 7px; border-radius: 6px; background: ${T.gold}; color: #FFFFFF; font: 600 12px Poppins, ui-sans-serif, system-ui, sans-serif;\n white-space: nowrap; }\n.toast-text { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }\n.title { font-weight: 600; }\n.head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.popover { border-radius: 13px; }\n.popover > .head { padding: 13px 10px 0 15px; }\n.content { display: flex; flex-direction: column; gap: 11px; padding: 10px 15px 15px; }\n.extra { display: flex; flex-direction: column; gap: 8px; }\n.check { gap: 8px; font-size: 13px; align-self: flex-start; }\n.check .box { width: 16px; height: 16px; border-radius: 4px; border: 1px solid #90A1B9; background: ${T.bg}; }\n.check[aria-checked=\"true\"] .box { background: ${T.primary}; border-color: ${T.primaryBorder};\n box-shadow: inset 0 0 0 3px ${T.bg}; }\n.propose { align-self: flex-start; height: 30px; }\n.proposal { display: flex; flex-direction: column; gap: 6px; padding: 10px; border-radius: 12px; background: ${T.goldTint}; }\n.chip { display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px 0 6px; border-radius: 7px;\n background: ${T.goldTint}; color: ${T.goldText}; font: 400 12px Poppins, ui-sans-serif, system-ui, sans-serif;\n white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }\n.before { overflow-wrap: anywhere; }\n.strong-text { color: ${T.fg}; }\n.small { font-size: 12px; }\n.composer, .value { width: 100%; font: 400 13px/22px Poppins, ui-sans-serif, system-ui, sans-serif; color: ${T.fg};\n border: 1px solid ${T.border}; border-radius: 12px; padding: 8px 12px; background: ${T.bg}; resize: vertical; }\ninput.value { height: 36px; border-radius: 9px; }\n.composer:focus, .value:focus { border-color: #90A1B9; box-shadow: 0 0 0 3px ${T.focus}; outline: none; }\n.error:empty { display: none; }\n.actions { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }\n.foot { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; margin: 2px -15px -15px;\n padding: 11px 15px; border-top: 1px solid ${T.border}; }\n.foot .btn { height: 30px; gap: 7px; }\n.foot .btn-outline { padding: 0 14px; }\n`\n"],"mappings":"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","names":["storage","write","call","key","reveal","onClick","stored","unit","list"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@8ux-co/eelzap",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "The Eel Zap client: typed content delivery and writes, stega-aware field helpers, Next.js and React preview helpers, and the on-demand preview overlay.",
5
5
  "license": "MIT",
6
6
  "repository": {