diff --git a/simulator/static/flash.js b/simulator/static/flash.js new file mode 100644 index 0000000..38ac605 --- /dev/null +++ b/simulator/static/flash.js @@ -0,0 +1,20 @@ +// Pure photosensitivity helper. WCAG 2.3.1: no more than 3 general flashes +// (luminance transitions) per second. Given a transition COUNT, returns the +// minimum total duration that keeps the rate at or below 3/sec, and a clamp +// that only ever slows a transition down. UMD: browser `HEFFlash` + require(). +(function (root, factory) { + const api = factory(); + if (typeof module !== "undefined" && module.exports) module.exports = api; + else root.HEFFlash = api; +})(typeof self !== "undefined" ? self : this, function () { + "use strict"; + const MAX_PER_SEC = 3; + function minSafeDurationMs(count) { + const n = Math.max(0, Number(count) || 0); + return (n / MAX_PER_SEC) * 1000; + } + function clampDurationMs(requestedMs, count) { + return Math.max(Number(requestedMs) || 0, minSafeDurationMs(count)); + } + return { MAX_PER_SEC, minSafeDurationMs, clampDurationMs }; +}); diff --git a/simulator/static/flash.test.js b/simulator/static/flash.test.js new file mode 100644 index 0000000..72f1188 --- /dev/null +++ b/simulator/static/flash.test.js @@ -0,0 +1,16 @@ +const test = require("node:test"); +const assert = require("node:assert"); +const F = require("./flash.js"); + +test("minSafeDurationMs: N transitions need N/3 seconds", () => { + assert.strictEqual(F.minSafeDurationMs(3), 1000); // 3 flashes in >=1s + assert.strictEqual(F.minSafeDurationMs(6), 2000); + assert.strictEqual(F.minSafeDurationMs(0), 0); + assert.strictEqual(F.minSafeDurationMs(1), 1000 / 3); +}); + +test("clampDurationMs: stretches only when too fast", () => { + assert.strictEqual(F.clampDurationMs(2000, 3), 2000); // already safe + assert.strictEqual(F.clampDurationMs(200, 3), 1000); // too fast -> clamped up + assert.strictEqual(F.clampDurationMs(500, 1), 500); // single transition, slow enough +});