import assert from 'node:assert/strict'; import test from 'node:test'; import { buildPaneNavCss, withAlpha, type RailSite } from '../src/paneNav.ts'; const SITE: RailSite = { prefix: 'demo', rail: 'nav.sidebar', anchor: 'a.home', main: '#content', modalOpen: '.modal[open]', menuOpen: '.menu[open]', paint: { width: 72, background: 'rgb(0, 0, 0)', line: 'rgba(1, 2, 3, 0.16)', accent: 'rgb(83, 252, 24)', rtl: false }, }; test('pane CSS parks the site rail only while the html attribute is set', () => { const css = buildPaneNavCss(SITE); for (const rule of css.split('}').map(part => part.trim()).filter(Boolean)) { const selector = rule.split('{')[0]!; // Every rule is scoped: to the parked state, to our own edge element, or inside the motion query. assert.ok(/html\[data-demo-pane-nav|#demo-rail-edge|@media/.test(selector), selector); } assert.match(css, /width: 72px !important/); assert.match(css, /translateX\(-100%\)/); assert.match(css, /\[data-demo-pane-nav="peek"\]/); assert.match(css, /:is\(nav\.sidebar, \[data-demo-rail\]\) ~ #content/); assert.match(css, /background: rgb\(83, 252, 24\)/); }); test('RTL: the rail parks and slides in on the right', () => { const css = buildPaneNavCss(SITE, { ...SITE.paint, rtl: true }); assert.match(css, /right: 0 !important; left: auto !important/); assert.match(css, /translateX\(100%\)/); assert.doesNotMatch(css, /translateX\(-100%\)/); assert.match(css, /#demo-rail-edge \{ position: fixed; right: 0/); }); test('withAlpha keeps the channels and swaps the alpha', () => { assert.equal(withAlpha('rgb(231, 233, 234)', 0.16), 'rgba(231, 233, 234, 0.16)'); assert.equal(withAlpha('rgba(15, 20, 25, 1)', 0.5), 'rgba(15, 20, 25, 0.5)'); assert.equal(withAlpha('', 0.2), 'rgba(128, 128, 128, 0.2)'); });