v0.1.0
First tagged release. pencere is a modern, accessible, framework-agnostic
lightbox — pure TypeScript, zero runtime dependencies, ESM, tree-shakeable.
Live demo: pencere.productdevbook.com
npm install pencereHighlights
- Core engine — typed event emitter,
Pencere<T>state machine,next/prev/goTo/open/close, optional looping. - Renderers — first-class image,
<video>, sandboxed<iframe>, and a user-extensibleRendererregistry (#8) for custom item types. - View Transitions API morph (#12) — pass the clicked thumbnail as the
triggerand the UA animates thumb → lightbox natively. Symmetric fade on close. - Hash-based deep linking (#75) —
/page#p3opens slide 3 on reload; browser Back + Safari / Firefox edge-swipe dismiss viapopstate. - Fullscreen API (#14) — real
requestFullscreenwhere supported, CSS faux-fullscreen fallback on iOS Safari. - Declarative DOM scanner (#7) —
bindPencere("[data-pencere]")wires<a data-pencere>anchors into a grouped gallery with zero JS glue. - Lifecycle hooks (Phase 2) —
willOpen,didOpen,willClose,didClose,willRender,didRender,didNavigate.will*is awaited and may abort the transition. - Plugin architecture (#4) — narrow
PencereContext { core, events, dom, registerHook, registerRenderer }. Includes a referenceslideshowPlugin({ intervalMs, autoStart, pauseOnHover }). - Controlled mode (#6) —
new Pencere({ controlled: true })emitsrequestOpen/requestChange/requestClose; consumer commits state viacommitOpen/commitChange/commitClose. Drop-in for React / Vue router sync. - ImageLoader DI (#9) —
interface ImageLoader { load(item, signal, options) }lets you inject CDN signing, blur-up previews, service-worker caching, or a custom AVIF fallback.
Gestures & keyboard
- Pinch, wheel, double-tap zoom (1×–8×), pan once zoomed.
- Swipe left/right to navigate at fit scale; swipe down to dismiss with backdrop fade.
- Full keyboard map (Arrow, Home/End, +/-/0, Esc) with IME-safe composition guard.
- WCAG 2.5.7 arrow-key pan alternative while zoomed (#25).
- Opt-in haptic feedback on coarse pointers.
Accessibility (WCAG 2.2 AA)
- APG Dialog + Carousel patterns, focus trap with shadow-DOM-aware tabbable detection.
- 44×44 min targets,
prefers-reduced-motionhonored,forced-colorsmapping, live-region announcements. ImageItem.longDescriptionwired toaria-describedby(#26), per-slidelangfont stacks (#65).
Security
- URL protocol allowlist — rejects
javascript:,vbscript:,file:,data:text/html,data:image/svg+xml(script-bearing SVG). Raster-onlydata:images pass. textContentfor captions by default; opt into HTML via the Trusted Types helper.- iframe renderer sets
sandboxbeforesrc, strict referrer policy everywhere. - npm releases published with OIDC
--provenancefrom GitHub Actions. Verify withnpm audit signatures pencere. - OSSF Scorecard workflow, Dependabot, SHA-pinned actions.
Adapters
Sub-path exports: pencere/react, pencere/vue, pencere/svelte, pencere/solid, pencere/element. All SSR-safe: no document / window access at import time.
Refactor + bug hunt
Architecture Phase 1 — viewer.ts decomposed from a 1003-LOC god file into five focused controllers: routing-controller, fullscreen-controller, view-transition-controller, motion-controller, render-pipeline. Three rounds of parallel bug hunts (concurrency, security, async races, real-browser smoke test) landed 29 fixes before this tag.