@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.
- package/CHANGELOG.md +17 -1
- package/dist/{chunk-7ZPXZZUT.js → chunk-4ET7VBJA.js} +60 -6
- package/dist/chunk-4ET7VBJA.js.map +1 -0
- package/dist/{chunk-7CXQK2PR.js → chunk-T6S3S5RH.js} +2 -2
- package/dist/{chunk-7CXQK2PR.js.map → chunk-T6S3S5RH.js.map} +1 -1
- package/dist/preview.js +6 -3
- package/dist/preview.js.map +1 -1
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/{signin-QT7YANBN.js → signin-XOGBCGBL.js} +4 -8
- package/dist/signin-XOGBCGBL.js.map +1 -0
- package/dist/{suggest-JZ63L3WP.js → suggest-KLS6B7AM.js} +467 -75
- package/dist/suggest-KLS6B7AM.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-7ZPXZZUT.js.map +0 -1
- package/dist/signin-QT7YANBN.js.map +0 -1
- package/dist/suggest-JZ63L3WP.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preview/site/signin.ts"],"sourcesContent":["import {\n SIGNIN_CHANNEL,\n type CallbackParams,\n type ChunkHandle,\n type SiteContext,\n type StartOptions,\n} from './config'\nimport { SIGNIN_MESSAGES } from './messages'\nimport {\n authorizeUrl,\n challengeFor,\n checkCallback,\n createState,\n createVerifier,\n exchangeCode,\n returnPathOf,\n savePending,\n takePending,\n type PendingSignIn,\n} from './oauth'\nimport { writeToken } from './token'\nimport { el, icon, kbd, mountHost, TOKENS as T } from './ui'\n\n/**\n * The `signin` chunk (zap-cms-v2 §3.4 steps 2 to 5, ADR 041; boards\n * SitioLanzador, SitioEntrar and SitioRenovacion): loaded only after the\n * opt-in trigger.\n *\n * The launcher «Editar o comentar», with the Shift Z hint above it, opens a\n * panel with «Entrar con Eel». All three sit at the bottom centre, the zone\n * the toolbar takes after sign-in (SitioBarra): sites keep the corners for\n * their own floating buttons (a WhatsApp button, a chat bubble). Signing in opens a popup on Nest's consent\n * screen (or, when the person consented to this site before and is signed in\n * to Eel, a popup Nest answers at once and closes, ADR 041 amendment\n * 2026-10-05); the popup lands back on\n * `{origin}/`, where the core hands the code over `BroadcastChannel('eel-zap')`\n * and closes it. This tab, which alone holds the PKCE verifier and the state,\n * checks both and the issuer, exchanges the code and opens `suggest`.\n *\n * A blocked popup turns into a full-page redirect: the verifier and state wait\n * in `sessionStorage` (`PENDING_STORAGE_KEY`), the state carries the return\n * path, and the callback page finishes here (`options.callback`) and goes back.\n */\n\nconst POPUP_NAME = 'eelzap-signin'\nconst POPUP_FEATURES = 'popup,width=480,height=720'\n\ntype Phase = 'closed' | 'open' | 'waiting' | 'error'\n\nexport function start(ctx: SiteContext, options: StartOptions = {}): ChunkHandle {\n const { win, doc } = ctx\n const m = SIGNIN_MESSAGES[ctx.locale]\n const host = mountHost(doc, CSS)\n const layer = el(doc, 'div', { class: 'layer' })\n host.root.append(layer)\n\n const renewing = options.reason === 'expired'\n let phase: Phase = renewing ? 'open' : 'closed'\n let notice: string | null = options.reason === 'expired' ? m.expired : null\n let pending: PendingSignIn | null = null\n let destroyed = false\n\n let channel: BroadcastChannel | null = null\n try {\n channel = new BroadcastChannel(SIGNIN_CHANNEL)\n channel.onmessage = (event: MessageEvent) => onCallback(event.data)\n } catch {\n // No BroadcastChannel: the popup cannot hand back; the redirect path still works.\n }\n\n function render(): void {\n if (destroyed) return\n const expanded = phase !== 'closed'\n const launcher = el(\n doc,\n 'button',\n {\n class: 'launcher',\n attrs: { type: 'button', 'aria-expanded': String(expanded) },\n on: { click: () => setPhase(expanded ? 'closed' : 'open') },\n },\n [icon(doc, 'zap', 18), m.launcher],\n )\n layer.replaceChildren(launcher, expanded ? panel() : hint())\n }\n\n /** «Pulsa Shift Z para editar o comentar», above the closed launcher (SitioLanzador). */\n function hint(): HTMLElement | string {\n const key = ctx.shortcut\n if (!key) return ''\n return el(doc, 'span', { class: 'hint', attrs: { role: 'tooltip' } }, [\n `${m.hintBefore} `,\n kbd(doc, 'Shift', key.toUpperCase()),\n ` ${m.hintAfter}`,\n ])\n }\n\n function panel(): HTMLElement {\n const waiting = phase === 'waiting'\n return el(\n doc,\n 'div',\n {\n class: 'card panel sheet',\n attrs: { role: 'dialog', 'aria-labelledby': 'eelzap-signin-title' },\n },\n [\n el(doc, 'div', { class: 'head' }, [\n el(doc, 'h2', { attrs: { id: 'eelzap-signin-title' } }, [icon(doc, 'zap', 20), m.title]),\n el(\n doc,\n 'button',\n {\n class: 'iconbtn',\n attrs: { type: 'button', 'aria-label': m.close, title: m.close },\n on: { click: () => ctx.close() },\n },\n [icon(doc, 'x')],\n ),\n ]),\n el(doc, 'p', { class: 'muted body', text: waiting ? m.waitingHelp : m.body }),\n notice ? el(doc, 'p', { class: 'notice', attrs: { role: 'status' }, text: notice }) : null,\n el(\n doc,\n 'button',\n {\n class: 'btn-dark',\n attrs: { type: 'button', 'data-action': 'sign-in' },\n on: { click: () => void signIn() },\n },\n [icon(doc, 'eel', 18), waiting ? m.retry : m.signIn],\n ),\n waiting\n ? el(doc, 'p', { class: 'muted waiting', attrs: { role: 'status' }, text: m.waiting })\n : null,\n el(doc, 'p', { class: 'muted note' }, [\n icon(doc, 'lock', 13),\n el(doc, 'span', { text: m.note }),\n ]),\n ],\n )\n }\n\n function setPhase(next: Phase, message: string | null = null): void {\n phase = next\n notice = message\n render()\n }\n\n async function signIn(): Promise<void> {\n // A stale full-page attempt in this tab is abandoned.\n takePending(win)\n // The popup opens INSIDE the click, before any await, or the browser blocks it.\n const popup = win.open('', POPUP_NAME, POPUP_FEATURES)\n const verifier = createVerifier(win)\n try {\n const challenge = await challengeFor(win, verifier)\n if (popup) {\n const state = createState(win)\n pending = { state, verifier, mode: 'popup' }\n setPhase('waiting')\n popup.location.href = authorizeUrl(ctx, state, challenge)\n return\n }\n // Popup blocked: the whole tab goes to Nest and comes back to this path.\n const { pathname, search, hash } = win.location\n const state = createState(win, `${pathname}${search}${hash}`)\n savePending(win, { state, verifier, mode: 'redirect' })\n win.location.assign(authorizeUrl(ctx, state, challenge))\n } catch {\n popup?.close()\n setPhase('error', m.failed)\n }\n }\n\n function onCallback(data: unknown): void {\n if (!pending || !data || (data as { type?: unknown }).type !== 'eelzap:callback') return\n const callback = data as Partial<CallbackParams>\n const problem = checkCallback(callback, pending, ctx.authOrigin)\n // Another sign-in's callback (another tab of this site): not ours to judge.\n if (problem === 'state') return\n const used = pending\n pending = null\n if (problem) {\n setPhase('error', m.failed)\n return\n }\n void complete(callback.code!, used.verifier, null)\n }\n\n async function complete(code: string, verifier: string, returnPath: string | null) {\n try {\n const token = await exchangeCode(ctx, code, verifier)\n writeToken(win, token)\n if (destroyed) return\n if (returnPath && returnPath !== `${win.location.pathname}${win.location.search}`) {\n win.location.replace(returnPath)\n return\n }\n await ctx.open('suggest', renewing ? { reason: 'renewed' } : undefined)\n } catch {\n setPhase('error', m.failed)\n }\n }\n\n if (options.callback) {\n const stored = takePending(win)\n const problem =\n stored?.mode === 'redirect'\n ? checkCallback(options.callback, stored, ctx.authOrigin)\n : 'state'\n if (problem) {\n setPhase('error', m.failed)\n } else {\n render()\n void complete(options.callback.code, stored!.verifier, returnPathOf(options.callback.state))\n }\n } else {\n render()\n // «Volver a entrar»: one click already made, so the sign-in starts now.\n if (options.signIn) void signIn()\n }\n\n return {\n destroy() {\n destroyed = true\n pending = null\n channel?.close()\n host.destroy()\n },\n }\n}\n\nconst CSS = `\n.launcher { pointer-events: auto; position: fixed; left: 50%; transform: translateX(-50%); bottom: 24px; height: 42px; gap: 8px;\n padding: 0 16px 0 12px; border: 1px solid ${T.border}; border-radius: 999px; background: ${T.bg}; color: ${T.fg};\n box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 4px 6px -4px rgba(15,23,42,.08); }\n.hint { pointer-events: none; position: fixed; left: 50%; transform: translateX(-50%); bottom: 76px; display: flex; align-items: center; gap: 4px;\n padding: 6px 10px; border-radius: 9px; background: ${T.dark}; color: #FFFFFF; font-size: 12px; white-space: nowrap; }\n.launcher[aria-expanded=\"true\"] { box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 0 0 3px ${T.focus}; }\n.panel { left: calc(50% - 160px); bottom: 78px; width: 320px; padding: 16px; }\n.head { display: flex; align-items: center; justify-content: space-between; }\n.body { margin: 8px 0 14px; }\n.notice { margin: 0 0 12px; padding: 8px 10px; border-radius: 9px; background: ${T.goldTint}; color: ${T.goldText}; font-size: 12px; }\n.waiting { margin-top: 8px; font-size: 12px; text-align: center; }\n.note { margin-top: 10px; display: flex; align-items: flex-start; gap: 6px; font-size: 12px; }\n.note .icon { margin-top: 2px; }\n`\n"],"mappings":"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","names":["state"]}
|