@docentjs/dom 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["createMemoryStorage","TourController","Docent"],"sources":["../src/content.ts","../src/occlusion.ts","../src/position.ts","../src/overlay.ts","../src/popover.ts","../src/styles.ts","../src/target.ts","../src/theme.ts","../src/renderer.ts","../src/storage.ts","../src/create.ts","../src/environment.ts","../src/docent.ts"],"sourcesContent":["/**\n * Turns step text into DOM nodes without ever using innerHTML. Supports a\n * small, safe inline Markdown subset: **bold**, *italic*, `code`, [links](url),\n * paragraphs separated by blank lines and line breaks on single newlines.\n */\n\nimport type { Media } from '@docentjs/core'\n\nconst SAFE_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:'])\n\nexport function isSafeUrl(url: string): boolean {\n const match = /^([a-z][a-z0-9+.-]*):/i.exec(url.trim())\n if (!match) return true // relative\n return SAFE_SCHEMES.has(`${match[1]?.toLowerCase()}:`)\n}\n\nconst INLINE = /(\\*\\*(.+?)\\*\\*)|(\\*(.+?)\\*)|(`(.+?)`)|(\\[(.+?)\\]\\(((?:[^()\\s]|\\([^()]*\\))+)\\))/g\n\nfunction appendInline(doc: Document, parent: Node, text: string): void {\n let last = 0\n for (const m of text.matchAll(INLINE)) {\n const index = m.index ?? 0\n if (index > last) parent.appendChild(doc.createTextNode(text.slice(last, index)))\n if (m[2] !== undefined) {\n const el = doc.createElement('strong')\n appendInline(doc, el, m[2])\n parent.appendChild(el)\n } else if (m[4] !== undefined) {\n const el = doc.createElement('em')\n appendInline(doc, el, m[4])\n parent.appendChild(el)\n } else if (m[6] !== undefined) {\n const el = doc.createElement('code')\n el.textContent = m[6]\n parent.appendChild(el)\n } else if (m[8] !== undefined && m[9] !== undefined) {\n if (isSafeUrl(m[9])) {\n const a = doc.createElement('a')\n a.href = m[9]\n a.target = '_blank'\n a.rel = 'noopener noreferrer'\n appendInline(doc, a, m[8])\n parent.appendChild(a)\n } else {\n parent.appendChild(doc.createTextNode(m[8]))\n }\n }\n last = index + m[0].length\n }\n if (last < text.length) parent.appendChild(doc.createTextNode(text.slice(last)))\n}\n\nfunction appendLines(doc: Document, parent: Node, text: string, inline: boolean): void {\n const lines = text.split('\\n')\n lines.forEach((line, i) => {\n if (i > 0) parent.appendChild(doc.createElement('br'))\n if (inline) appendInline(doc, parent, line)\n else parent.appendChild(doc.createTextNode(line))\n })\n}\n\nexport function renderBody(\n doc: Document,\n body: string,\n format: 'text' | 'markdown' = 'text',\n): DocumentFragment {\n const frag = doc.createDocumentFragment()\n for (const para of body.split(/\\n{2,}/)) {\n if (!para.trim()) continue\n const p = doc.createElement('p')\n appendLines(doc, p, para, format === 'markdown')\n frag.appendChild(p)\n }\n return frag\n}\n\nexport function renderMedia(doc: Document, media: Media): HTMLElement | null {\n if (!isSafeUrl(media.src)) return null\n if (media.type === 'image') {\n const img = doc.createElement('img')\n img.src = media.src\n img.alt = media.alt ?? ''\n img.setAttribute('loading', 'lazy')\n return img\n }\n const video = doc.createElement('video')\n video.src = media.src\n video.controls = true\n video.playsInline = true\n if (media.alt) video.setAttribute('aria-label', media.alt)\n return video\n}\n","/**\n * Detects fixed or sticky elements (headers, footers, banners) covering a\n * target after it was scrolled into view, and scrolls the page so the\n * target is fully uncovered.\n */\n\nimport type { Viewport } from './position'\n\nexport interface Occluder {\n el: Element\n rect: DOMRect\n /** Which edge of the target it covers. */\n edge: 'top' | 'bottom'\n}\n\nfunction isPinned(el: Element): boolean {\n const view = el.ownerDocument.defaultView\n if (!view) return false\n const position = view.getComputedStyle(el).position\n return position === 'fixed' || position === 'sticky'\n}\n\n/** Nearest pinned ancestor (inclusive), or null. */\nfunction pinnedAncestor(el: Element | null): Element | null {\n let cur: Element | null = el\n while (cur && cur !== cur.ownerDocument.documentElement) {\n if (isPinned(cur)) return cur\n cur = cur.parentElement\n }\n return null\n}\n\n/**\n * Find a pinned element covering the target's top or bottom edge.\n * `ignore` is our own host, which sits above everything.\n */\nexport function findOccluder(\n target: Element,\n ignore: Element | null,\n viewport: Viewport,\n): Occluder | null {\n const doc = target.ownerDocument\n const r = target.getBoundingClientRect()\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n const x = Math.min(Math.max(r.left + r.width / 2, vx + 1), vx + viewport.width - 1)\n const probes: Array<{ y: number; edge: 'top' | 'bottom' }> = [\n { y: r.top + 1, edge: 'top' },\n { y: r.bottom - 1, edge: 'bottom' },\n ]\n for (const { y, edge } of probes) {\n if (y < vy || y > vy + viewport.height) continue\n const stack = doc.elementsFromPoint(x, y).filter((el) => el !== ignore)\n const top = stack[0]\n if (!top || top === target || target.contains(top) || top.contains(target)) continue\n const pinned = pinnedAncestor(top)\n if (!pinned || pinned.contains(target)) continue\n return { el: pinned, rect: pinned.getBoundingClientRect(), edge }\n }\n return null\n}\n\n/**\n * Scroll so nothing pinned covers the target. Returns true if it scrolled.\n * Runs at most twice to handle a header and a footer together.\n */\nexport function uncover(\n target: Element,\n ignore: Element | null,\n viewport: Viewport,\n margin = 8,\n): boolean {\n const win = target.ownerDocument.defaultView\n if (!win || typeof target.ownerDocument.elementsFromPoint !== 'function') return false\n let scrolled = false\n for (let i = 0; i < 2; i++) {\n const occluder = findOccluder(target, ignore, viewport)\n if (!occluder) break\n const r = target.getBoundingClientRect()\n const delta =\n occluder.edge === 'top'\n ? -(occluder.rect.bottom - r.top + margin)\n : r.bottom - occluder.rect.top + margin\n win.scrollBy({ top: delta, behavior: 'auto' })\n scrolled = true\n }\n return scrolled\n}\n","/**\n * Pure popover positioning: pick a side, align, keep it on screen, and place\n * the arrow. No DOM access, so it is unit-tested without a browser.\n */\n\nimport type { Alignment, Placement, Side } from '@docentjs/core'\n\nexport interface Rect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface Size {\n width: number\n height: number\n}\n\n/**\n * The visible area, in the same coordinate space as the anchor. `x`/`y` are\n * the visual viewport's offset within the layout viewport (non-zero when the\n * page is pinch-zoomed or overflows horizontally on mobile).\n */\nexport interface Viewport extends Size {\n x?: number\n y?: number\n}\n\nexport interface PositionInput {\n /** The spotlighted area, in viewport coordinates. */\n anchor: Rect\n floating: Size\n viewport: Viewport\n placement: Placement\n /** Distance between anchor and popover. */\n gap?: number\n /** Minimum distance from the viewport edges. */\n edgePadding?: number\n /** Arrow size; keeps the arrow clear of the popover corners. */\n arrowSize?: number\n}\n\nexport interface PositionResult {\n x: number\n y: number\n side: Side\n align: Alignment\n /** Arrow offset along the popover's cross axis, from its top-left corner. */\n arrow: number\n}\n\nconst OPPOSITE: Record<Side, Side> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' }\n\nexport function parsePlacement(placement: Placement): { side: Side | 'auto'; align: Alignment } {\n if (placement === 'auto') return { side: 'auto', align: 'center' }\n const [side, align] = placement.split('-') as [Side, Alignment | undefined]\n return { side, align: align ?? 'center' }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n\nfunction isVertical(side: Side): boolean {\n return side === 'top' || side === 'bottom'\n}\n\n/** Free space between the anchor and the viewport edge on each side. */\nexport function availableSpace(anchor: Rect, viewport: Viewport): Record<Side, number> {\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n return {\n top: anchor.y - vy,\n bottom: vy + viewport.height - (anchor.y + anchor.height),\n left: anchor.x - vx,\n right: vx + viewport.width - (anchor.x + anchor.width),\n }\n}\n\nfunction candidates(side: Side | 'auto', space: Record<Side, number>): Side[] {\n if (side === 'auto') {\n return (Object.keys(space) as Side[]).sort((a, b) => space[b] - space[a])\n }\n const perpendicular: Side[] = isVertical(side) ? ['right', 'left'] : ['bottom', 'top']\n return [side, OPPOSITE[side], ...perpendicular.sort((a, b) => space[b] - space[a])]\n}\n\nexport function computePosition(input: PositionInput): PositionResult {\n const { anchor, floating, viewport } = input\n const gap = input.gap ?? 12\n const edge = input.edgePadding ?? 8\n const arrowSize = input.arrowSize ?? 8\n const { side: preferred, align } = parsePlacement(input.placement)\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n\n const space = availableSpace(anchor, viewport)\n const order = candidates(preferred, space)\n const needed = (s: Side) => (isVertical(s) ? floating.height : floating.width) + gap + edge\n const side = order.find((s) => space[s] >= needed(s)) ?? (order[0] as Side)\n\n // Main axis\n let x = 0\n let y = 0\n if (side === 'top') y = anchor.y - gap - floating.height\n if (side === 'bottom') y = anchor.y + anchor.height + gap\n if (side === 'left') x = anchor.x - gap - floating.width\n if (side === 'right') x = anchor.x + anchor.width + gap\n\n // Cross axis\n if (isVertical(side)) {\n if (align === 'start') x = anchor.x\n else if (align === 'end') x = anchor.x + anchor.width - floating.width\n else x = anchor.x + anchor.width / 2 - floating.width / 2\n x = clamp(x, vx + edge, Math.max(vx + edge, vx + viewport.width - edge - floating.width))\n } else {\n if (align === 'start') y = anchor.y\n else if (align === 'end') y = anchor.y + anchor.height - floating.height\n else y = anchor.y + anchor.height / 2 - floating.height / 2\n y = clamp(y, vy + edge, Math.max(vy + edge, vy + viewport.height - edge - floating.height))\n }\n\n // Arrow points at the anchor centre, kept away from the popover corners.\n const margin = arrowSize * 2\n const arrow = isVertical(side)\n ? clamp(anchor.x + anchor.width / 2 - x, margin, floating.width - margin)\n : clamp(anchor.y + anchor.height / 2 - y, margin, floating.height - margin)\n\n return { x: Math.round(x), y: Math.round(y), side, align, arrow: Math.round(arrow) }\n}\n\n/** Centre a popover in the viewport, for steps without a target. */\nexport function centerPosition(floating: Size, viewport: Viewport): { x: number; y: number } {\n return {\n x: Math.round((viewport.x ?? 0) + Math.max(0, (viewport.width - floating.width) / 2)),\n y: Math.round((viewport.y ?? 0) + Math.max(0, (viewport.height - floating.height) / 2)),\n }\n}\n\n/** Grow a rect on every side. */\nexport function inflate(rect: Rect, by: number): Rect {\n return {\n x: rect.x - by,\n y: rect.y - by,\n width: rect.width + by * 2,\n height: rect.height + by * 2,\n }\n}\n\n/**\n * The part of a rect that is on screen. Positioning against this keeps the\n * popover and arrow near the visible portion of oversized targets.\n */\nexport function clipToViewport(rect: Rect, viewport: Viewport): Rect {\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n const x1 = Math.max(vx, rect.x)\n const y1 = Math.max(vy, rect.y)\n const x2 = Math.min(vx + viewport.width, rect.x + rect.width)\n const y2 = Math.min(vy + viewport.height, rect.y + rect.height)\n if (x2 <= x1 || y2 <= y1) return rect\n return { x: x1, y: y1, width: x2 - x1, height: y2 - y1 }\n}\n","/**\n * Full-viewport backdrop with a rounded cutout. The cutout is a `clip-path`\n * so pointer events pass through the hole to the page for free; a separate\n * blocker element covers it when the step forbids interaction.\n */\n\nimport { inflate, type Rect, type Size } from './position'\n\nexport function holePath(viewport: Size, hole: Rect, radius: number): string {\n const r = Math.max(0, Math.min(radius, hole.width / 2, hole.height / 2))\n const { x, y, width: w, height: h } = hole\n const outer = `M0 0H${viewport.width}V${viewport.height}H0Z`\n const inner =\n `M${x + r} ${y}H${x + w - r}A${r} ${r} 0 0 1 ${x + w} ${y + r}V${y + h - r}` +\n `A${r} ${r} 0 0 1 ${x + w - r} ${y + h}H${x + r}A${r} ${r} 0 0 1 ${x} ${y + h - r}` +\n `V${y + r}A${r} ${r} 0 0 1 ${x + r} ${y}Z`\n return `path(evenodd, \"${outer}${inner}\")`\n}\n\nexport interface OverlayUpdate {\n /** Target rect in viewport coordinates, or `null` for a modal step. */\n target: Rect | null\n padding: number\n radius: number\n}\n\nexport class Overlay {\n readonly el: HTMLDivElement\n readonly blocker: HTMLDivElement\n private lastHole: Rect | null = null\n\n constructor(doc: Document) {\n this.el = doc.createElement('div')\n this.el.setAttribute('part', 'overlay')\n this.el.className = 'overlay'\n this.blocker = doc.createElement('div')\n this.blocker.className = 'blocker'\n this.blocker.hidden = true\n }\n\n /** Current hole, padded, in viewport coordinates. */\n get hole(): Rect | null {\n return this.lastHole\n }\n\n update(viewport: Size, { target, padding, radius }: OverlayUpdate, block: boolean): void {\n if (target) {\n this.lastHole = inflate(target, padding)\n } else {\n // Collapse to a point so the path keeps the same structure and can animate.\n const c = this.lastHole\n const cx = c ? c.x + c.width / 2 : viewport.width / 2\n const cy = c ? c.y + c.height / 2 : viewport.height / 2\n this.lastHole = null\n this.el.style.clipPath = holePath(viewport, { x: cx, y: cy, width: 0, height: 0 }, 0)\n this.blocker.hidden = true\n return\n }\n const hole = this.lastHole\n this.el.style.clipPath = holePath(viewport, hole, radius)\n this.blocker.hidden = !block\n if (block) {\n this.blocker.style.transform = `translate(${hole.x}px, ${hole.y}px)`\n this.blocker.style.width = `${hole.width}px`\n this.blocker.style.height = `${hole.height}px`\n }\n }\n}\n","/**\n * Builds the popover DOM for a step. Every region is wrapped in a named\n * `<slot>` whose fallback is the default UI, so custom content projected\n * from the light DOM replaces it without touching the rest.\n */\n\nimport type { Labels, RenderContext } from '@docentjs/core'\nimport { renderBody, renderMedia } from './content'\nimport type { PopoverSlots, SlotName } from './theme'\n\nexport const DEFAULT_LABELS: Required<Labels> = {\n next: 'Next',\n back: 'Back',\n skip: 'Skip',\n done: 'Done',\n close: 'Close',\n progress: '{current} of {total}',\n}\n\nexport interface PopoverParts {\n el: HTMLDivElement\n arrow: HTMLDivElement\n /** Element to focus when the step opens. */\n initialFocus: HTMLElement\n /** Light-DOM nodes to append to the shadow host so they project into slots. */\n slotted: Element[]\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className: string,\n part: string,\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag)\n el.className = className\n el.setAttribute('part', part)\n return el\n}\n\nfunction slot(doc: Document, name: SlotName, fallback?: Node): HTMLSlotElement {\n const s = doc.createElement('slot')\n s.name = name\n if (fallback) s.appendChild(fallback)\n return s\n}\n\nexport function formatProgress(template: string, current: number, total: number): string {\n return template.replace('{current}', String(current)).replace('{total}', String(total))\n}\n\n/**\n * Resolve slot overrides into light-DOM elements carrying `slot=\"<name>\"`.\n * A `null` result projects an empty element, which suppresses the fallback.\n */\nexport function resolveSlots(doc: Document, slots: PopoverSlots, ctx: RenderContext): Element[] {\n const out: Element[] = []\n for (const [name, render] of Object.entries(slots) as Array<[SlotName, PopoverSlots[SlotName]]>) {\n const content = render?.(ctx, doc)\n if (content === undefined) continue\n let el: Element\n if (content === null) el = doc.createElement('span')\n else if (typeof content === 'string') {\n el = doc.createElement('span')\n el.textContent = content\n } else if (content instanceof Element) el = content\n else {\n el = doc.createElement('div')\n el.appendChild(content)\n }\n el.setAttribute('slot', name)\n out.push(el)\n }\n return out\n}\n\nexport function buildPopover(\n doc: Document,\n ctx: RenderContext,\n labels: Labels = {},\n slots: PopoverSlots = {},\n): PopoverParts {\n const { step, tour, actions } = ctx\n const options = tour.options ?? {}\n const text: Required<Labels> = { ...DEFAULT_LABELS, ...options.labels, ...labels }\n const buttons = step.buttons ?? {}\n const id = `docent-${tour.id}-${step.id}`\n\n const el = h(doc, 'div', 'popover', 'popover')\n el.setAttribute('role', 'dialog')\n el.tabIndex = -1\n\n const arrow = h(doc, 'div', 'arrow', 'arrow')\n el.appendChild(arrow)\n\n // Header: title + close\n const header = h(doc, 'div', 'header', 'header')\n let titleNode: Node | undefined\n if (step.title) {\n const title = h(doc, 'h2', 'title', 'title')\n title.id = `${id}-title`\n title.textContent = step.title\n titleNode = title\n el.setAttribute('aria-labelledby', title.id)\n }\n header.appendChild(slot(doc, 'title', titleNode))\n let closeNode: Node | undefined\n if (options.allowClose !== false && buttons.close !== false) {\n const close = h(doc, 'button', 'close', 'close')\n close.type = 'button'\n close.setAttribute('aria-label', text.close)\n close.textContent = '×'\n close.addEventListener('click', () => actions.skip())\n closeNode = close\n }\n header.appendChild(slot(doc, 'close', closeNode))\n el.appendChild(slot(doc, 'header', header))\n\n // Body\n let bodyNode: Node | undefined\n if (step.body) {\n const body = h(doc, 'div', 'body', 'body')\n body.id = `${id}-body`\n body.appendChild(renderBody(doc, step.body, step.format))\n bodyNode = body\n el.setAttribute('aria-describedby', body.id)\n }\n el.appendChild(slot(doc, 'body', bodyNode))\n\n // Media\n let mediaNode: Node | undefined\n if (step.media) {\n const media = renderMedia(doc, step.media)\n if (media) {\n const wrap = h(doc, 'div', 'media', 'media')\n wrap.appendChild(media)\n mediaNode = wrap\n }\n }\n el.appendChild(slot(doc, 'media', mediaNode))\n\n // Footer: progress + buttons\n const footer = h(doc, 'div', 'footer', 'footer')\n const progress = h(doc, 'div', 'progress', 'progress')\n if (options.showProgress !== false) {\n progress.textContent = formatProgress(text.progress, ctx.progress.current, ctx.progress.total)\n }\n footer.appendChild(slot(doc, 'progress', progress))\n\n const group = h(doc, 'div', 'buttons', 'buttons')\n let initialFocus: HTMLElement = el\n const button = (label: string, part: string, primary: boolean, onClick: () => void) => {\n const b = h(doc, 'button', primary ? 'button primary' : 'button', `button ${part}`)\n b.type = 'button'\n b.textContent = label\n b.addEventListener('click', onClick)\n group.appendChild(b)\n return b\n }\n if (buttons.back !== false && ctx.canGoBack) button(text.back, 'button-back', false, actions.back)\n if (buttons.skip !== false && !ctx.isLast) button(text.skip, 'button-skip', false, actions.skip)\n if (buttons.next !== false) {\n initialFocus = button(ctx.isLast ? text.done : text.next, 'button-next', true, actions.next)\n }\n footer.appendChild(slot(doc, 'buttons', group))\n el.appendChild(slot(doc, 'footer', footer))\n\n const slotted = resolveSlots(doc, slots, ctx)\n if (\n slotted.some((s) => s.getAttribute('slot') === 'buttons' || s.getAttribute('slot') === 'footer')\n ) {\n initialFocus = el\n }\n return { el, arrow, initialFocus, slotted }\n}\n\n/** Wrapper used in headless mode: a positioned shell that projects the app's own popover. */\nexport function buildHeadlessShell(doc: Document): { el: HTMLDivElement; arrow: HTMLDivElement } {\n const el = h(doc, 'div', 'popover headless', 'popover')\n const arrow = h(doc, 'div', 'arrow', 'arrow')\n arrow.hidden = true\n el.appendChild(arrow)\n const s = doc.createElement('slot')\n s.name = 'popover'\n el.appendChild(s)\n return { el, arrow }\n}\n","/** Styles injected into the shadow root. Theme through the custom properties. */\nexport const STYLES = `\n:host {\n --docent-font: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n --docent-bg: #ffffff;\n --docent-fg: #111827;\n --docent-muted: #6b7280;\n --docent-accent: #2563eb;\n --docent-accent-fg: #ffffff;\n --docent-radius: 12px;\n --docent-shadow: 0 10px 30px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);\n --docent-width: 320px;\n --docent-overlay: #000;\n --docent-overlay-opacity: 0.55;\n --docent-duration: 220ms;\n /* Fast start, gentle stop: movement begins the moment you click. */\n --docent-easing: cubic-bezier(0.2, 0.8, 0.2, 1);\n position: fixed;\n inset: 0;\n z-index: var(--docent-z, 2147483000);\n pointer-events: none;\n font: 14px/1.5 var(--docent-font);\n color: var(--docent-fg);\n}\n@media (prefers-color-scheme: dark) {\n :host {\n --docent-bg: #1f2937;\n --docent-fg: #f9fafb;\n --docent-muted: #9ca3af;\n --docent-accent: #60a5fa;\n --docent-accent-fg: #0b1220;\n }\n}\n* { box-sizing: border-box; }\n.overlay {\n position: absolute;\n inset: 0;\n background: var(--docent-overlay);\n opacity: var(--docent-overlay-opacity);\n pointer-events: auto;\n transition: clip-path var(--docent-duration) var(--docent-easing);\n}\n.blocker {\n position: absolute;\n left: 0;\n top: 0;\n pointer-events: auto;\n}\n.popover {\n position: absolute;\n left: 0;\n top: 0;\n width: var(--docent-width);\n max-width: calc(100vw - 32px);\n background: var(--docent-bg);\n border-radius: var(--docent-radius);\n box-shadow: var(--docent-shadow);\n padding: 16px;\n pointer-events: auto;\n outline: none;\n transition: transform var(--docent-duration) var(--docent-easing), opacity var(--docent-duration) var(--docent-easing);\n}\n.popover[data-entering] { opacity: 0; transition: none; }\n/* Between steps the popover slides; only its content cross-fades, briefly. */\n.popover[data-moving] > * { animation: docent-swap 160ms ease-out; }\n@keyframes docent-swap { from { opacity: 0; } to { opacity: 1; } }\n.popover.headless {\n width: auto;\n max-width: none;\n padding: 0;\n background: none;\n box-shadow: none;\n border-radius: 0;\n}\n.arrow {\n position: absolute;\n width: 12px;\n height: 12px;\n background: var(--docent-bg);\n transform: rotate(45deg);\n}\n.popover[data-side=\"top\"] .arrow { bottom: -6px; }\n.popover[data-side=\"bottom\"] .arrow { top: -6px; }\n.popover[data-side=\"left\"] .arrow { right: -6px; }\n.popover[data-side=\"right\"] .arrow { left: -6px; }\n.popover[data-side=\"center\"] .arrow, .popover[data-side=\"sheet\"] .arrow { display: none; }\n.popover.sheet {\n max-width: none;\n border-radius: var(--docent-radius) var(--docent-radius) 0 0;\n padding-bottom: max(16px, env(safe-area-inset-bottom));\n}\n.header { display: flex; align-items: flex-start; gap: 8px; }\n.title { flex: 1; margin: 0; font-size: 16px; font-weight: 600; }\n.close {\n appearance: none;\n border: 0;\n background: transparent;\n color: var(--docent-muted);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n padding: 2px 4px;\n margin: -4px -6px 0 0;\n border-radius: 6px;\n}\n.close:hover, .close:focus-visible { color: var(--docent-fg); background: rgba(127, 127, 127, 0.15); }\n.body { margin-top: 6px; }\n.body p { margin: 0 0 8px; }\n.body p:last-child { margin-bottom: 0; }\n.body code {\n font-family: ui-monospace, monospace;\n font-size: 0.9em;\n padding: 1px 4px;\n border-radius: 4px;\n background: rgba(127, 127, 127, 0.15);\n}\n.body a { color: var(--docent-accent); }\n.media { margin: 10px 0 0; }\n.media img, .media video { display: block; max-width: 100%; border-radius: 8px; }\n.footer { display: flex; align-items: center; gap: 8px; margin-top: 14px; }\n.progress { flex: 1; color: var(--docent-muted); font-size: 12px; }\n.buttons { display: flex; gap: 8px; }\n.button {\n appearance: none;\n border: 0;\n border-radius: 8px;\n padding: 7px 12px;\n font: inherit;\n font-weight: 500;\n cursor: pointer;\n background: rgba(127, 127, 127, 0.15);\n color: var(--docent-fg);\n}\n.button.primary { background: var(--docent-accent); color: var(--docent-accent-fg); }\n.button:focus-visible, .close:focus-visible { outline: 2px solid var(--docent-accent); outline-offset: 2px; }\n@media (prefers-reduced-motion: reduce) {\n .overlay, .popover { transition: none; }\n .popover[data-moving] > * { animation: none; }\n}\n`\n","/**\n * Resolves schema targets to DOM elements. Pierces open shadow roots as a\n * fallback and can wait for elements that render later.\n */\n\nimport type { Target, TargetSpec } from '@docentjs/core'\n\nexport type QueryRoot = Document | DocumentFragment | Element\n\n/** Attribute that `{ name }` targets resolve through. */\nexport const NAME_ATTRIBUTE = 'data-docent'\n\nfunction escapeAttr(value: string): string {\n const css = (globalThis as { CSS?: { escape?: (s: string) => string } }).CSS\n return css?.escape ? css.escape(value) : value.replace(/[\"\\\\]/g, '\\\\$&')\n}\n\nexport function toSpec(target: Target): TargetSpec {\n return typeof target === 'string' ? { selectors: [target] } : target\n}\n\n/** Selectors to try, in order, for a target. */\nexport function candidateSelectors(target: Target): string[] {\n const spec = toSpec(target)\n const out: string[] = []\n if (spec.name) out.push(`[${NAME_ATTRIBUTE}=\"${escapeAttr(spec.name)}\"]`)\n if (spec.selectors) out.push(...spec.selectors)\n return out\n}\n\nfunction safeQueryAll(root: QueryRoot, selector: string): Element[] {\n try {\n return Array.from(root.querySelectorAll(selector))\n } catch {\n return []\n }\n}\n\n/** Query the root, then every open shadow root beneath it. */\nexport function queryAllDeep(root: QueryRoot, selector: string): Element[] {\n const direct = safeQueryAll(root, selector)\n if (direct.length > 0) return direct\n const out: Element[] = []\n for (const el of safeQueryAll(root, '*')) {\n if (el.shadowRoot) out.push(...queryAllDeep(el.shadowRoot, selector))\n }\n return out\n}\n\nexport function resolveTarget(target: Target, root: QueryRoot = document): Element | null {\n const spec = toSpec(target)\n let scope: QueryRoot = root\n if (spec.within) {\n const container = queryAllDeep(root, spec.within)[0]\n if (!container) return null\n scope = container\n }\n for (const selector of candidateSelectors(spec)) {\n const matches = queryAllDeep(scope, selector)\n if (matches.length > 0) return matches[spec.nth ?? 0] ?? null\n }\n return null\n}\n\n/**\n * Resolve now, or watch the DOM until the target appears, the timeout passes,\n * or the signal aborts. Resolves `null` when it never shows up.\n */\nexport function waitForTarget(\n target: Target,\n timeoutMs: number,\n signal?: AbortSignal,\n root: QueryRoot = document,\n): Promise<Element | null> {\n const now = resolveTarget(target, root)\n if (now || signal?.aborted) return Promise.resolve(now)\n\n return new Promise((resolve) => {\n let scheduled = false\n const observed =\n root.nodeType === Node.DOCUMENT_NODE ? (root as Document).documentElement : root\n const done = (el: Element | null) => {\n observer.disconnect()\n if (timer !== undefined) clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n resolve(el)\n }\n const check = () => {\n scheduled = false\n const el = resolveTarget(target, root)\n if (el) done(el)\n }\n const observer = new MutationObserver(() => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(check)\n })\n const onAbort = () => done(null)\n const timer = Number.isFinite(timeoutMs) ? setTimeout(() => done(null), timeoutMs) : undefined\n signal?.addEventListener('abort', onAbort, { once: true })\n observer.observe(observed, { childList: true, subtree: true, attributes: true })\n })\n}\n","/**\n * Theme tokens → CSS custom properties, plus the slot and template contracts\n * that let apps, framework adapters and (later) the visual builder customise\n * the popover without forking the renderer.\n */\n\nimport type { RenderContext, Theme } from '@docentjs/core'\n\n/** Token → CSS custom property (without the `--docent-` prefix). */\nexport const THEME_VARS: Record<keyof Theme, string> = {\n background: 'bg',\n foreground: 'fg',\n muted: 'muted',\n accent: 'accent',\n accentForeground: 'accent-fg',\n radius: 'radius',\n shadow: 'shadow',\n font: 'font',\n width: 'width',\n overlay: 'overlay',\n overlayOpacity: 'overlay-opacity',\n duration: 'duration',\n zIndex: 'z',\n}\n\n/** Write theme tokens as inline custom properties on an element. Clears unset ones. */\nexport function applyTheme(el: HTMLElement, theme: Theme | undefined): void {\n for (const key of Object.keys(THEME_VARS) as Array<keyof Theme>) {\n const value = theme?.[key]\n const prop = `--docent-${THEME_VARS[key]}`\n if (value === undefined) el.style.removeProperty(prop)\n else el.style.setProperty(prop, value)\n }\n}\n\nexport function mergeThemes(...themes: Array<Theme | undefined>): Theme {\n return Object.assign({}, ...themes.filter(Boolean)) as Theme\n}\n\n// ---------------------------------------------------------------------------\n// Slots\n// ---------------------------------------------------------------------------\n\n/**\n * Regions of the built-in popover that can be replaced. Custom content is\n * projected through native Shadow DOM slots, so it lives in the page's DOM\n * and keeps the page's CSS and framework behaviour.\n */\nexport type SlotName =\n | 'header'\n | 'title'\n | 'close'\n | 'body'\n | 'media'\n | 'footer'\n | 'progress'\n | 'buttons'\n\n/**\n * What a slot renderer returns:\n * - a `Node` replaces the region,\n * - a string replaces it with text,\n * - `null` removes the region,\n * - `undefined` keeps the default.\n */\nexport type SlotContent = Node | string | null | undefined\n\nexport type SlotRenderer = (ctx: RenderContext, doc: Document) => SlotContent\n\nexport type PopoverSlots = Partial<Record<SlotName, SlotRenderer>>\n\n// ---------------------------------------------------------------------------\n// Templates and headless mode\n// ---------------------------------------------------------------------------\n\n/**\n * A named bundle of theme, slots and CSS. Tours pick one by name through\n * `options.template`, which keeps the JSON builder-friendly while the code\n * that defines the template stays in the app.\n */\nexport interface PopoverTemplate {\n theme?: Theme\n slots?: PopoverSlots\n /** Extra CSS injected into the shadow root while this template is active. */\n css?: string\n}\n\n/**\n * Replace the whole popover. The renderer still draws the overlay and\n * spotlight, positions `container`, sets `data-side` and `--docent-arrow`\n * on it, and handles keyboard, focus and state. You draw everything inside.\n */\nexport interface HeadlessPopover {\n /** Render the step into `container`. Return a cleanup to run before the next step. */\n render(ctx: RenderContext, container: HTMLElement): undefined | (() => void)\n}\n","/**\n * The web renderer. Draws the overlay, spotlight and popover inside a shadow\n * root, keeps them glued to the target through scroll, resize and layout\n * changes, and wires gestures and keys back to the controller.\n *\n * Customisation layers, lowest to highest precedence:\n * renderer options → template (by name) → tour options. Slots project\n * light-DOM content into the built-in popover; headless mode replaces it.\n */\n\nimport type { Labels, RenderContext, Renderer, Step, Target, Theme } from '@docentjs/core'\nimport { uncover } from './occlusion'\nimport { Overlay } from './overlay'\nimport { buildHeadlessShell, buildPopover } from './popover'\nimport {\n centerPosition,\n clipToViewport,\n computePosition,\n type Rect,\n type Viewport,\n} from './position'\nimport { STYLES } from './styles'\nimport { resolveTarget, waitForTarget } from './target'\nimport {\n applyTheme,\n type HeadlessPopover,\n mergeThemes,\n type PopoverSlots,\n type PopoverTemplate,\n} from './theme'\n\nexport interface DomRendererOptions {\n /** Document to render into. Defaults to the global document. */\n document?: Document\n /** Override button and progress labels for every tour. */\n labels?: Labels\n /** Distance between target and popover, in px. */\n gap?: number\n /** Spotlight defaults when a tour sets none. */\n spotlight?: { padding?: number; radius?: number }\n /** Base theme tokens. Tours and templates layer on top. */\n theme?: Theme\n /** Replace regions of the built-in popover. */\n slots?: PopoverSlots\n /** Named templates that tours select with `options.template`. */\n templates?: Record<string, PopoverTemplate>\n /** Template to use when a tour names none. */\n template?: string\n /** Bring your own popover. Overlay, spotlight, positioning and keys stay. */\n headless?: HeadlessPopover\n /** Extra CSS injected into the shadow root. */\n css?: string\n /**\n * Below this viewport width the popover docks to the bottom edge as a sheet\n * instead of floating beside the target. Default 480; 0 disables.\n */\n sheetBreakpoint?: number\n /** Scroll past sticky/fixed headers and footers that cover the target. Default true. */\n avoidOcclusion?: boolean\n}\n\ntype Cleanup = () => void\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\nexport class DomRenderer implements Renderer {\n private readonly doc: Document\n private readonly options: DomRendererOptions\n private host: HTMLDivElement | undefined\n private shadow: ShadowRoot | undefined\n private overlay: Overlay | undefined\n private templateStyle: HTMLStyleElement | undefined\n private popover: HTMLDivElement | undefined\n private arrow: HTMLDivElement | undefined\n private headlessContainer: HTMLElement | undefined\n private ctx: RenderContext | undefined\n private target: Element | null = null\n private cleanups: Cleanup[] = []\n private frame: number | undefined\n private previousFocus: Element | null = null\n /** Set once per step after the sheet has scrolled the target clear. */\n private sheetAdjusted = false\n\n constructor(options: DomRendererOptions = {}) {\n this.options = options\n this.doc = options.document ?? document\n }\n\n // -------------------------------------------------------------------------\n // Renderer contract\n // -------------------------------------------------------------------------\n\n hasTarget(target: Target): boolean {\n return resolveTarget(target, this.doc) !== null\n }\n\n async waitForTarget(target: Target, timeoutMs: number, signal: AbortSignal): Promise<boolean> {\n return (await waitForTarget(target, timeoutMs, signal, this.doc)) !== null\n }\n\n currentRoute(): string {\n const { pathname, search } = this.doc.defaultView?.location ?? { pathname: '/', search: '' }\n return `${pathname}${search}`\n }\n\n show(ctx: RenderContext): void {\n const firstStep = !this.host\n const host = this.mount()\n // Where the previous step's popover sat, so the new one glides from there\n // alongside the spotlight instead of vanishing and fading back in.\n const from = this.popover?.style.transform || null\n this.teardownStep()\n this.ctx = ctx\n this.target = ctx.step.target === undefined ? null : resolveTarget(ctx.step.target, this.doc)\n\n const template = this.template(ctx)\n applyTheme(host, mergeThemes(this.options.theme, template?.theme, ctx.tour.options?.theme))\n this.setTemplateCss(template?.css)\n\n const initialFocus = this.options.headless\n ? this.buildHeadless(ctx, host, this.options.headless)\n : this.buildDefault(ctx, host, template)\n if (this.popover && from) {\n this.popover.style.transform = from\n this.popover.setAttribute('data-moving', '')\n } else {\n this.popover?.setAttribute('data-entering', '')\n }\n\n if (this.target) {\n const smooth = this.scrollIntoView(this.target, ctx.step)\n if (this.options.avoidOcclusion !== false) {\n const target = this.target\n this.afterScroll(smooth, target, () => {\n if (this.target === target && uncover(target, host, this.viewport())) this.update()\n })\n }\n }\n this.update()\n this.listen()\n this.wireAdvance(ctx.step)\n\n if (firstStep) this.previousFocus = this.doc.activeElement\n requestAnimationFrame(() => {\n this.popover?.removeAttribute('data-entering')\n initialFocus.focus({ preventScroll: true })\n })\n }\n\n hide(): void {\n this.teardownStep()\n if (this.host) {\n this.host.remove()\n this.host = undefined\n this.shadow = undefined\n this.overlay = undefined\n this.templateStyle = undefined\n }\n const prev = this.previousFocus\n this.previousFocus = null\n if (prev instanceof HTMLElement && prev.isConnected) prev.focus({ preventScroll: true })\n }\n\n // -------------------------------------------------------------------------\n // Layout\n // -------------------------------------------------------------------------\n\n /** Re-measure and re-position everything. Safe to call often. */\n update(): void {\n const ctx = this.ctx\n const overlay = this.overlay\n const popover = this.popover\n const win = this.doc.defaultView\n if (!ctx || !overlay || !popover || !win) return\n\n const viewport = this.viewport()\n const overlaySize = { width: overlay.el.offsetWidth, height: overlay.el.offsetHeight }\n const spotlight = {\n ...this.options.spotlight,\n ...ctx.tour.options?.spotlight,\n ...ctx.step.spotlight,\n }\n const padding = spotlight.padding ?? 6\n const radius = spotlight.radius ?? 6\n const external = this.headlessContainer\n const sheet = this.isSheet(viewport)\n popover.classList.toggle('sheet', sheet)\n popover.style.width = sheet ? `${viewport.width}px` : ''\n const floating = { width: popover.offsetWidth, height: popover.offsetHeight }\n\n if (sheet) {\n const rect = this.target?.isConnected ? toRect(this.target.getBoundingClientRect()) : null\n overlay.update(\n overlaySize,\n { target: rect, padding, radius },\n this.blocksInteraction(ctx.step),\n )\n const vx = viewport.x ?? 0\n const top = (viewport.y ?? 0) + viewport.height - floating.height\n popover.style.transform = `translate(${vx}px, ${top}px)`\n popover.setAttribute('data-side', 'sheet')\n external?.setAttribute('data-side', 'sheet')\n this.keepClearOfSheet(rect, top)\n return\n }\n\n if (!this.target?.isConnected) {\n overlay.update(overlaySize, { target: null, padding, radius }, false)\n const { x, y } = centerPosition(floating, viewport)\n popover.style.transform = `translate(${x}px, ${y}px)`\n popover.setAttribute('data-side', 'center')\n external?.setAttribute('data-side', 'center')\n return\n }\n\n const rect = toRect(this.target.getBoundingClientRect())\n overlay.update(overlaySize, { target: rect, padding, radius }, this.blocksInteraction(ctx.step))\n const hole = overlay.hole ?? rect\n const pos = computePosition({\n anchor: clipToViewport(hole, viewport),\n floating,\n viewport,\n placement: ctx.step.placement ?? 'auto',\n gap: this.options.gap ?? 12,\n })\n popover.style.transform = `translate(${pos.x}px, ${pos.y}px)`\n popover.setAttribute('data-side', pos.side)\n if (this.arrow) {\n const vertical = pos.side === 'top' || pos.side === 'bottom'\n this.arrow.style.left = vertical ? `${pos.arrow - 6}px` : ''\n this.arrow.style.top = vertical ? '' : `${pos.arrow - 6}px`\n }\n if (external) {\n external.setAttribute('data-side', pos.side)\n external.style.setProperty('--docent-arrow', `${pos.arrow}px`)\n }\n }\n\n /**\n * The visible area in layout-viewport coordinates. Uses the visual viewport\n * so pinch zoom, the on-screen keyboard and pages that overflow on mobile\n * (where `innerWidth` grows past the screen) all position correctly.\n */\n private viewport(): Viewport {\n const win = this.doc.defaultView\n const vv = win?.visualViewport\n if (vv) return { x: vv.offsetLeft, y: vv.offsetTop, width: vv.width, height: vv.height }\n const el = this.doc.documentElement\n return { x: 0, y: 0, width: el.clientWidth, height: el.clientHeight }\n }\n\n private isSheet(viewport: Viewport): boolean {\n const breakpoint = this.options.sheetBreakpoint ?? 480\n return breakpoint > 0 && viewport.width < breakpoint\n }\n\n /** In sheet mode, scroll once so the target is not hidden behind the sheet. */\n private keepClearOfSheet(target: Rect | null, sheetTop: number): void {\n const win = this.doc.defaultView\n if (!target || !win || this.sheetAdjusted) return\n const overlap = target.y + target.height - sheetTop\n if (overlap <= 0) return\n this.sheetAdjusted = true\n win.scrollBy({ top: overlap + 16, behavior: 'auto' })\n }\n\n /**\n * Run once a smooth scroll has settled, or right away for instant scrolls.\n * Settled means the target stopped moving for two frames' worth of samples,\n * not a fixed delay: smooth scrolls take longer on slow or busy devices.\n * `scrollend` finishes early where supported; a cap keeps it bounded.\n */\n private afterScroll(smooth: boolean, target: Element, fn: () => void): void {\n const win = this.doc.defaultView\n if (!smooth || !win) {\n fn()\n return\n }\n let done = false\n let lastTop = Number.NaN\n let stableSamples = 0\n const stop = () => {\n done = true\n win.removeEventListener('scrollend', finish)\n clearInterval(poll)\n clearTimeout(cap)\n }\n const finish = () => {\n if (done) return\n stop()\n fn()\n }\n const poll = setInterval(() => {\n const top = target.getBoundingClientRect().top\n stableSamples = Math.abs(top - lastTop) < 0.5 ? stableSamples + 1 : 0\n lastTop = top\n if (stableSamples >= 2) finish()\n }, 80)\n const cap = setTimeout(finish, 3000)\n win.addEventListener('scrollend', finish, { once: true })\n this.cleanups.push(stop)\n }\n\n // -------------------------------------------------------------------------\n // Popover construction\n // -------------------------------------------------------------------------\n\n private template(ctx: RenderContext): PopoverTemplate | undefined {\n const name = ctx.tour.options?.template ?? this.options.template\n return name === undefined ? undefined : this.options.templates?.[name]\n }\n\n private buildDefault(\n ctx: RenderContext,\n host: HTMLElement,\n template: PopoverTemplate | undefined,\n ): HTMLElement {\n const slots: PopoverSlots = { ...this.options.slots, ...template?.slots }\n const { el, arrow, initialFocus, slotted } = buildPopover(\n this.doc,\n ctx,\n this.options.labels ?? {},\n slots,\n )\n this.popover = el\n this.arrow = arrow\n for (const node of slotted) {\n host.appendChild(node)\n this.cleanups.push(() => node.remove())\n }\n this.shadow?.appendChild(el)\n return initialFocus\n }\n\n private buildHeadless(\n ctx: RenderContext,\n host: HTMLElement,\n headless: HeadlessPopover,\n ): HTMLElement {\n const { el, arrow } = buildHeadlessShell(this.doc)\n this.popover = el\n this.arrow = arrow\n this.shadow?.appendChild(el)\n\n const container = this.doc.createElement('div')\n container.setAttribute('slot', 'popover')\n container.setAttribute('data-docent-popover', '')\n container.setAttribute('role', 'dialog')\n container.tabIndex = -1\n host.appendChild(container)\n this.headlessContainer = container\n const cleanup = headless.render(ctx, container)\n this.cleanups.push(() => {\n cleanup?.()\n container.remove()\n this.headlessContainer = undefined\n })\n return container\n }\n\n private setTemplateCss(css: string | undefined): void {\n if (!this.shadow) return\n if (!css) {\n this.templateStyle?.remove()\n this.templateStyle = undefined\n return\n }\n if (!this.templateStyle) {\n this.templateStyle = this.doc.createElement('style')\n this.shadow.appendChild(this.templateStyle)\n }\n if (this.templateStyle.textContent !== css) this.templateStyle.textContent = css\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private mount(): HTMLDivElement {\n if (this.host) return this.host\n const host = this.doc.createElement('div')\n host.setAttribute('data-docent-host', '')\n const shadow = host.attachShadow({ mode: 'open' })\n const style = this.doc.createElement('style')\n style.textContent = this.options.css ? `${STYLES}\\n${this.options.css}` : STYLES\n shadow.appendChild(style)\n const overlay = new Overlay(this.doc)\n shadow.appendChild(overlay.el)\n shadow.appendChild(overlay.blocker)\n this.doc.body.appendChild(host)\n this.host = host\n this.shadow = shadow\n this.overlay = overlay\n return host\n }\n\n private teardownStep(): void {\n for (const c of this.cleanups) c()\n this.cleanups = []\n if (this.frame !== undefined) cancelAnimationFrame(this.frame)\n this.frame = undefined\n this.popover?.remove()\n this.popover = undefined\n this.arrow = undefined\n this.ctx = undefined\n this.target = null\n this.sheetAdjusted = false\n }\n\n private blocksInteraction(step: Step): boolean {\n if (step.interaction) return step.interaction === 'block'\n const advance = step.advance\n return !(typeof advance === 'object' && (advance.on === 'click' || advance.on === 'input'))\n }\n\n /** Returns true when a smooth scroll was started (callers must wait for it to settle). */\n private scrollIntoView(el: Element, step: Step): boolean {\n const scroll = { ...this.ctx?.tour.options?.scroll, ...step.scroll }\n if (scroll.enabled === false) return false\n const r = el.getBoundingClientRect()\n const v = this.viewport()\n const vx = v.x ?? 0\n const vy = v.y ?? 0\n const behavior = scroll.behavior ?? 'auto'\n if (r.height > v.height || r.width > v.width) {\n // Oversized target: it can never be fully shown, so only make sure its top is on screen.\n const topVisible = r.top >= vy && r.top < vy + v.height && r.left < vx + v.width\n if (!topVisible) el.scrollIntoView({ block: 'start', inline: 'start', behavior })\n return !topVisible && behavior === 'smooth'\n }\n const visible =\n r.top >= vy && r.left >= vx && r.bottom <= vy + v.height && r.right <= vx + v.width\n if (visible) return false\n el.scrollIntoView({ block: scroll.block ?? 'center', inline: 'nearest', behavior })\n return behavior === 'smooth'\n }\n\n private scheduleUpdate = (): void => {\n if (this.frame !== undefined) return\n this.frame = requestAnimationFrame(() => {\n this.frame = undefined\n this.update()\n })\n }\n\n private listen(): void {\n const win = this.doc.defaultView\n const ctx = this.ctx\n if (!win || !ctx) return\n const on = <K extends keyof WindowEventMap>(\n type: K,\n handler: (e: WindowEventMap[K]) => void,\n opts?: AddEventListenerOptions,\n ) => {\n win.addEventListener(type, handler, opts)\n this.cleanups.push(() => win.removeEventListener(type, handler, opts))\n }\n\n on('scroll', this.scheduleUpdate, { capture: true, passive: true })\n on('resize', this.scheduleUpdate, { passive: true })\n const vv = win.visualViewport\n if (vv) {\n vv.addEventListener('resize', this.scheduleUpdate)\n vv.addEventListener('scroll', this.scheduleUpdate)\n this.cleanups.push(() => {\n vv.removeEventListener('resize', this.scheduleUpdate)\n vv.removeEventListener('scroll', this.scheduleUpdate)\n })\n }\n if (typeof ResizeObserver !== 'undefined') {\n const ro = new ResizeObserver(this.scheduleUpdate)\n if (this.target) ro.observe(this.target)\n ro.observe(this.doc.documentElement)\n if (this.popover) ro.observe(this.popover)\n if (this.headlessContainer) ro.observe(this.headlessContainer)\n this.cleanups.push(() => ro.disconnect())\n }\n\n const options = ctx.tour.options ?? {}\n on('keydown', (e) => this.onKeydown(e, ctx), { capture: true })\n\n if (options.closeOnOverlayClick && this.overlay) {\n const overlayEl = this.overlay.el\n const handler = () => ctx.actions.skip()\n overlayEl.addEventListener('click', handler)\n this.cleanups.push(() => overlayEl.removeEventListener('click', handler))\n }\n }\n\n private onKeydown(e: KeyboardEvent, ctx: RenderContext): void {\n const options = ctx.tour.options ?? {}\n // The real origin, even inside shadow roots (where `e.target` is retargeted to the host).\n const path = typeof e.composedPath === 'function' ? e.composedPath() : []\n const origin = (path[0] ?? e.target) as Element | null\n // Elements marked `data-docent-ignore-keys` (e.g. the devtools panel) keep their keys.\n if (path.some((n) => n instanceof Element && n.hasAttribute('data-docent-ignore-keys'))) return\n if (e.key === 'Escape' && options.allowClose !== false) {\n e.preventDefault()\n ctx.actions.skip()\n return\n }\n if (e.key === 'Tab') {\n this.trapTab(e)\n return\n }\n if (options.keyboard === false) return\n const inField =\n origin instanceof HTMLElement &&\n (/^(INPUT|TEXTAREA|SELECT)$/.test(origin.tagName) || origin.isContentEditable)\n if (inField) return\n if (e.key === 'ArrowRight' && ctx.step.buttons?.next !== false) {\n e.preventDefault()\n ctx.actions.next()\n } else if (e.key === 'ArrowLeft' && ctx.canGoBack && ctx.step.buttons?.back !== false) {\n e.preventDefault()\n ctx.actions.back()\n }\n }\n\n /** Keep Tab cycling inside the popover when focus is already in it. */\n private trapTab(e: KeyboardEvent): void {\n const scope = this.headlessContainer ?? this.popover\n if (!scope) return\n const active = this.headlessContainer ? this.doc.activeElement : this.shadow?.activeElement\n const inside = active && (scope.contains(active) || this.host?.contains(active))\n if (!active || !inside) return\n // Slotted light-DOM controls are children of the host; include them in the cycle.\n const roots: ParentNode[] = this.headlessContainer\n ? [scope]\n : [scope, ...(this.host ? [this.host] : [])]\n const items = roots.flatMap((r) => Array.from(r.querySelectorAll<HTMLElement>(FOCUSABLE)))\n if (items.length === 0) return\n const first = items[0] as HTMLElement\n const last = items[items.length - 1] as HTMLElement\n if (e.shiftKey && active === first) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && active === last) {\n e.preventDefault()\n first.focus()\n }\n }\n\n private wireAdvance(step: Step): void {\n const advance = step.advance\n const ctx = this.ctx\n if (!ctx || typeof advance !== 'object') return\n if (advance.on !== 'click' && advance.on !== 'input') return\n const el = advance.target === undefined ? this.target : resolveTarget(advance.target, this.doc)\n if (!el) return\n\n if (advance.on === 'click') {\n const handler = () => ctx.actions.next()\n el.addEventListener('click', handler, { once: true })\n this.cleanups.push(() => el.removeEventListener('click', handler))\n return\n }\n\n const pattern = advance.match ? new RegExp(advance.match) : /.+/\n const handler = (e: Event) => {\n const value = (e.target as HTMLInputElement | HTMLTextAreaElement).value ?? ''\n if (pattern.test(value)) ctx.actions.next()\n }\n el.addEventListener('input', handler)\n this.cleanups.push(() => el.removeEventListener('input', handler))\n }\n}\n\nfunction toRect(r: DOMRect): Rect {\n return { x: r.left, y: r.top, width: r.width, height: r.height }\n}\n","import { createMemoryStorage, type StorageAdapter } from '@docentjs/core'\n\n/**\n * `localStorage`-backed adapter. Falls back to memory when storage is\n * unavailable (private mode, blocked cookies, SSR).\n */\nexport function createLocalStorage(storage?: Storage): StorageAdapter {\n let backing: Storage\n try {\n backing = storage ?? globalThis.localStorage\n const probe = '__docent__'\n backing.setItem(probe, '1')\n backing.removeItem(probe)\n } catch {\n return createMemoryStorage()\n }\n const guard = <T>(fn: () => T, fallback: T): T => {\n try {\n return fn()\n } catch {\n return fallback\n }\n }\n return {\n get: (key) => guard(() => backing.getItem(key), null),\n set: (key, value) => guard(() => backing.setItem(key, value), undefined),\n remove: (key) => guard(() => backing.removeItem(key), undefined),\n }\n}\n","import { type ControllerOptions, type Tour, TourController } from '@docentjs/core'\nimport { DomRenderer, type DomRendererOptions } from './renderer'\nimport { createLocalStorage } from './storage'\n\nexport interface CreateTourOptions extends Omit<ControllerOptions, 'tour' | 'renderer'> {\n renderer?: DomRendererOptions\n /** Follow browser navigation to pause and resume route-bound steps. Default true. */\n followRoutes?: boolean\n}\n\n/**\n * A controller pre-wired for the browser: DOM renderer, localStorage\n * persistence and route change tracking.\n */\nexport class DomTourController extends TourController {\n private readonly cleanups: Array<() => void> = []\n private readonly followRoutes: boolean\n\n constructor(tour: Tour, options: CreateTourOptions = {}) {\n const { renderer: rendererOptions, followRoutes, ...rest } = options\n const renderer = new DomRenderer(rendererOptions)\n super({ ...rest, tour, renderer, storage: rest.storage ?? createLocalStorage() })\n // Listeners attach on start, not here, so constructing has no side effects\n // and a destroyed controller can start again (React StrictMode).\n this.followRoutes = followRoutes !== false\n }\n\n override async start(at?: number | string): Promise<void> {\n this.listenToRoutes()\n return super.start(at)\n }\n\n override async destroy(): Promise<void> {\n for (const c of this.cleanups) c()\n this.cleanups.length = 0\n await super.destroy()\n }\n\n private listenToRoutes(): void {\n if (!this.followRoutes || this.cleanups.length > 0 || typeof window === 'undefined') return\n const onChange = () => void this.routeChanged()\n for (const type of ['popstate', 'hashchange']) {\n window.addEventListener(type, onChange)\n this.cleanups.push(() => window.removeEventListener(type, onChange))\n }\n const nav = (window as { navigation?: EventTarget }).navigation\n if (nav) {\n nav.addEventListener('navigatesuccess', onChange)\n this.cleanups.push(() => nav.removeEventListener('navigatesuccess', onChange))\n }\n }\n}\n\n/** Create a browser-ready tour. Call `.start()` or `.resume()` on the result. */\nexport function createTour(tour: Tour, options?: CreateTourOptions): DomTourController {\n return new DomTourController(tour, options)\n}\n","/**\n * Browser implementation of the manager's environment: routes from `location`\n * and navigation events, element presence from the DOM.\n */\n\nimport type { DocentEnvironment, Target } from '@docentjs/core'\nimport { resolveTarget } from './target'\n\nexport function createDomEnvironment(doc: Document = document): DocentEnvironment {\n const win = doc.defaultView\n return {\n currentRoute() {\n const loc = win?.location\n return loc ? `${loc.pathname}${loc.search}` : '/'\n },\n\n onRouteChange(listener) {\n if (!win) return () => {}\n const cleanups: Array<() => void> = []\n for (const type of ['popstate', 'hashchange'] as const) {\n win.addEventListener(type, listener)\n cleanups.push(() => win.removeEventListener(type, listener))\n }\n const nav = (win as { navigation?: EventTarget }).navigation\n if (nav) {\n nav.addEventListener('navigatesuccess', listener)\n cleanups.push(() => nav.removeEventListener('navigatesuccess', listener))\n }\n return () => {\n for (const c of cleanups) c()\n }\n },\n\n hasTarget: (target: Target) => resolveTarget(target, doc) !== null,\n\n watchTarget(target, listener) {\n let present = resolveTarget(target, doc) !== null\n if (present) listener()\n let scheduled = false\n const check = () => {\n scheduled = false\n const now = resolveTarget(target, doc) !== null\n if (now && !present) listener()\n present = now\n }\n const observer = new MutationObserver(() => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(check)\n })\n observer.observe(doc.documentElement, { childList: true, subtree: true, attributes: true })\n return () => observer.disconnect()\n },\n }\n}\n","import { Docent, type DocentOptions } from '@docentjs/core'\nimport { DomTourController } from './create'\nimport { createDomEnvironment } from './environment'\nimport type { DomRendererOptions } from './renderer'\nimport { createLocalStorage } from './storage'\n\nexport interface CreateDocentOptions\n extends Omit<DocentOptions, 'environment' | 'createController'> {\n /** Renderer options shared by every tour: theme, templates, slots, headless, labels. */\n renderer?: DomRendererOptions\n /** Document to watch and render into. Defaults to the global document. */\n document?: Document\n}\n\n/**\n * Create the tour manager for the browser. It loads your tours, watches their\n * triggers (routes, elements, events, delays), checks conditions and frequency\n * per user, and runs at most one tour at a time.\n *\n * ```ts\n * const docent = createDocent({ tours: [welcome, invoices] })\n * docent.identify(user.id, { plan: user.plan })\n * docent.track('invoice-saved')\n * ```\n */\nexport function createDocent(options: CreateDocentOptions = {}): Docent {\n const { renderer, document: doc, ...rest } = options\n const rendererOptions: DomRendererOptions = doc ? { ...renderer, document: doc } : { ...renderer }\n return new Docent({\n ...rest,\n storage: rest.storage ?? createLocalStorage(),\n environment: createDomEnvironment(doc),\n createController: (tour, shared) =>\n new DomTourController(tour, { ...shared, renderer: rendererOptions }),\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["arrowGap","isConnector","createMemoryStorage","TourController","Docent"],"sources":["../src/content.ts","../src/occlusion.ts","../src/position.ts","../src/overlay.ts","../src/popover.ts","../src/styles.ts","../src/target.ts","../src/theme.ts","../src/renderer.ts","../src/storage.ts","../src/create.ts","../src/environment.ts","../src/docent.ts"],"sourcesContent":["/**\n * Turns step text into DOM nodes without ever using innerHTML. Supports a\n * small, safe inline Markdown subset: **bold**, *italic*, `code`, [links](url),\n * paragraphs separated by blank lines and line breaks on single newlines.\n */\n\nimport type { Media } from '@docentjs/core'\n\nconst SAFE_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:'])\n\nexport function isSafeUrl(url: string): boolean {\n const match = /^([a-z][a-z0-9+.-]*):/i.exec(url.trim())\n if (!match) return true // relative\n return SAFE_SCHEMES.has(`${match[1]?.toLowerCase()}:`)\n}\n\nconst INLINE = /(\\*\\*(.+?)\\*\\*)|(\\*(.+?)\\*)|(`(.+?)`)|(\\[(.+?)\\]\\(((?:[^()\\s]|\\([^()]*\\))+)\\))/g\n\nfunction appendInline(doc: Document, parent: Node, text: string): void {\n let last = 0\n for (const m of text.matchAll(INLINE)) {\n const index = m.index ?? 0\n if (index > last) parent.appendChild(doc.createTextNode(text.slice(last, index)))\n if (m[2] !== undefined) {\n const el = doc.createElement('strong')\n appendInline(doc, el, m[2])\n parent.appendChild(el)\n } else if (m[4] !== undefined) {\n const el = doc.createElement('em')\n appendInline(doc, el, m[4])\n parent.appendChild(el)\n } else if (m[6] !== undefined) {\n const el = doc.createElement('code')\n el.textContent = m[6]\n parent.appendChild(el)\n } else if (m[8] !== undefined && m[9] !== undefined) {\n if (isSafeUrl(m[9])) {\n const a = doc.createElement('a')\n a.href = m[9]\n a.target = '_blank'\n a.rel = 'noopener noreferrer'\n appendInline(doc, a, m[8])\n parent.appendChild(a)\n } else {\n parent.appendChild(doc.createTextNode(m[8]))\n }\n }\n last = index + m[0].length\n }\n if (last < text.length) parent.appendChild(doc.createTextNode(text.slice(last)))\n}\n\nfunction appendLines(doc: Document, parent: Node, text: string, inline: boolean): void {\n const lines = text.split('\\n')\n lines.forEach((line, i) => {\n if (i > 0) parent.appendChild(doc.createElement('br'))\n if (inline) appendInline(doc, parent, line)\n else parent.appendChild(doc.createTextNode(line))\n })\n}\n\nexport function renderBody(\n doc: Document,\n body: string,\n format: 'text' | 'markdown' = 'text',\n): DocumentFragment {\n const frag = doc.createDocumentFragment()\n for (const para of body.split(/\\n{2,}/)) {\n if (!para.trim()) continue\n const p = doc.createElement('p')\n appendLines(doc, p, para, format === 'markdown')\n frag.appendChild(p)\n }\n return frag\n}\n\nexport function renderMedia(doc: Document, media: Media): HTMLElement | null {\n if (!isSafeUrl(media.src)) return null\n if (media.type === 'image') {\n const img = doc.createElement('img')\n img.src = media.src\n img.alt = media.alt ?? ''\n img.setAttribute('loading', 'lazy')\n return img\n }\n const video = doc.createElement('video')\n video.src = media.src\n video.controls = true\n video.playsInline = true\n if (media.alt) video.setAttribute('aria-label', media.alt)\n return video\n}\n","/**\n * Detects fixed or sticky elements (headers, footers, banners) covering a\n * target after it was scrolled into view, and scrolls the page so the\n * target is fully uncovered.\n */\n\nimport type { Viewport } from './position'\n\nexport interface Occluder {\n el: Element\n rect: DOMRect\n /** Which edge of the target it covers. */\n edge: 'top' | 'bottom'\n}\n\nfunction isPinned(el: Element): boolean {\n const view = el.ownerDocument.defaultView\n if (!view) return false\n const position = view.getComputedStyle(el).position\n return position === 'fixed' || position === 'sticky'\n}\n\n/** Nearest pinned ancestor (inclusive), or null. */\nfunction pinnedAncestor(el: Element | null): Element | null {\n let cur: Element | null = el\n while (cur && cur !== cur.ownerDocument.documentElement) {\n if (isPinned(cur)) return cur\n cur = cur.parentElement\n }\n return null\n}\n\n/**\n * Find a pinned element covering the target's top or bottom edge.\n * `ignore` is our own host, which sits above everything.\n */\nexport function findOccluder(\n target: Element,\n ignore: Element | null,\n viewport: Viewport,\n): Occluder | null {\n const doc = target.ownerDocument\n const r = target.getBoundingClientRect()\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n const x = Math.min(Math.max(r.left + r.width / 2, vx + 1), vx + viewport.width - 1)\n const probes: Array<{ y: number; edge: 'top' | 'bottom' }> = [\n { y: r.top + 1, edge: 'top' },\n { y: r.bottom - 1, edge: 'bottom' },\n ]\n for (const { y, edge } of probes) {\n if (y < vy || y > vy + viewport.height) continue\n const stack = doc.elementsFromPoint(x, y).filter((el) => el !== ignore)\n const top = stack[0]\n if (!top || top === target || target.contains(top) || top.contains(target)) continue\n const pinned = pinnedAncestor(top)\n if (!pinned || pinned.contains(target)) continue\n return { el: pinned, rect: pinned.getBoundingClientRect(), edge }\n }\n return null\n}\n\n/**\n * Scroll so nothing pinned covers the target. Returns true if it scrolled.\n * Runs at most twice to handle a header and a footer together.\n */\nexport function uncover(\n target: Element,\n ignore: Element | null,\n viewport: Viewport,\n margin = 8,\n): boolean {\n const win = target.ownerDocument.defaultView\n if (!win || typeof target.ownerDocument.elementsFromPoint !== 'function') return false\n let scrolled = false\n for (let i = 0; i < 2; i++) {\n const occluder = findOccluder(target, ignore, viewport)\n if (!occluder) break\n const r = target.getBoundingClientRect()\n const delta =\n occluder.edge === 'top'\n ? -(occluder.rect.bottom - r.top + margin)\n : r.bottom - occluder.rect.top + margin\n win.scrollBy({ top: delta, behavior: 'auto' })\n scrolled = true\n }\n return scrolled\n}\n","/**\n * Pure popover positioning: pick a side, align, keep it on screen, and place\n * the arrow. No DOM access, so it is unit-tested without a browser.\n */\n\nimport type { Alignment, Placement, Side } from '@docentjs/core'\n\nexport interface Rect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface Size {\n width: number\n height: number\n}\n\n/**\n * The visible area, in the same coordinate space as the anchor. `x`/`y` are\n * the visual viewport's offset within the layout viewport (non-zero when the\n * page is pinch-zoomed or overflows horizontally on mobile).\n */\nexport interface Viewport extends Size {\n x?: number\n y?: number\n}\n\nexport interface PositionInput {\n /** The spotlighted area, in viewport coordinates. */\n anchor: Rect\n floating: Size\n viewport: Viewport\n placement: Placement\n /** Distance between anchor and popover. */\n gap?: number\n /** Minimum distance from the viewport edges. */\n edgePadding?: number\n /** Arrow size; keeps the arrow clear of the popover corners. */\n arrowSize?: number\n}\n\nexport interface PositionResult {\n x: number\n y: number\n side: Side\n align: Alignment\n /** Arrow offset along the popover's cross axis, from its top-left corner. */\n arrow: number\n}\n\nconst OPPOSITE: Record<Side, Side> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' }\n\nexport function parsePlacement(placement: Placement): { side: Side | 'auto'; align: Alignment } {\n if (placement === 'auto') return { side: 'auto', align: 'center' }\n const [side, align] = placement.split('-') as [Side, Alignment | undefined]\n return { side, align: align ?? 'center' }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n\nfunction isVertical(side: Side): boolean {\n return side === 'top' || side === 'bottom'\n}\n\n/** Free space between the anchor and the viewport edge on each side. */\nexport function availableSpace(anchor: Rect, viewport: Viewport): Record<Side, number> {\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n return {\n top: anchor.y - vy,\n bottom: vy + viewport.height - (anchor.y + anchor.height),\n left: anchor.x - vx,\n right: vx + viewport.width - (anchor.x + anchor.width),\n }\n}\n\nfunction candidates(side: Side | 'auto', space: Record<Side, number>): Side[] {\n if (side === 'auto') {\n return (Object.keys(space) as Side[]).sort((a, b) => space[b] - space[a])\n }\n const perpendicular: Side[] = isVertical(side) ? ['right', 'left'] : ['bottom', 'top']\n return [side, OPPOSITE[side], ...perpendicular.sort((a, b) => space[b] - space[a])]\n}\n\nexport function computePosition(input: PositionInput): PositionResult {\n const { anchor, floating, viewport } = input\n const gap = input.gap ?? 12\n const edge = input.edgePadding ?? 8\n const arrowSize = input.arrowSize ?? 8\n const { side: preferred, align } = parsePlacement(input.placement)\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n\n const space = availableSpace(anchor, viewport)\n const order = candidates(preferred, space)\n const needed = (s: Side) => (isVertical(s) ? floating.height : floating.width) + gap + edge\n const side = order.find((s) => space[s] >= needed(s)) ?? (order[0] as Side)\n\n // Main axis\n let x = 0\n let y = 0\n if (side === 'top') y = anchor.y - gap - floating.height\n if (side === 'bottom') y = anchor.y + anchor.height + gap\n if (side === 'left') x = anchor.x - gap - floating.width\n if (side === 'right') x = anchor.x + anchor.width + gap\n\n // Cross axis\n if (isVertical(side)) {\n if (align === 'start') x = anchor.x\n else if (align === 'end') x = anchor.x + anchor.width - floating.width\n else x = anchor.x + anchor.width / 2 - floating.width / 2\n x = clamp(x, vx + edge, Math.max(vx + edge, vx + viewport.width - edge - floating.width))\n } else {\n if (align === 'start') y = anchor.y\n else if (align === 'end') y = anchor.y + anchor.height - floating.height\n else y = anchor.y + anchor.height / 2 - floating.height / 2\n y = clamp(y, vy + edge, Math.max(vy + edge, vy + viewport.height - edge - floating.height))\n }\n\n // Arrow points at the anchor centre, kept away from the popover corners.\n const margin = arrowSize * 2\n const arrow = isVertical(side)\n ? clamp(anchor.x + anchor.width / 2 - x, margin, floating.width - margin)\n : clamp(anchor.y + anchor.height / 2 - y, margin, floating.height - margin)\n\n return { x: Math.round(x), y: Math.round(y), side, align, arrow: Math.round(arrow) }\n}\n\n/** Centre a popover in the viewport, for steps without a target. */\nexport function centerPosition(floating: Size, viewport: Viewport): { x: number; y: number } {\n return {\n x: Math.round((viewport.x ?? 0) + Math.max(0, (viewport.width - floating.width) / 2)),\n y: Math.round((viewport.y ?? 0) + Math.max(0, (viewport.height - floating.height) / 2)),\n }\n}\n\n/** Grow a rect on every side. */\nexport function inflate(rect: Rect, by: number): Rect {\n return {\n x: rect.x - by,\n y: rect.y - by,\n width: rect.width + by * 2,\n height: rect.height + by * 2,\n }\n}\n\n/**\n * The part of a rect that is on screen. Positioning against this keeps the\n * popover and arrow near the visible portion of oversized targets.\n */\nexport function clipToViewport(rect: Rect, viewport: Viewport): Rect {\n const vx = viewport.x ?? 0\n const vy = viewport.y ?? 0\n const x1 = Math.max(vx, rect.x)\n const y1 = Math.max(vy, rect.y)\n const x2 = Math.min(vx + viewport.width, rect.x + rect.width)\n const y2 = Math.min(vy + viewport.height, rect.y + rect.height)\n if (x2 <= x1 || y2 <= y1) return rect\n return { x: x1, y: y1, width: x2 - x1, height: y2 - y1 }\n}\n","/**\n * Full-viewport backdrop with a rounded cutout. The cutout is a `clip-path`\n * so pointer events pass through the hole to the page for free; a separate\n * blocker element covers it when the step forbids interaction.\n */\n\nimport type { SpotlightShape } from '@docentjs/core'\nimport { inflate, type Rect, type Size } from './position'\n\nexport function holePath(viewport: Size, hole: Rect, radius: number): string {\n const r = Math.max(0, Math.min(radius, hole.width / 2, hole.height / 2))\n const { x, y, width: w, height: h } = hole\n const outer = `M0 0H${viewport.width}V${viewport.height}H0Z`\n const inner =\n `M${x + r} ${y}H${x + w - r}A${r} ${r} 0 0 1 ${x + w} ${y + r}V${y + h - r}` +\n `A${r} ${r} 0 0 1 ${x + w - r} ${y + h}H${x + r}A${r} ${r} 0 0 1 ${x} ${y + h - r}` +\n `V${y + r}A${r} ${r} 0 0 1 ${x + r} ${y}Z`\n return `path(evenodd, \"${outer}${inner}\")`\n}\n\nexport interface OverlayUpdate {\n /** Target rect in viewport coordinates, or `null` for a modal step. */\n target: Rect | null\n padding: number\n radius: number\n shape?: SpotlightShape\n}\n\n/** The padded cutout and its corner radius for a shape. */\nexport function holeFor(\n target: Rect,\n padding: number,\n radius: number,\n shape: SpotlightShape = 'rounded',\n): { hole: Rect; radius: number } {\n if (shape === 'circle') {\n const cx = target.x + target.width / 2\n const cy = target.y + target.height / 2\n const rr = Math.hypot(target.width, target.height) / 2 + padding\n return { hole: { x: cx - rr, y: cy - rr, width: rr * 2, height: rr * 2 }, radius: rr }\n }\n const hole = inflate(target, padding)\n if (shape === 'rect') return { hole, radius: 0 }\n if (shape === 'pill') return { hole, radius: Math.min(hole.width, hole.height) / 2 }\n return { hole, radius: Math.max(0, Math.min(radius, hole.width / 2, hole.height / 2)) }\n}\n\nexport class Overlay {\n readonly el: HTMLDivElement\n readonly blocker: HTMLDivElement\n /** Hairline of light around the cutout. */\n readonly ring: HTMLDivElement\n private lastHole: Rect | null = null\n\n constructor(doc: Document) {\n this.el = doc.createElement('div')\n this.el.setAttribute('part', 'overlay')\n this.el.className = 'overlay'\n this.blocker = doc.createElement('div')\n this.blocker.className = 'blocker'\n this.blocker.hidden = true\n this.ring = doc.createElement('div')\n this.ring.className = 'ring'\n this.ring.setAttribute('part', 'ring')\n this.ring.style.opacity = '0'\n }\n\n /** Move the ring to a rect; a zero-size rect collapses it (modal steps). */\n private placeRing(rect: Rect, radius: number, visible: boolean): void {\n Object.assign(this.ring.style, {\n transform: `translate(${rect.x}px, ${rect.y}px)`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n borderRadius: `${radius}px`,\n opacity: visible ? '1' : '0',\n })\n }\n\n /** Current hole, padded, in viewport coordinates. */\n get hole(): Rect | null {\n return this.lastHole\n }\n\n update(viewport: Size, { target, padding, radius, shape }: OverlayUpdate, block: boolean): void {\n if (!target) {\n // Collapse to a point so the path keeps the same structure and can animate.\n const c = this.lastHole\n const cx = c ? c.x + c.width / 2 : viewport.width / 2\n const cy = c ? c.y + c.height / 2 : viewport.height / 2\n this.lastHole = null\n this.setCentre(cx, cy)\n this.el.style.clipPath = holePath(viewport, { x: cx, y: cy, width: 0, height: 0 }, 0)\n this.placeRing({ x: cx, y: cy, width: 0, height: 0 }, 0, false)\n this.blocker.hidden = true\n return\n }\n const { hole, radius: r } = holeFor(target, padding, radius, shape)\n this.lastHole = hole\n this.setCentre(hole.x + hole.width / 2, hole.y + hole.height / 2)\n this.el.style.clipPath = holePath(viewport, hole, r)\n this.placeRing(hole, r, true)\n this.blocker.hidden = !block\n if (block) {\n this.blocker.style.transform = `translate(${hole.x}px, ${hole.y}px)`\n this.blocker.style.width = `${hole.width}px`\n this.blocker.style.height = `${hole.height}px`\n }\n }\n\n /** Exposed for the vignette style, which is centred on the cutout. */\n private setCentre(x: number, y: number): void {\n this.el.style.setProperty('--docent-hole-x', `${Math.round(x)}px`)\n this.el.style.setProperty('--docent-hole-y', `${Math.round(y)}px`)\n }\n}\n","/**\n * Builds the popover DOM for a step. Every region is wrapped in a named\n * `<slot>` whose fallback is the default UI, so custom content projected\n * from the light DOM replaces it without touching the rest.\n */\n\nimport type { Labels, RenderContext } from '@docentjs/core'\nimport { renderBody, renderMedia } from './content'\nimport type { PopoverSlots, SlotName } from './theme'\n\nexport const DEFAULT_LABELS: Required<Labels> = {\n next: 'Next',\n back: 'Back',\n skip: 'Skip',\n done: 'Done',\n close: 'Close',\n progress: '{current} of {total}',\n}\n\nexport interface PopoverParts {\n el: HTMLDivElement\n arrow: HTMLDivElement\n /** Element to focus when the step opens. */\n initialFocus: HTMLElement\n /** Light-DOM nodes to append to the shadow host so they project into slots. */\n slotted: Element[]\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className: string,\n part: string,\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag)\n el.className = className\n el.setAttribute('part', part)\n return el\n}\n\nfunction slot(doc: Document, name: SlotName, fallback?: Node): HTMLSlotElement {\n const s = doc.createElement('slot')\n s.name = name\n if (fallback) s.appendChild(fallback)\n return s\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** A 14px stroked X, drawn rather than typed so it centers optically in any font. */\nfunction closeIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, 'svg')\n svg.setAttribute('viewBox', '0 0 14 14')\n svg.setAttribute('aria-hidden', 'true')\n svg.setAttribute('fill', 'none')\n const path = doc.createElementNS(SVG_NS, 'path')\n path.setAttribute('d', 'M3.5 3.5l7 7m0-7l-7 7')\n path.setAttribute('stroke', 'currentColor')\n path.setAttribute('stroke-width', '1.6')\n path.setAttribute('stroke-linecap', 'round')\n svg.appendChild(path)\n return svg\n}\n\n/** A small forward arrow for the primary action, so direction reads at a glance. */\nfunction arrowIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, 'svg')\n svg.setAttribute('viewBox', '0 0 12 12')\n svg.setAttribute('aria-hidden', 'true')\n svg.setAttribute('fill', 'none')\n svg.setAttribute('class', 'icon')\n const path = doc.createElementNS(SVG_NS, 'path')\n path.setAttribute('d', 'M2.5 6h7m-3-3l3 3-3 3')\n path.setAttribute('stroke', 'currentColor')\n path.setAttribute('stroke-width', '1.5')\n path.setAttribute('stroke-linecap', 'round')\n path.setAttribute('stroke-linejoin', 'round')\n svg.appendChild(path)\n return svg\n}\n\nexport function formatProgress(template: string, current: number, total: number): string {\n return template.replace('{current}', String(current)).replace('{total}', String(total))\n}\n\n/**\n * Resolve slot overrides into light-DOM elements carrying `slot=\"<name>\"`.\n * A `null` result projects an empty element, which suppresses the fallback.\n */\nexport function resolveSlots(doc: Document, slots: PopoverSlots, ctx: RenderContext): Element[] {\n const out: Element[] = []\n for (const [name, render] of Object.entries(slots) as Array<[SlotName, PopoverSlots[SlotName]]>) {\n const content = render?.(ctx, doc)\n if (content === undefined) continue\n let el: Element\n if (content === null) el = doc.createElement('span')\n else if (typeof content === 'string') {\n el = doc.createElement('span')\n el.textContent = content\n } else if (content instanceof Element) el = content\n else {\n el = doc.createElement('div')\n el.appendChild(content)\n }\n el.setAttribute('slot', name)\n out.push(el)\n }\n return out\n}\n\nexport function buildPopover(\n doc: Document,\n ctx: RenderContext,\n labels: Labels = {},\n slots: PopoverSlots = {},\n): PopoverParts {\n const { step, tour, actions } = ctx\n const options = tour.options ?? {}\n const text: Required<Labels> = { ...DEFAULT_LABELS, ...options.labels, ...labels }\n const buttons = step.buttons ?? {}\n const id = `docent-${tour.id}-${step.id}`\n\n const el = h(doc, 'div', 'popover', 'popover')\n el.setAttribute('role', 'dialog')\n el.tabIndex = -1\n\n const arrow = h(doc, 'div', 'arrow', 'arrow')\n el.appendChild(arrow)\n\n // Header: title + close\n const header = h(doc, 'div', 'header', 'header')\n let titleNode: Node | undefined\n if (step.title) {\n const title = h(doc, 'h2', 'title', 'title')\n title.id = `${id}-title`\n title.textContent = step.title\n titleNode = title\n el.setAttribute('aria-labelledby', title.id)\n }\n header.appendChild(slot(doc, 'title', titleNode))\n let closeNode: Node | undefined\n if (options.allowClose !== false && buttons.close !== false) {\n const close = h(doc, 'button', 'close', 'close')\n close.type = 'button'\n close.setAttribute('aria-label', text.close)\n close.appendChild(closeIcon(doc))\n close.addEventListener('click', () => actions.skip())\n closeNode = close\n }\n header.appendChild(slot(doc, 'close', closeNode))\n el.appendChild(slot(doc, 'header', header))\n\n // Body\n let bodyNode: Node | undefined\n if (step.body) {\n const body = h(doc, 'div', 'body', 'body')\n body.id = `${id}-body`\n body.appendChild(renderBody(doc, step.body, step.format))\n bodyNode = body\n el.setAttribute('aria-describedby', body.id)\n }\n el.appendChild(slot(doc, 'body', bodyNode))\n\n // Media\n let mediaNode: Node | undefined\n if (step.media) {\n const media = renderMedia(doc, step.media)\n if (media) {\n const wrap = h(doc, 'div', 'media', 'media')\n wrap.appendChild(media)\n mediaNode = wrap\n }\n }\n el.appendChild(slot(doc, 'media', mediaNode))\n\n // Footer: progress + buttons\n const footer = h(doc, 'div', 'footer', 'footer')\n const progress = h(doc, 'div', 'progress', 'progress')\n if (options.showProgress !== false) {\n // A slim meter plus the count; the meter is decorative, the text is read out.\n const meter = h(doc, 'span', 'meter', 'meter')\n meter.setAttribute('aria-hidden', 'true')\n progress.style.setProperty('--docent-step', String(ctx.progress.current))\n progress.style.setProperty('--docent-steps', String(Math.max(1, ctx.progress.total)))\n const count = h(doc, 'span', 'count', 'count')\n count.textContent = formatProgress(text.progress, ctx.progress.current, ctx.progress.total)\n progress.append(meter, count)\n }\n footer.appendChild(slot(doc, 'progress', progress))\n\n const group = h(doc, 'div', 'buttons', 'buttons')\n let initialFocus: HTMLElement = el\n const button = (label: string, part: string, primary: boolean, onClick: () => void) => {\n const b = h(doc, 'button', primary ? 'button primary' : 'button', `button ${part}`)\n b.type = 'button'\n b.textContent = label\n b.addEventListener('click', onClick)\n group.appendChild(b)\n return b\n }\n // Reading order matches visual order: quiet Skip, then Back, then the primary action.\n if (buttons.skip !== false && !ctx.isLast) button(text.skip, 'button-skip', false, actions.skip)\n if (buttons.back !== false && ctx.canGoBack) button(text.back, 'button-back', false, actions.back)\n if (buttons.next !== false) {\n initialFocus = button(ctx.isLast ? text.done : text.next, 'button-next', true, actions.next)\n if (!ctx.isLast) initialFocus.appendChild(arrowIcon(doc))\n }\n footer.appendChild(slot(doc, 'buttons', group))\n el.appendChild(slot(doc, 'footer', footer))\n\n const slotted = resolveSlots(doc, slots, ctx)\n if (\n slotted.some((s) => s.getAttribute('slot') === 'buttons' || s.getAttribute('slot') === 'footer')\n ) {\n initialFocus = el\n }\n return { el, arrow, initialFocus, slotted }\n}\n\n/** Wrapper used in headless mode: a positioned shell that projects the app's own popover. */\nexport function buildHeadlessShell(doc: Document): { el: HTMLDivElement; arrow: HTMLDivElement } {\n const el = h(doc, 'div', 'popover headless', 'popover')\n const arrow = h(doc, 'div', 'arrow', 'arrow')\n arrow.hidden = true\n el.appendChild(arrow)\n const s = doc.createElement('slot')\n s.name = 'popover'\n el.appendChild(s)\n return { el, arrow }\n}\n","/**\n * Styles injected into the shadow root. Theme through the custom properties.\n *\n * Design: quiet precision (see .impeccable.md). The popover inherits the host\n * site's font; hierarchy comes from size, weight, tracking and color. Colors\n * are ink tinted toward the Docent hue (OKLCH 285). Light is the default;\n * dark is opt-in through tokens or the `dark` preset.\n */\nexport const STYLES = `\n:host {\n /* Public tokens (see Theme). --docent-font is unset so the host font is inherited. */\n --docent-bg: oklch(99.4% 0.003 285);\n --docent-fg: oklch(23% 0.018 285);\n --docent-muted: oklch(52% 0.014 285);\n --docent-accent: oklch(26% 0.02 285);\n --docent-accent-fg: oklch(98.5% 0.004 285);\n --docent-radius: 14px;\n --docent-shadow:\n 0 1px 2px oklch(23% 0.02 285 / 0.06),\n 0 8px 24px -6px oklch(23% 0.02 285 / 0.16),\n 0 28px 56px -16px oklch(23% 0.02 285 / 0.24);\n --docent-width: 344px;\n --docent-overlay: oklch(20% 0.02 285);\n --docent-overlay-opacity: 0.52;\n --docent-duration: 220ms;\n /* Fast start, gentle stop: movement begins the moment you click. */\n --docent-easing: cubic-bezier(0.2, 0.8, 0.2, 1);\n\n /* Derived, internal: follow whatever the tokens are set to. */\n --_line: color-mix(in oklch, var(--docent-fg) 11%, transparent);\n --_soft: color-mix(in oklch, var(--docent-fg) 6%, transparent);\n --_body: color-mix(in oklch, var(--docent-fg) 80%, var(--docent-bg));\n\n position: fixed;\n inset: 0;\n z-index: var(--docent-z, 2147483000);\n pointer-events: none;\n color: var(--docent-fg);\n /* Invalid (unset) when the token is absent, which inherits the host font. */\n font-family: var(--docent-font);\n font-size: 14px;\n font-weight: 400;\n font-style: normal;\n line-height: 1.55;\n letter-spacing: normal;\n text-transform: none;\n text-align: start;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n* { box-sizing: border-box; }\n\n/* ------------------------------------------------------------------ overlay */\n\n.overlay {\n --_scrim: color-mix(in oklch, var(--docent-overlay) calc(var(--docent-overlay-opacity) * 100%), transparent);\n position: absolute;\n inset: 0;\n background: var(--_scrim);\n pointer-events: auto;\n transition: clip-path var(--docent-duration) var(--docent-easing);\n}\n/* Overlay styles. The scrim is a translucent color (not element opacity), so blur stays crisp. */\n:host([data-overlay=\"blur\"]) .overlay {\n -webkit-backdrop-filter: blur(var(--docent-blur, 4px));\n backdrop-filter: blur(var(--docent-blur, 4px));\n}\n:host([data-overlay=\"vignette\"]) .overlay {\n background: radial-gradient(\n circle at var(--docent-hole-x, 50%) var(--docent-hole-y, 50%),\n transparent 0,\n color-mix(in oklch, var(--docent-overlay) calc(var(--docent-overlay-opacity) * 30%), transparent) 22%,\n var(--_scrim) 78%\n );\n}\n:host([data-overlay=\"none\"]) .overlay { background: transparent; pointer-events: none; }\n.blocker {\n position: absolute;\n left: 0;\n top: 0;\n pointer-events: auto;\n}\n/* A hairline of light around the cutout keeps the target crisp against the scrim. */\n.ring {\n position: absolute;\n left: 0;\n top: 0;\n pointer-events: none;\n /* Light by default: it sits on the scrim, not on the popover, in every theme. */\n color: var(--docent-ring, oklch(98% 0.004 285));\n box-shadow:\n 0 0 0 1px color-mix(in oklch, currentColor 58%, transparent),\n 0 0 0 6px color-mix(in oklch, currentColor 8%, transparent);\n transition:\n transform var(--docent-duration) var(--docent-easing),\n width var(--docent-duration) var(--docent-easing),\n height var(--docent-duration) var(--docent-easing),\n border-radius var(--docent-duration) var(--docent-easing),\n opacity var(--docent-duration) var(--docent-easing);\n}\n\n/* Ring styles. */\n:host([data-overlay=\"none\"]) .ring { color: var(--docent-ring, var(--docent-accent)); }\n:host([data-ring=\"none\"]) .ring { box-shadow: none; }\n:host([data-ring=\"glow\"]) .ring {\n box-shadow:\n 0 0 0 1.5px color-mix(in oklch, currentColor 85%, transparent),\n 0 0 20px 4px color-mix(in oklch, currentColor 42%, transparent);\n}\n:host([data-ring=\"solid\"]) .ring { box-shadow: 0 0 0 2px currentColor; }\n:host([data-ring=\"dashed\"]) .ring {\n box-shadow: none;\n outline: 1.5px dashed color-mix(in oklch, currentColor 85%, transparent);\n outline-offset: 3px;\n}\n:host([data-ring=\"pulse\"]) .ring::after {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n animation: docent-pulse 1.8s var(--docent-easing) infinite;\n}\n@keyframes docent-pulse {\n from { box-shadow: 0 0 0 0 color-mix(in oklch, currentColor 60%, transparent); }\n to { box-shadow: 0 0 0 14px transparent; }\n}\n\n:host(:not([data-arrow=\"caret\"])) .arrow { display: none; }\n\n/* Scroll-driven updates follow the target instantly. */\n:host([data-tracking]) .overlay,\n:host([data-tracking]) .ring,\n:host([data-tracking]) .popover { transition: none; }\n\n/* ------------------------------------------------------------------ popover */\n\n.popover {\n position: absolute;\n left: 0;\n top: 0;\n display: flex;\n flex-direction: column;\n width: var(--docent-width);\n max-width: calc(100vw - 32px);\n padding: 20px 20px 16px;\n background: var(--docent-bg);\n border-radius: var(--docent-radius);\n box-shadow: 0 0 0 1px var(--_line), var(--docent-shadow);\n pointer-events: auto;\n outline: none;\n transition:\n transform var(--docent-duration) var(--docent-easing),\n opacity var(--docent-duration) var(--docent-easing),\n scale var(--docent-duration) var(--docent-easing);\n}\n.popover[data-side=\"bottom\"] { transform-origin: 50% 0; }\n.popover[data-side=\"top\"] { transform-origin: 50% 100%; }\n.popover[data-side=\"right\"] { transform-origin: 0 50%; }\n.popover[data-side=\"left\"] { transform-origin: 100% 50%; }\n.popover[data-entering] { opacity: 0; scale: 0.97; transition: none; }\n/* Between steps the popover slides; only its content cross-fades, briefly. */\n.popover[data-moving] > * { animation: docent-swap 160ms ease-out; }\n@keyframes docent-swap { from { opacity: 0; } to { opacity: 1; } }\n.popover.headless {\n width: auto;\n max-width: none;\n padding: 0;\n background: none;\n box-shadow: none;\n border-radius: 0;\n}\n\n/* The arrow carries the same hairline on its two outward edges. */\n.arrow {\n position: absolute;\n width: 12px;\n height: 12px;\n background: var(--docent-bg);\n transform: rotate(45deg);\n}\n.popover[data-side=\"bottom\"] .arrow {\n top: -6px;\n border-top: 1px solid var(--_line);\n border-left: 1px solid var(--_line);\n border-top-left-radius: 2px;\n}\n.popover[data-side=\"top\"] .arrow {\n bottom: -6px;\n border-bottom: 1px solid var(--_line);\n border-right: 1px solid var(--_line);\n border-bottom-right-radius: 2px;\n}\n.popover[data-side=\"right\"] .arrow {\n left: -6px;\n border-bottom: 1px solid var(--_line);\n border-left: 1px solid var(--_line);\n border-bottom-left-radius: 2px;\n}\n.popover[data-side=\"left\"] .arrow {\n right: -6px;\n border-top: 1px solid var(--_line);\n border-right: 1px solid var(--_line);\n border-top-right-radius: 2px;\n}\n.popover[data-side=\"center\"] .arrow,\n.popover[data-side=\"sheet\"] .arrow { display: none; }\n\n/* ------------------------------------------------------------------ content */\n\n.header { display: flex; align-items: flex-start; gap: 12px; }\n.title {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n line-height: 1.3;\n letter-spacing: -0.012em;\n color: var(--docent-fg);\n text-wrap: balance;\n}\n.close {\n flex: none;\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n margin: -3px -8px -3px 0;\n padding: 0;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--docent-muted);\n cursor: pointer;\n transition: background-color 120ms ease-out, color 120ms ease-out;\n}\n.close svg { width: 14px; height: 14px; }\n.close:hover { background: var(--_soft); color: var(--docent-fg); }\n\n.body { margin-top: 6px; color: var(--_body); text-wrap: pretty; }\n.body p { margin: 0; }\n.body p + p { margin-top: 8px; }\n.body strong { font-weight: 600; color: var(--docent-fg); }\n.body a {\n color: var(--docent-fg);\n text-decoration: underline;\n text-decoration-color: color-mix(in oklch, var(--docent-fg) 32%, transparent);\n text-decoration-thickness: 1px;\n text-underline-offset: 3px;\n transition: text-decoration-color 120ms ease-out;\n}\n.body a:hover { text-decoration-color: currentColor; }\n.body code {\n font-family: ui-monospace, \"SF Mono\", SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 0.88em;\n padding: 1px 5px;\n border-radius: 5px;\n background: var(--_soft);\n color: var(--docent-fg);\n}\n\n.media { margin-top: 14px; }\n.media img, .media video {\n display: block;\n width: 100%;\n border-radius: 8px;\n box-shadow: 0 0 0 1px var(--_line);\n}\n\n/* ------------------------------------------------------------------- footer */\n\n.footer {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 20px;\n}\n.progress {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n color: var(--docent-muted);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.01em;\n white-space: nowrap;\n}\n.meter {\n flex: none;\n width: 28px;\n height: 3px;\n border-radius: 999px;\n background:\n linear-gradient(var(--docent-fg), var(--docent-fg)) 0 0 / calc(var(--docent-step) / var(--docent-steps) * 100%) 100% no-repeat,\n var(--_line);\n}\n.buttons { display: flex; align-items: center; gap: 6px; }\n.button {\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 32px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--docent-fg);\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n line-height: 1;\n letter-spacing: -0.003em;\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color 120ms ease-out,\n color 120ms ease-out,\n scale 80ms ease-out;\n}\n.button:hover { background: var(--_soft); }\n.button:active { scale: 0.97; }\n[part~=\"button-skip\"] { color: var(--docent-muted); padding: 0 8px; }\n[part~=\"button-skip\"]:hover { color: var(--docent-fg); background: transparent; }\n.button.primary {\n padding: 0 14px;\n background: var(--docent-accent);\n color: var(--docent-accent-fg);\n font-weight: 600;\n box-shadow: inset 0 1px 0 color-mix(in oklch, var(--docent-accent-fg) 14%, transparent);\n}\n.button.primary .icon { width: 12px; height: 12px; margin: 0 -2px 0 6px; transition: translate 160ms var(--docent-easing); }\n.button.primary:hover .icon { translate: 2px 0; }\n.button.primary:hover {\n background: color-mix(in oklch, var(--docent-accent) 86%, var(--docent-accent-fg));\n}\n.button:focus-visible,\n.close:focus-visible {\n outline: 2px solid var(--docent-accent);\n outline-offset: 2px;\n}\n\n/* ------------------------------------------------------------ mobile sheet */\n\n.popover.sheet {\n max-width: none;\n padding: 20px 20px max(16px, env(safe-area-inset-bottom));\n border-radius: var(--docent-radius) var(--docent-radius) 0 0;\n box-shadow:\n 0 0 0 1px var(--_line),\n 0 -12px 40px -12px oklch(23% 0.02 285 / 0.28);\n}\n@media (pointer: coarse) {\n :host { font-size: 15px; }\n .button { min-height: 44px; padding: 0 16px; font-size: 14px; }\n .close { width: 40px; height: 40px; margin: -9px -12px -9px 0; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .overlay, .popover, .ring { transition: none; }\n .ring::after { animation: none !important; }\n .popover[data-moving] > * { animation: none; }\n}\n`\n","/**\n * Resolves schema targets to DOM elements. Pierces open shadow roots as a\n * fallback and can wait for elements that render later.\n */\n\nimport type { Target, TargetSpec } from '@docentjs/core'\n\nexport type QueryRoot = Document | DocumentFragment | Element\n\n/** Attribute that `{ name }` targets resolve through. */\nexport const NAME_ATTRIBUTE = 'data-docent'\n\nfunction escapeAttr(value: string): string {\n const css = (globalThis as { CSS?: { escape?: (s: string) => string } }).CSS\n return css?.escape ? css.escape(value) : value.replace(/[\"\\\\]/g, '\\\\$&')\n}\n\nexport function toSpec(target: Target): TargetSpec {\n return typeof target === 'string' ? { selectors: [target] } : target\n}\n\n/** Selectors to try, in order, for a target. */\nexport function candidateSelectors(target: Target): string[] {\n const spec = toSpec(target)\n const out: string[] = []\n if (spec.name) out.push(`[${NAME_ATTRIBUTE}=\"${escapeAttr(spec.name)}\"]`)\n if (spec.selectors) out.push(...spec.selectors)\n return out\n}\n\nfunction safeQueryAll(root: QueryRoot, selector: string): Element[] {\n try {\n return Array.from(root.querySelectorAll(selector))\n } catch {\n return []\n }\n}\n\n/** Query the root, then every open shadow root beneath it. */\nexport function queryAllDeep(root: QueryRoot, selector: string): Element[] {\n const direct = safeQueryAll(root, selector)\n if (direct.length > 0) return direct\n const out: Element[] = []\n for (const el of safeQueryAll(root, '*')) {\n if (el.shadowRoot) out.push(...queryAllDeep(el.shadowRoot, selector))\n }\n return out\n}\n\nexport function resolveTarget(target: Target, root: QueryRoot = document): Element | null {\n const spec = toSpec(target)\n let scope: QueryRoot = root\n if (spec.within) {\n const container = queryAllDeep(root, spec.within)[0]\n if (!container) return null\n scope = container\n }\n for (const selector of candidateSelectors(spec)) {\n const matches = queryAllDeep(scope, selector)\n if (matches.length > 0) return matches[spec.nth ?? 0] ?? null\n }\n return null\n}\n\n/**\n * Resolve now, or watch the DOM until the target appears, the timeout passes,\n * or the signal aborts. Resolves `null` when it never shows up.\n */\nexport function waitForTarget(\n target: Target,\n timeoutMs: number,\n signal?: AbortSignal,\n root: QueryRoot = document,\n): Promise<Element | null> {\n const now = resolveTarget(target, root)\n if (now || signal?.aborted) return Promise.resolve(now)\n\n return new Promise((resolve) => {\n let scheduled = false\n const observed =\n root.nodeType === Node.DOCUMENT_NODE ? (root as Document).documentElement : root\n const done = (el: Element | null) => {\n observer.disconnect()\n if (timer !== undefined) clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n resolve(el)\n }\n const check = () => {\n scheduled = false\n const el = resolveTarget(target, root)\n if (el) done(el)\n }\n const observer = new MutationObserver(() => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(check)\n })\n const onAbort = () => done(null)\n const timer = Number.isFinite(timeoutMs) ? setTimeout(() => done(null), timeoutMs) : undefined\n signal?.addEventListener('abort', onAbort, { once: true })\n observer.observe(observed, { childList: true, subtree: true, attributes: true })\n })\n}\n","/**\n * Theme tokens → CSS custom properties, plus the slot and template contracts\n * that let apps, framework adapters and (later) the visual builder customise\n * the popover without forking the renderer.\n */\n\nimport type {\n ArrowStyle,\n OverlayOptions,\n RenderContext,\n SpotlightOptions,\n Theme,\n} from '@docentjs/core'\n\n/** Token → CSS custom property (without the `--docent-` prefix). */\nexport const THEME_VARS: Record<keyof Theme, string> = {\n background: 'bg',\n foreground: 'fg',\n muted: 'muted',\n accent: 'accent',\n accentForeground: 'accent-fg',\n radius: 'radius',\n shadow: 'shadow',\n font: 'font',\n width: 'width',\n overlay: 'overlay',\n overlayOpacity: 'overlay-opacity',\n duration: 'duration',\n zIndex: 'z',\n connector: 'connector',\n ring: 'ring',\n}\n\n/** Write theme tokens as inline custom properties on an element. Clears unset ones. */\nexport function applyTheme(el: HTMLElement, theme: Theme | undefined): void {\n for (const key of Object.keys(THEME_VARS) as Array<keyof Theme>) {\n const value = theme?.[key]\n const prop = `--docent-${THEME_VARS[key]}`\n if (value === undefined) el.style.removeProperty(prop)\n else el.style.setProperty(prop, value)\n }\n}\n\nexport function mergeThemes(...themes: Array<Theme | undefined>): Theme {\n return Object.assign({}, ...themes.filter(Boolean)) as Theme\n}\n\n// ---------------------------------------------------------------------------\n// Slots\n// ---------------------------------------------------------------------------\n\n/**\n * Regions of the built-in popover that can be replaced. Custom content is\n * projected through native Shadow DOM slots, so it lives in the page's DOM\n * and keeps the page's CSS and framework behaviour.\n */\nexport type SlotName =\n | 'header'\n | 'title'\n | 'close'\n | 'body'\n | 'media'\n | 'footer'\n | 'progress'\n | 'buttons'\n\n/**\n * What a slot renderer returns:\n * - a `Node` replaces the region,\n * - a string replaces it with text,\n * - `null` removes the region,\n * - `undefined` keeps the default.\n */\nexport type SlotContent = Node | string | null | undefined\n\nexport type SlotRenderer = (ctx: RenderContext, doc: Document) => SlotContent\n\nexport type PopoverSlots = Partial<Record<SlotName, SlotRenderer>>\n\n// ---------------------------------------------------------------------------\n// Templates and headless mode\n// ---------------------------------------------------------------------------\n\n/**\n * A named bundle of theme, slots and CSS. Tours pick one by name through\n * `options.template`, which keeps the JSON builder-friendly while the code\n * that defines the template stays in the app.\n */\nexport interface PopoverTemplate {\n theme?: Theme\n slots?: PopoverSlots\n /** Arrow style for tours using this template. */\n arrow?: ArrowStyle\n spotlight?: SpotlightOptions\n overlay?: OverlayOptions\n /** Extra CSS injected into the shadow root while this template is active. */\n css?: string\n}\n\n/**\n * Replace the whole popover. The renderer still draws the overlay and\n * spotlight, positions `container`, sets `data-side` and `--docent-arrow`\n * on it, and handles keyboard, focus and state. You draw everything inside.\n */\nexport interface HeadlessPopover {\n /** Render the step into `container`. Return a cleanup to run before the next step. */\n render(ctx: RenderContext, container: HTMLElement): undefined | (() => void)\n}\n","/**\n * The web renderer. Draws the overlay, spotlight and popover inside a shadow\n * root, keeps them glued to the target through scroll, resize and layout\n * changes, and wires gestures and keys back to the controller.\n *\n * Customisation layers, lowest to highest precedence:\n * renderer options → template (by name) → tour options. Slots project\n * light-DOM content into the built-in popover; headless mode replaces it.\n */\n\nimport type {\n ArrowStyle,\n Labels,\n OverlayOptions,\n RenderContext,\n Renderer,\n SpotlightOptions,\n Step,\n Target,\n Theme,\n} from '@docentjs/core'\nimport { arrowGap, isConnector } from './arrows'\nimport type { Connector, Point } from './connector'\nimport { uncover } from './occlusion'\nimport { Overlay } from './overlay'\nimport { buildHeadlessShell, buildPopover } from './popover'\nimport {\n centerPosition,\n clipToViewport,\n computePosition,\n type Rect,\n type Viewport,\n} from './position'\nimport { STYLES } from './styles'\nimport { resolveTarget, waitForTarget } from './target'\nimport {\n applyTheme,\n type HeadlessPopover,\n mergeThemes,\n type PopoverSlots,\n type PopoverTemplate,\n} from './theme'\n\nexport interface DomRendererOptions {\n /** Document to render into. Defaults to the global document. */\n document?: Document\n /** Override button and progress labels for every tour. */\n labels?: Labels\n /** Distance between target and popover, in px. */\n gap?: number\n /** Spotlight defaults when a tour sets none: padding, radius, shape, ring. */\n spotlight?: SpotlightOptions\n /** Arrow style when a tour sets none. Default `caret`. */\n arrow?: ArrowStyle\n /** Overlay defaults when a tour sets none: style, color, opacity, blur. */\n overlay?: OverlayOptions\n /** Base theme tokens. Tours and templates layer on top. */\n theme?: Theme\n /** Replace regions of the built-in popover. */\n slots?: PopoverSlots\n /** Named templates that tours select with `options.template`. */\n templates?: Record<string, PopoverTemplate>\n /** Template to use when a tour names none. */\n template?: string\n /** Bring your own popover. Overlay, spotlight, positioning and keys stay. */\n headless?: HeadlessPopover\n /** Extra CSS injected into the shadow root. */\n css?: string\n /**\n * Below this viewport width the popover docks to the bottom edge as a sheet\n * instead of floating beside the target. Default 480; 0 disables.\n */\n sheetBreakpoint?: number\n /** Scroll past sticky/fixed headers and footers that cover the target. Default true. */\n avoidOcclusion?: boolean\n}\n\ntype Cleanup = () => void\n\ninterface Look {\n arrow: ArrowStyle\n spotlight: SpotlightOptions\n overlay: OverlayOptions\n}\n\nconst DEFAULT_LOOK: Look = { arrow: 'caret', spotlight: {}, overlay: {} }\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\nexport class DomRenderer implements Renderer {\n private readonly doc: Document\n private readonly options: DomRendererOptions\n private host: HTMLDivElement | undefined\n private shadow: ShadowRoot | undefined\n private overlay: Overlay | undefined\n private templateStyle: HTMLStyleElement | undefined\n private popover: HTMLDivElement | undefined\n private arrow: HTMLDivElement | undefined\n private headlessContainer: HTMLElement | undefined\n private ctx: RenderContext | undefined\n private target: Element | null = null\n private cleanups: Cleanup[] = []\n private frame: number | undefined\n private previousFocus: Element | null = null\n /** Set once per step after the sheet has scrolled the target clear. */\n private sheetAdjusted = false\n private connector: Connector | undefined\n /** Loaded on first use: connector styles cost nothing for tours that never use them. */\n private connectorModule: typeof import('./connector') | undefined\n private connectorLoading: Promise<void> | undefined\n /** Arrow, spotlight and overlay settings for the current step. */\n private look: Look = DEFAULT_LOOK\n /** Until then the step's own transition runs; scroll updates may animate. */\n private settleUntil = 0\n /** Play the connector draw-in on its next render. */\n private drawConnector = false\n private trackingFrame: number | undefined\n\n constructor(options: DomRendererOptions = {}) {\n this.options = options\n this.doc = options.document ?? document\n }\n\n // -------------------------------------------------------------------------\n // Renderer contract\n // -------------------------------------------------------------------------\n\n hasTarget(target: Target): boolean {\n return resolveTarget(target, this.doc) !== null\n }\n\n async waitForTarget(target: Target, timeoutMs: number, signal: AbortSignal): Promise<boolean> {\n return (await waitForTarget(target, timeoutMs, signal, this.doc)) !== null\n }\n\n currentRoute(): string {\n const { pathname, search } = this.doc.defaultView?.location ?? { pathname: '/', search: '' }\n return `${pathname}${search}`\n }\n\n show(ctx: RenderContext): void {\n const firstStep = !this.host\n const host = this.mount()\n // Where the previous step's popover sat, so the new one glides from there\n // alongside the spotlight instead of vanishing and fading back in.\n const from = this.popover?.style.transform || null\n this.teardownStep()\n this.ctx = ctx\n this.target = ctx.step.target === undefined ? null : resolveTarget(ctx.step.target, this.doc)\n\n const template = this.template(ctx)\n applyTheme(host, mergeThemes(this.options.theme, template?.theme, ctx.tour.options?.theme))\n this.setTemplateCss(template?.css)\n this.applyLook(host, this.resolveLook(ctx, template))\n this.settleUntil = performance.now() + this.duration(host) * 1.5\n this.drawConnector = true\n\n const initialFocus = this.options.headless\n ? this.buildHeadless(ctx, host, this.options.headless)\n : this.buildDefault(ctx, host, template)\n if (this.popover && from) {\n this.popover.style.transform = from\n this.popover.setAttribute('data-moving', '')\n } else {\n this.popover?.setAttribute('data-entering', '')\n }\n\n if (this.target) {\n const smooth = this.scrollIntoView(this.target, ctx.step)\n if (this.options.avoidOcclusion !== false) {\n const target = this.target\n this.afterScroll(smooth, target, () => {\n if (this.target === target && uncover(target, host, this.viewport())) this.update()\n })\n }\n }\n this.update()\n this.listen()\n this.wireAdvance(ctx.step)\n\n if (firstStep) this.previousFocus = this.doc.activeElement\n requestAnimationFrame(() => {\n this.popover?.removeAttribute('data-entering')\n initialFocus.focus({ preventScroll: true })\n })\n }\n\n hide(): void {\n this.teardownStep()\n if (this.host) {\n this.host.remove()\n this.host = undefined\n this.shadow = undefined\n this.overlay = undefined\n this.connector = undefined\n this.templateStyle = undefined\n }\n const prev = this.previousFocus\n this.previousFocus = null\n if (prev instanceof HTMLElement && prev.isConnected) prev.focus({ preventScroll: true })\n }\n\n // -------------------------------------------------------------------------\n // Layout\n // -------------------------------------------------------------------------\n\n /**\n * Re-measure and re-position everything. Safe to call often. `tracking`\n * marks updates caused by scroll or resize: once the step's own transition\n * has finished, those follow the target instantly instead of trailing it.\n */\n update(tracking = false): void {\n const ctx = this.ctx\n const overlay = this.overlay\n const popover = this.popover\n const win = this.doc.defaultView\n if (!ctx || !overlay || !popover || !win) return\n if (tracking && performance.now() > this.settleUntil) this.markTracking()\n\n const viewport = this.viewport()\n const overlaySize = { width: overlay.el.offsetWidth, height: overlay.el.offsetHeight }\n const spotlight = this.look.spotlight\n const padding = spotlight.padding ?? 8\n const radius = spotlight.radius ?? 10\n const shape = spotlight.shape ?? 'rounded'\n const external = this.headlessContainer\n const sheet = this.isSheet(viewport)\n popover.classList.toggle('sheet', sheet)\n popover.style.width = sheet ? `${viewport.width}px` : ''\n const floating = { width: popover.offsetWidth, height: popover.offsetHeight }\n\n if (sheet) {\n const rect = this.target?.isConnected ? toRect(this.target.getBoundingClientRect()) : null\n overlay.update(\n overlaySize,\n { target: rect, padding, radius, shape },\n this.blocksInteraction(ctx.step),\n )\n this.connector?.clear()\n const vx = viewport.x ?? 0\n const top = (viewport.y ?? 0) + viewport.height - floating.height\n popover.style.transform = `translate(${vx}px, ${top}px)`\n popover.setAttribute('data-side', 'sheet')\n external?.setAttribute('data-side', 'sheet')\n this.keepClearOfSheet(rect, top)\n return\n }\n\n if (!this.target?.isConnected) {\n overlay.update(overlaySize, { target: null, padding, radius }, false)\n this.connector?.clear()\n const { x, y } = centerPosition(floating, viewport)\n popover.style.transform = `translate(${x}px, ${y}px)`\n popover.setAttribute('data-side', 'center')\n external?.setAttribute('data-side', 'center')\n return\n }\n\n const rect = toRect(this.target.getBoundingClientRect())\n overlay.update(\n overlaySize,\n { target: rect, padding, radius, shape },\n this.blocksInteraction(ctx.step),\n )\n const hole = overlay.hole ?? rect\n const pos = computePosition({\n anchor: clipToViewport(hole, viewport),\n floating,\n viewport,\n placement: ctx.step.placement ?? 'auto',\n gap: this.options.gap ?? arrowGap(this.look.arrow),\n })\n popover.style.transform = `translate(${pos.x}px, ${pos.y}px)`\n popover.setAttribute('data-side', pos.side)\n if (this.arrow) {\n const vertical = pos.side === 'top' || pos.side === 'bottom'\n this.arrow.style.left = vertical ? `${pos.arrow - 6}px` : ''\n this.arrow.style.top = vertical ? '' : `${pos.arrow - 6}px`\n }\n if (external) {\n external.setAttribute('data-side', pos.side)\n external.style.setProperty('--docent-arrow', `${pos.arrow}px`)\n }\n this.renderConnector(pos, floating, hole)\n }\n\n /** Draw the connector for connector arrow styles; clear it otherwise. */\n private renderConnector(\n pos: { x: number; y: number; side: string; arrow: number },\n floating: { width: number; height: number },\n hole: Rect,\n ): void {\n const style = this.look.arrow\n if (!isConnector(style)) {\n this.connector?.clear()\n return\n }\n const mod = this.connectorModule\n const connector = this.connector\n if (!mod || !connector) {\n this.loadConnector()\n return\n }\n const inset = 6\n const clampX = (x: number) => Math.min(Math.max(x, hole.x + 10), hole.x + hole.width - 10)\n const clampY = (y: number) => Math.min(Math.max(y, hole.y + 10), hole.y + hole.height - 10)\n const cx = hole.x + hole.width / 2\n const cy = hole.y + hole.height / 2\n // Leave from 30% or 70% along the edge (away from the target's centre) so the\n // connector runs diagonally and each style reads distinctly.\n const alongX = pos.x + floating.width * (cx < pos.x + floating.width / 2 ? 0.3 : 0.7)\n const alongY = pos.y + floating.height * (cy < pos.y + floating.height / 2 ? 0.3 : 0.7)\n let from: Point\n let to: Point\n switch (pos.side) {\n case 'bottom':\n from = { x: alongX, y: pos.y }\n to = { x: clampX(cx), y: hole.y + hole.height + inset }\n break\n case 'top':\n from = { x: alongX, y: pos.y + floating.height }\n to = { x: clampX(cx), y: hole.y - inset }\n break\n case 'right':\n from = { x: pos.x, y: alongY }\n to = { x: hole.x + hole.width + inset, y: clampY(cy) }\n break\n default:\n from = { x: pos.x + floating.width, y: alongY }\n to = { x: hole.x - inset, y: clampY(cy) }\n }\n // Bow curves outward, away from the popover's middle.\n const bend =\n pos.side === 'top' || pos.side === 'bottom'\n ? to.x < from.x\n ? 1\n : -1\n : to.y < from.y\n ? -1\n : 1\n connector.render(\n mod.connectorShape(style, from, to, pos.side === 'top' || pos.side === 'left' ? -bend : bend),\n this.drawConnector,\n )\n this.drawConnector = false\n }\n\n /** Fetch the connector module once, then draw with it. */\n private loadConnector(): void {\n this.connectorLoading ??= import('./connector').then((mod) => {\n this.connectorModule = mod\n if (this.shadow) this.attachConnector(this.shadow, mod)\n this.update()\n })\n }\n\n /** Add the connector layer and its styles, beneath any popover. */\n private attachConnector(shadow: ShadowRoot, mod: typeof import('./connector')): void {\n if (this.connector) return\n const style = this.doc.createElement('style')\n style.textContent = mod.CONNECTOR_STYLES_CSS\n this.connector = new mod.Connector(this.doc)\n const before = this.popover ?? null\n shadow.insertBefore(style, before)\n shadow.insertBefore(this.connector.el, before)\n }\n\n private resolveLook(ctx: RenderContext, template: PopoverTemplate | undefined): Look {\n const tour = ctx.tour.options ?? {}\n const step = ctx.step\n return {\n arrow: step.arrow ?? tour.arrow ?? template?.arrow ?? this.options.arrow ?? 'caret',\n spotlight: {\n ...this.options.spotlight,\n ...template?.spotlight,\n ...tour.spotlight,\n ...step.spotlight,\n },\n overlay: { ...this.options.overlay, ...template?.overlay, ...tour.overlay, ...step.overlay },\n }\n }\n\n /** Expose the look to the stylesheet as host attributes and variables. */\n private applyLook(host: HTMLElement, look: Look): void {\n this.look = look\n host.setAttribute('data-arrow', look.arrow)\n host.setAttribute('data-ring', look.spotlight.ring ?? 'hairline')\n host.setAttribute('data-shape', look.spotlight.shape ?? 'rounded')\n host.setAttribute('data-overlay', look.overlay.style ?? 'dim')\n const { color, opacity, blur } = look.overlay\n if (color !== undefined) host.style.setProperty('--docent-overlay', color)\n if (opacity !== undefined) host.style.setProperty('--docent-overlay-opacity', String(opacity))\n if (blur !== undefined) host.style.setProperty('--docent-blur', `${blur}px`)\n else host.style.removeProperty('--docent-blur')\n }\n\n /** The current transition duration in ms, from the --docent-duration token. */\n private duration(host: HTMLElement): number {\n const raw =\n this.doc.defaultView?.getComputedStyle(host).getPropertyValue('--docent-duration').trim() ??\n ''\n const n = Number.parseFloat(raw)\n if (Number.isNaN(n)) return 220\n return raw.endsWith('ms') ? n : n * 1000\n }\n\n /** Disable transitions for this frame so scroll-driven moves stay glued to the target. */\n private markTracking(): void {\n const host = this.host\n if (!host) return\n host.setAttribute('data-tracking', '')\n if (this.trackingFrame !== undefined) cancelAnimationFrame(this.trackingFrame)\n this.trackingFrame = requestAnimationFrame(() => {\n this.trackingFrame = undefined\n host.removeAttribute('data-tracking')\n })\n }\n\n /**\n * The visible area in layout-viewport coordinates. Uses the visual viewport\n * so pinch zoom, the on-screen keyboard and pages that overflow on mobile\n * (where `innerWidth` grows past the screen) all position correctly.\n */\n private viewport(): Viewport {\n const win = this.doc.defaultView\n const vv = win?.visualViewport\n if (vv) return { x: vv.offsetLeft, y: vv.offsetTop, width: vv.width, height: vv.height }\n const el = this.doc.documentElement\n return { x: 0, y: 0, width: el.clientWidth, height: el.clientHeight }\n }\n\n private isSheet(viewport: Viewport): boolean {\n const breakpoint = this.options.sheetBreakpoint ?? 480\n return breakpoint > 0 && viewport.width < breakpoint\n }\n\n /** In sheet mode, scroll once so the target is not hidden behind the sheet. */\n private keepClearOfSheet(target: Rect | null, sheetTop: number): void {\n const win = this.doc.defaultView\n if (!target || !win || this.sheetAdjusted) return\n const overlap = target.y + target.height - sheetTop\n if (overlap <= 0) return\n this.sheetAdjusted = true\n win.scrollBy({ top: overlap + 16, behavior: 'auto' })\n }\n\n /**\n * Run once a smooth scroll has settled, or right away for instant scrolls.\n * Settled means the target stopped moving for two frames' worth of samples,\n * not a fixed delay: smooth scrolls take longer on slow or busy devices.\n * `scrollend` finishes early where supported; a cap keeps it bounded.\n */\n private afterScroll(smooth: boolean, target: Element, fn: () => void): void {\n const win = this.doc.defaultView\n if (!smooth || !win) {\n fn()\n return\n }\n let done = false\n let lastTop = Number.NaN\n let stableSamples = 0\n const stop = () => {\n done = true\n win.removeEventListener('scrollend', finish)\n clearInterval(poll)\n clearTimeout(cap)\n }\n const finish = () => {\n if (done) return\n stop()\n fn()\n }\n const poll = setInterval(() => {\n const top = target.getBoundingClientRect().top\n stableSamples = Math.abs(top - lastTop) < 0.5 ? stableSamples + 1 : 0\n lastTop = top\n if (stableSamples >= 2) finish()\n }, 80)\n const cap = setTimeout(finish, 3000)\n win.addEventListener('scrollend', finish, { once: true })\n this.cleanups.push(stop)\n }\n\n // -------------------------------------------------------------------------\n // Popover construction\n // -------------------------------------------------------------------------\n\n private template(ctx: RenderContext): PopoverTemplate | undefined {\n const name = ctx.tour.options?.template ?? this.options.template\n return name === undefined ? undefined : this.options.templates?.[name]\n }\n\n private buildDefault(\n ctx: RenderContext,\n host: HTMLElement,\n template: PopoverTemplate | undefined,\n ): HTMLElement {\n const slots: PopoverSlots = { ...this.options.slots, ...template?.slots }\n const { el, arrow, initialFocus, slotted } = buildPopover(\n this.doc,\n ctx,\n this.options.labels ?? {},\n slots,\n )\n this.popover = el\n this.arrow = arrow\n for (const node of slotted) {\n host.appendChild(node)\n this.cleanups.push(() => node.remove())\n }\n this.shadow?.appendChild(el)\n return initialFocus\n }\n\n private buildHeadless(\n ctx: RenderContext,\n host: HTMLElement,\n headless: HeadlessPopover,\n ): HTMLElement {\n const { el, arrow } = buildHeadlessShell(this.doc)\n this.popover = el\n this.arrow = arrow\n this.shadow?.appendChild(el)\n\n const container = this.doc.createElement('div')\n container.setAttribute('slot', 'popover')\n container.setAttribute('data-docent-popover', '')\n container.setAttribute('role', 'dialog')\n container.tabIndex = -1\n host.appendChild(container)\n this.headlessContainer = container\n const cleanup = headless.render(ctx, container)\n this.cleanups.push(() => {\n cleanup?.()\n container.remove()\n this.headlessContainer = undefined\n })\n return container\n }\n\n private setTemplateCss(css: string | undefined): void {\n if (!this.shadow) return\n if (!css) {\n this.templateStyle?.remove()\n this.templateStyle = undefined\n return\n }\n if (!this.templateStyle) {\n this.templateStyle = this.doc.createElement('style')\n this.shadow.appendChild(this.templateStyle)\n }\n if (this.templateStyle.textContent !== css) this.templateStyle.textContent = css\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private mount(): HTMLDivElement {\n if (this.host) return this.host\n const host = this.doc.createElement('div')\n host.setAttribute('data-docent-host', '')\n const shadow = host.attachShadow({ mode: 'open' })\n const style = this.doc.createElement('style')\n style.textContent = this.options.css ? `${STYLES}\\n${this.options.css}` : STYLES\n shadow.appendChild(style)\n const overlay = new Overlay(this.doc)\n shadow.appendChild(overlay.el)\n shadow.appendChild(overlay.ring)\n shadow.appendChild(overlay.blocker)\n if (this.connectorModule) this.attachConnector(shadow, this.connectorModule)\n this.doc.body.appendChild(host)\n this.host = host\n this.shadow = shadow\n this.overlay = overlay\n return host\n }\n\n private teardownStep(): void {\n for (const c of this.cleanups) c()\n this.cleanups = []\n if (this.frame !== undefined) cancelAnimationFrame(this.frame)\n this.frame = undefined\n this.popover?.remove()\n this.popover = undefined\n this.connector?.clear()\n this.arrow = undefined\n this.ctx = undefined\n this.target = null\n this.sheetAdjusted = false\n }\n\n private blocksInteraction(step: Step): boolean {\n if (step.interaction) return step.interaction === 'block'\n const advance = step.advance\n return !(typeof advance === 'object' && (advance.on === 'click' || advance.on === 'input'))\n }\n\n /** Returns true when a smooth scroll was started (callers must wait for it to settle). */\n private scrollIntoView(el: Element, step: Step): boolean {\n const scroll = { ...this.ctx?.tour.options?.scroll, ...step.scroll }\n if (scroll.enabled === false) return false\n const r = el.getBoundingClientRect()\n const v = this.viewport()\n const vx = v.x ?? 0\n const vy = v.y ?? 0\n const behavior = scroll.behavior ?? 'auto'\n if (r.height > v.height || r.width > v.width) {\n // Oversized target: it can never be fully shown, so only make sure its top is on screen.\n const topVisible = r.top >= vy && r.top < vy + v.height && r.left < vx + v.width\n if (!topVisible) el.scrollIntoView({ block: 'start', inline: 'start', behavior })\n return !topVisible && behavior === 'smooth'\n }\n const visible =\n r.top >= vy && r.left >= vx && r.bottom <= vy + v.height && r.right <= vx + v.width\n if (visible) return false\n el.scrollIntoView({ block: scroll.block ?? 'center', inline: 'nearest', behavior })\n return behavior === 'smooth'\n }\n\n private scheduleUpdate = (): void => {\n if (this.frame !== undefined) return\n this.frame = requestAnimationFrame(() => {\n this.frame = undefined\n this.update(true)\n })\n }\n\n private listen(): void {\n const win = this.doc.defaultView\n const ctx = this.ctx\n if (!win || !ctx) return\n const on = <K extends keyof WindowEventMap>(\n type: K,\n handler: (e: WindowEventMap[K]) => void,\n opts?: AddEventListenerOptions,\n ) => {\n win.addEventListener(type, handler, opts)\n this.cleanups.push(() => win.removeEventListener(type, handler, opts))\n }\n\n on('scroll', this.scheduleUpdate, { capture: true, passive: true })\n on('resize', this.scheduleUpdate, { passive: true })\n const vv = win.visualViewport\n if (vv) {\n vv.addEventListener('resize', this.scheduleUpdate)\n vv.addEventListener('scroll', this.scheduleUpdate)\n this.cleanups.push(() => {\n vv.removeEventListener('resize', this.scheduleUpdate)\n vv.removeEventListener('scroll', this.scheduleUpdate)\n })\n }\n if (typeof ResizeObserver !== 'undefined') {\n const ro = new ResizeObserver(this.scheduleUpdate)\n if (this.target) ro.observe(this.target)\n ro.observe(this.doc.documentElement)\n if (this.popover) ro.observe(this.popover)\n if (this.headlessContainer) ro.observe(this.headlessContainer)\n this.cleanups.push(() => ro.disconnect())\n }\n\n const options = ctx.tour.options ?? {}\n on('keydown', (e) => this.onKeydown(e, ctx), { capture: true })\n\n if (options.closeOnOverlayClick && this.overlay) {\n const overlayEl = this.overlay.el\n const handler = () => ctx.actions.skip()\n overlayEl.addEventListener('click', handler)\n this.cleanups.push(() => overlayEl.removeEventListener('click', handler))\n }\n }\n\n private onKeydown(e: KeyboardEvent, ctx: RenderContext): void {\n const options = ctx.tour.options ?? {}\n // The real origin, even inside shadow roots (where `e.target` is retargeted to the host).\n const path = typeof e.composedPath === 'function' ? e.composedPath() : []\n const origin = (path[0] ?? e.target) as Element | null\n // Elements marked `data-docent-ignore-keys` (e.g. the devtools panel) keep their keys.\n if (path.some((n) => n instanceof Element && n.hasAttribute('data-docent-ignore-keys'))) return\n if (e.key === 'Escape' && options.allowClose !== false) {\n e.preventDefault()\n ctx.actions.skip()\n return\n }\n if (e.key === 'Tab') {\n this.trapTab(e)\n return\n }\n if (options.keyboard === false) return\n const inField =\n origin instanceof HTMLElement &&\n (/^(INPUT|TEXTAREA|SELECT)$/.test(origin.tagName) || origin.isContentEditable)\n if (inField) return\n if (e.key === 'ArrowRight' && ctx.step.buttons?.next !== false) {\n e.preventDefault()\n ctx.actions.next()\n } else if (e.key === 'ArrowLeft' && ctx.canGoBack && ctx.step.buttons?.back !== false) {\n e.preventDefault()\n ctx.actions.back()\n }\n }\n\n /** Keep Tab cycling inside the popover when focus is already in it. */\n private trapTab(e: KeyboardEvent): void {\n const scope = this.headlessContainer ?? this.popover\n if (!scope) return\n const active = this.headlessContainer ? this.doc.activeElement : this.shadow?.activeElement\n const inside = active && (scope.contains(active) || this.host?.contains(active))\n if (!active || !inside) return\n // Slotted light-DOM controls are children of the host; include them in the cycle.\n const roots: ParentNode[] = this.headlessContainer\n ? [scope]\n : [scope, ...(this.host ? [this.host] : [])]\n const items = roots.flatMap((r) => Array.from(r.querySelectorAll<HTMLElement>(FOCUSABLE)))\n if (items.length === 0) return\n const first = items[0] as HTMLElement\n const last = items[items.length - 1] as HTMLElement\n if (e.shiftKey && active === first) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && active === last) {\n e.preventDefault()\n first.focus()\n }\n }\n\n private wireAdvance(step: Step): void {\n const advance = step.advance\n const ctx = this.ctx\n if (!ctx || typeof advance !== 'object') return\n if (advance.on !== 'click' && advance.on !== 'input') return\n const el = advance.target === undefined ? this.target : resolveTarget(advance.target, this.doc)\n if (!el) return\n\n if (advance.on === 'click') {\n const handler = () => ctx.actions.next()\n el.addEventListener('click', handler, { once: true })\n this.cleanups.push(() => el.removeEventListener('click', handler))\n return\n }\n\n const pattern = advance.match ? new RegExp(advance.match) : /.+/\n const handler = (e: Event) => {\n const value = (e.target as HTMLInputElement | HTMLTextAreaElement).value ?? ''\n if (pattern.test(value)) ctx.actions.next()\n }\n el.addEventListener('input', handler)\n this.cleanups.push(() => el.removeEventListener('input', handler))\n }\n}\n\nfunction toRect(r: DOMRect): Rect {\n return { x: r.left, y: r.top, width: r.width, height: r.height }\n}\n","import { createMemoryStorage, type StorageAdapter } from '@docentjs/core'\n\n/**\n * `localStorage`-backed adapter. Falls back to memory when storage is\n * unavailable (private mode, blocked cookies, SSR).\n */\nexport function createLocalStorage(storage?: Storage): StorageAdapter {\n let backing: Storage\n try {\n backing = storage ?? globalThis.localStorage\n const probe = '__docent__'\n backing.setItem(probe, '1')\n backing.removeItem(probe)\n } catch {\n return createMemoryStorage()\n }\n const guard = <T>(fn: () => T, fallback: T): T => {\n try {\n return fn()\n } catch {\n return fallback\n }\n }\n return {\n get: (key) => guard(() => backing.getItem(key), null),\n set: (key, value) => guard(() => backing.setItem(key, value), undefined),\n remove: (key) => guard(() => backing.removeItem(key), undefined),\n }\n}\n","import { type ControllerOptions, type Tour, TourController } from '@docentjs/core'\nimport { DomRenderer, type DomRendererOptions } from './renderer'\nimport { createLocalStorage } from './storage'\n\nexport interface CreateTourOptions extends Omit<ControllerOptions, 'tour' | 'renderer'> {\n renderer?: DomRendererOptions\n /** Follow browser navigation to pause and resume route-bound steps. Default true. */\n followRoutes?: boolean\n}\n\n/**\n * A controller pre-wired for the browser: DOM renderer, localStorage\n * persistence and route change tracking.\n */\nexport class DomTourController extends TourController {\n private readonly cleanups: Array<() => void> = []\n private readonly followRoutes: boolean\n\n constructor(tour: Tour, options: CreateTourOptions = {}) {\n const { renderer: rendererOptions, followRoutes, ...rest } = options\n const renderer = new DomRenderer(rendererOptions)\n super({ ...rest, tour, renderer, storage: rest.storage ?? createLocalStorage() })\n // Listeners attach on start, not here, so constructing has no side effects\n // and a destroyed controller can start again (React StrictMode).\n this.followRoutes = followRoutes !== false\n }\n\n override async start(at?: number | string): Promise<void> {\n this.listenToRoutes()\n return super.start(at)\n }\n\n override async destroy(): Promise<void> {\n for (const c of this.cleanups) c()\n this.cleanups.length = 0\n await super.destroy()\n }\n\n private listenToRoutes(): void {\n if (!this.followRoutes || this.cleanups.length > 0 || typeof window === 'undefined') return\n const onChange = () => void this.routeChanged()\n for (const type of ['popstate', 'hashchange']) {\n window.addEventListener(type, onChange)\n this.cleanups.push(() => window.removeEventListener(type, onChange))\n }\n const nav = (window as { navigation?: EventTarget }).navigation\n if (nav) {\n nav.addEventListener('navigatesuccess', onChange)\n this.cleanups.push(() => nav.removeEventListener('navigatesuccess', onChange))\n }\n }\n}\n\n/** Create a browser-ready tour. Call `.start()` or `.resume()` on the result. */\nexport function createTour(tour: Tour, options?: CreateTourOptions): DomTourController {\n return new DomTourController(tour, options)\n}\n","/**\n * Browser implementation of the manager's environment: routes from `location`\n * and navigation events, element presence from the DOM.\n */\n\nimport type { DocentEnvironment, Target } from '@docentjs/core'\nimport { resolveTarget } from './target'\n\nexport function createDomEnvironment(doc: Document = document): DocentEnvironment {\n const win = doc.defaultView\n return {\n currentRoute() {\n const loc = win?.location\n return loc ? `${loc.pathname}${loc.search}` : '/'\n },\n\n onRouteChange(listener) {\n if (!win) return () => {}\n const cleanups: Array<() => void> = []\n for (const type of ['popstate', 'hashchange'] as const) {\n win.addEventListener(type, listener)\n cleanups.push(() => win.removeEventListener(type, listener))\n }\n const nav = (win as { navigation?: EventTarget }).navigation\n if (nav) {\n nav.addEventListener('navigatesuccess', listener)\n cleanups.push(() => nav.removeEventListener('navigatesuccess', listener))\n }\n return () => {\n for (const c of cleanups) c()\n }\n },\n\n hasTarget: (target: Target) => resolveTarget(target, doc) !== null,\n\n watchTarget(target, listener) {\n let present = resolveTarget(target, doc) !== null\n if (present) listener()\n let scheduled = false\n const check = () => {\n scheduled = false\n const now = resolveTarget(target, doc) !== null\n if (now && !present) listener()\n present = now\n }\n const observer = new MutationObserver(() => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(check)\n })\n observer.observe(doc.documentElement, { childList: true, subtree: true, attributes: true })\n return () => observer.disconnect()\n },\n }\n}\n","import { Docent, type DocentOptions } from '@docentjs/core'\nimport { DomTourController } from './create'\nimport { createDomEnvironment } from './environment'\nimport type { DomRendererOptions } from './renderer'\nimport { createLocalStorage } from './storage'\n\nexport interface CreateDocentOptions\n extends Omit<DocentOptions, 'environment' | 'createController'> {\n /** Renderer options shared by every tour: theme, templates, slots, headless, labels. */\n renderer?: DomRendererOptions\n /** Document to watch and render into. Defaults to the global document. */\n document?: Document\n}\n\n/**\n * Create the tour manager for the browser. It loads your tours, watches their\n * triggers (routes, elements, events, delays), checks conditions and frequency\n * per user, and runs at most one tour at a time.\n *\n * ```ts\n * const docent = createDocent({ tours: [welcome, invoices] })\n * docent.identify(user.id, { plan: user.plan })\n * docent.track('invoice-saved')\n * ```\n */\nexport function createDocent(options: CreateDocentOptions = {}): Docent {\n const { renderer, document: doc, ...rest } = options\n const rendererOptions: DomRendererOptions = doc ? { ...renderer, document: doc } : { ...renderer }\n return new Docent({\n ...rest,\n storage: rest.storage ?? createLocalStorage(),\n environment: createDomEnvironment(doc),\n createController: (tour, shared) =>\n new DomTourController(tour, { ...shared, renderer: rendererOptions }),\n })\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,11 @@
1
- import { Alignment, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, Placement, RenderContext, Renderer, Side, StorageAdapter, Target, TargetSpec, Theme, Tour, TourController, defineTour } from "@docentjs/core";
1
+ import { Alignment, ArrowStyle, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, OverlayOptions, Placement, RenderContext, Renderer, Side, SpotlightOptions, SpotlightShape, StorageAdapter, Target, TargetSpec, Theme, Tour, TourController, defineTour } from "@docentjs/core";
2
+ //#region src/arrows.d.ts
3
+ export declare const CONNECTOR_STYLES: readonly ["line", "dashed", "dotted", "curve", "curve-dashed", "squiggle", "loop", "elbow", "sketch", "pin"];
4
+ type ConnectorStyle = (typeof CONNECTOR_STYLES)[number];
5
+ export declare function isConnector(style: ArrowStyle): style is ConnectorStyle;
6
+ /** Space between target and popover for a style: connectors need room to be seen. */
7
+ export declare function arrowGap(style: ArrowStyle): number;
8
+ //#endregion
2
9
  //#region src/content.d.ts
3
10
  export declare function isSafeUrl(url: string): boolean;
4
11
  export declare function renderBody(doc: Document, body: string, format?: 'text' | 'markdown'): DocumentFragment;
@@ -34,6 +41,10 @@ type PopoverSlots = Partial<Record<SlotName, SlotRenderer>>;
34
41
  interface PopoverTemplate {
35
42
  theme?: Theme;
36
43
  slots?: PopoverSlots;
44
+ /** Arrow style for tours using this template. */
45
+ arrow?: ArrowStyle;
46
+ spotlight?: SpotlightOptions;
47
+ overlay?: OverlayOptions;
37
48
  /** Extra CSS injected into the shadow root while this template is active. */
38
49
  css?: string;
39
50
  }
@@ -55,11 +66,12 @@ interface DomRendererOptions {
55
66
  labels?: Labels;
56
67
  /** Distance between target and popover, in px. */
57
68
  gap?: number;
58
- /** Spotlight defaults when a tour sets none. */
59
- spotlight?: {
60
- padding?: number;
61
- radius?: number;
62
- };
69
+ /** Spotlight defaults when a tour sets none: padding, radius, shape, ring. */
70
+ spotlight?: SpotlightOptions;
71
+ /** Arrow style when a tour sets none. Default `caret`. */
72
+ arrow?: ArrowStyle;
73
+ /** Overlay defaults when a tour sets none: style, color, opacity, blur. */
74
+ overlay?: OverlayOptions;
63
75
  /** Base theme tokens. Tours and templates layer on top. */
64
76
  theme?: Theme;
65
77
  /** Replace regions of the built-in popover. */
@@ -97,14 +109,42 @@ export declare class DomRenderer implements Renderer {
97
109
  private previousFocus;
98
110
  /** Set once per step after the sheet has scrolled the target clear. */
99
111
  private sheetAdjusted;
112
+ private connector;
113
+ /** Loaded on first use: connector styles cost nothing for tours that never use them. */
114
+ private connectorModule;
115
+ private connectorLoading;
116
+ /** Arrow, spotlight and overlay settings for the current step. */
117
+ private look;
118
+ /** Until then the step's own transition runs; scroll updates may animate. */
119
+ private settleUntil;
120
+ /** Play the connector draw-in on its next render. */
121
+ private drawConnector;
122
+ private trackingFrame;
100
123
  constructor(options?: DomRendererOptions);
101
124
  hasTarget(target: Target): boolean;
102
125
  waitForTarget(target: Target, timeoutMs: number, signal: AbortSignal): Promise<boolean>;
103
126
  currentRoute(): string;
104
127
  show(ctx: RenderContext): void;
105
128
  hide(): void;
106
- /** Re-measure and re-position everything. Safe to call often. */
107
- update(): void;
129
+ /**
130
+ * Re-measure and re-position everything. Safe to call often. `tracking`
131
+ * marks updates caused by scroll or resize: once the step's own transition
132
+ * has finished, those follow the target instantly instead of trailing it.
133
+ */
134
+ update(tracking?: boolean): void;
135
+ /** Draw the connector for connector arrow styles; clear it otherwise. */
136
+ private renderConnector;
137
+ /** Fetch the connector module once, then draw with it. */
138
+ private loadConnector;
139
+ /** Add the connector layer and its styles, beneath any popover. */
140
+ private attachConnector;
141
+ private resolveLook;
142
+ /** Expose the look to the stylesheet as host attributes and variables. */
143
+ private applyLook;
144
+ /** The current transition duration in ms, from the --docent-duration token. */
145
+ private duration;
146
+ /** Disable transitions for this frame so scroll-driven moves stay glued to the target. */
147
+ private markTracking;
108
148
  /**
109
149
  * The visible area in layout-viewport coordinates. Uses the visual viewport
110
150
  * so pinch zoom, the on-screen keyboard and pages that overflow on mobile
@@ -263,15 +303,22 @@ interface OverlayUpdate {
263
303
  target: Rect | null;
264
304
  padding: number;
265
305
  radius: number;
306
+ shape?: SpotlightShape;
266
307
  }
267
308
  export declare class Overlay {
268
309
  readonly el: HTMLDivElement;
269
310
  readonly blocker: HTMLDivElement;
311
+ /** Hairline of light around the cutout. */
312
+ readonly ring: HTMLDivElement;
270
313
  private lastHole;
271
314
  constructor(doc: Document);
315
+ /** Move the ring to a rect; a zero-size rect collapses it (modal steps). */
316
+ private placeRing;
272
317
  /** Current hole, padded, in viewport coordinates. */
273
318
  get hole(): Rect | null;
274
- update(viewport: Size, { target, padding, radius }: OverlayUpdate, block: boolean): void;
319
+ update(viewport: Size, { target, padding, radius, shape }: OverlayUpdate, block: boolean): void;
320
+ /** Exposed for the vignette style, which is centred on the cutout. */
321
+ private setCentre;
275
322
  }
276
323
  //#endregion
277
324
  //#region src/popover.d.ts
@@ -320,5 +367,5 @@ export declare function resolveTarget(target: Target, root?: QueryRoot): Element
320
367
  */
321
368
  export declare function waitForTarget(target: Target, timeoutMs: number, signal?: AbortSignal, root?: QueryRoot): Promise<Element | null>;
322
369
  //#endregion
323
- export { type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
370
+ export { type ConnectorStyle, type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
324
371
  //# sourceMappingURL=index.d.cts.map