accessify-widget 0.1.0 → 0.2.1

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.
Files changed (38) hide show
  1. package/README.md +57 -3
  2. package/dist/accessify.min.js +1 -1
  3. package/dist/accessify.min.js.map +1 -1
  4. package/dist/accessify.mjs +1 -1
  5. package/dist/{alt-text-CLxbmwG6.js → alt-text-CgzNGvdT.js} +2 -2
  6. package/dist/{alt-text-CLxbmwG6.js.map → alt-text-CgzNGvdT.js.map} +1 -1
  7. package/dist/contrast-CqsICAkU.js +139 -0
  8. package/dist/contrast-CqsICAkU.js.map +1 -0
  9. package/dist/{index-CUQfpnwR.js → index-qmiN2JAz.js} +1811 -736
  10. package/dist/index-qmiN2JAz.js.map +1 -0
  11. package/dist/{keyboard-nav-BdPyLaZt.js → keyboard-nav-DH4qBThF.js} +16 -12
  12. package/dist/keyboard-nav-DH4qBThF.js.map +1 -0
  13. package/dist/{page-structure-2X8mOSpC.js → page-structure-DTBqkrYs.js} +11 -7
  14. package/dist/page-structure-DTBqkrYs.js.map +1 -0
  15. package/dist/text-size-C6OFhCGi.js +186 -0
  16. package/dist/text-size-C6OFhCGi.js.map +1 -0
  17. package/dist/widget.js +1 -1
  18. package/dist/widget.js.map +1 -1
  19. package/package.json +1 -1
  20. package/dist/color-blind-0LFng55r.js +0 -108
  21. package/dist/color-blind-0LFng55r.js.map +0 -1
  22. package/dist/contrast-DCkE0NXZ.js +0 -64
  23. package/dist/contrast-DCkE0NXZ.js.map +0 -1
  24. package/dist/dyslexia-font-wONgIy2T.js +0 -77
  25. package/dist/dyslexia-font-wONgIy2T.js.map +0 -1
  26. package/dist/index-CUQfpnwR.js.map +0 -1
  27. package/dist/keyboard-nav-BdPyLaZt.js.map +0 -1
  28. package/dist/line-height-BT98qgEF.js +0 -54
  29. package/dist/line-height-BT98qgEF.js.map +0 -1
  30. package/dist/page-structure-2X8mOSpC.js.map +0 -1
  31. package/dist/saturation-D8ZXpWAN.js +0 -59
  32. package/dist/saturation-D8ZXpWAN.js.map +0 -1
  33. package/dist/spacing-DENai3JU.js +0 -106
  34. package/dist/spacing-DENai3JU.js.map +0 -1
  35. package/dist/text-align-BDRPqPvl.js +0 -51
  36. package/dist/text-align-BDRPqPvl.js.map +0 -1
  37. package/dist/text-size-B-uv436p.js +0 -69
  38. package/dist/text-size-B-uv436p.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"keyboard-nav-BdPyLaZt.js","sources":["../src/features/keyboard-nav.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\nexport default function createKeyboardNavModule(): FeatureModule {\n let enabled = false;\n const STYLE_ID = 'accessify-keyboard-nav';\n const SKIP_LINK_ID = 'accessify-skip-link';\n const OVERLAY_ID = 'accessify-keyboard-help';\n const STORAGE_KEY = 'accessify-keyboard-nav';\n\n let headingIndex = -1;\n let landmarkIndex = -1;\n let headings: HTMLElement[] = [];\n let landmarks: HTMLElement[] = [];\n let helpOverlayVisible = false;\n\n // --- Skip-to-content link ---\n\n function findMainContent(): HTMLElement | null {\n return (\n document.querySelector('main') ||\n document.getElementById('content') ||\n document.getElementById('main-content') ||\n document.querySelector('[role=\"main\"]') ||\n document.querySelector('h1')\n );\n }\n\n function hasSkipLink(): boolean {\n const links = document.querySelectorAll('a[href^=\"#\"]');\n for (const link of links) {\n const text = (link as HTMLElement).textContent?.toLowerCase() || '';\n if (text.includes('skip') || text.includes('main content') || text.includes('navigation')) {\n return true;\n }\n }\n return false;\n }\n\n function injectSkipLink() {\n if (hasSkipLink()) return;\n const target = findMainContent();\n if (!target) return;\n\n // Ensure target has an ID for the skip link to reference\n if (!target.id) {\n target.id = 'accessify-main-content';\n }\n\n const skipLink = document.createElement('a');\n skipLink.id = SKIP_LINK_ID;\n skipLink.href = `#${target.id}`;\n skipLink.textContent = 'Skip to main content';\n skipLink.addEventListener('click', (e) => {\n e.preventDefault();\n target.setAttribute('tabindex', '-1');\n target.focus();\n target.scrollIntoView({ behavior: 'smooth', block: 'start' });\n });\n\n document.body.insertBefore(skipLink, document.body.firstChild);\n }\n\n function removeSkipLink() {\n const skipLink = document.getElementById(SKIP_LINK_ID);\n skipLink?.remove();\n }\n\n // --- Heading navigation (Alt+H) ---\n\n function collectHeadings() {\n headings = Array.from(\n document.querySelectorAll<HTMLElement>('h1, h2, h3, h4, h5, h6')\n ).filter((el) => {\n // Only visible headings\n const style = window.getComputedStyle(el);\n return style.display !== 'none' && style.visibility !== 'hidden';\n });\n }\n\n function navigateToNextHeading() {\n collectHeadings();\n if (headings.length === 0) return;\n headingIndex = (headingIndex + 1) % headings.length;\n const heading = headings[headingIndex];\n heading.setAttribute('tabindex', '-1');\n heading.focus();\n heading.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n\n // --- Landmark navigation (Alt+L) ---\n\n function collectLandmarks() {\n const selectors = [\n 'header, [role=\"banner\"]',\n 'nav, [role=\"navigation\"]',\n 'main, [role=\"main\"]',\n 'aside, [role=\"complementary\"]',\n '[role=\"search\"]',\n '[role=\"form\"]',\n 'footer, [role=\"contentinfo\"]',\n '[role=\"region\"][aria-label]',\n ];\n landmarks = Array.from(\n document.querySelectorAll<HTMLElement>(selectors.join(', '))\n ).filter((el) => {\n const style = window.getComputedStyle(el);\n return style.display !== 'none' && style.visibility !== 'hidden';\n });\n }\n\n function navigateToNextLandmark() {\n collectLandmarks();\n if (landmarks.length === 0) return;\n landmarkIndex = (landmarkIndex + 1) % landmarks.length;\n const landmark = landmarks[landmarkIndex];\n landmark.setAttribute('tabindex', '-1');\n landmark.focus();\n landmark.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n\n // --- Keyboard shortcut help overlay (Alt+K) ---\n\n function toggleHelpOverlay() {\n const existing = document.getElementById(OVERLAY_ID);\n if (existing) {\n existing.remove();\n helpOverlayVisible = false;\n return;\n }\n\n helpOverlayVisible = true;\n const overlay = document.createElement('div');\n overlay.id = OVERLAY_ID;\n overlay.setAttribute('role', 'dialog');\n overlay.setAttribute('aria-label', 'Keyboard shortcuts');\n overlay.setAttribute('aria-modal', 'true');\n\n overlay.innerHTML = `\n <div style=\"\n position: fixed; inset: 0; background: rgba(0,0,0,0.6);\n display: flex; align-items: center; justify-content: center;\n z-index: 2147483647;\n \">\n <div style=\"\n background: #fff; color: #222; border-radius: 12px; padding: 32px;\n max-width: 480px; width: 90%; max-height: 80vh; overflow-y: auto;\n box-shadow: 0 8px 32px rgba(0,0,0,0.3); font-family: system-ui, sans-serif;\n \" role=\"document\">\n <h2 style=\"margin: 0 0 16px; font-size: 20px; color: #1a73e8;\">Keyboard Shortcuts</h2>\n <table style=\"width: 100%; border-collapse: collapse; font-size: 14px;\">\n <thead>\n <tr style=\"border-bottom: 2px solid #e0e0e0;\">\n <th style=\"text-align: left; padding: 8px 12px;\">Shortcut</th>\n <th style=\"text-align: left; padding: 8px 12px;\">Action</th>\n </tr>\n </thead>\n <tbody>\n <tr style=\"border-bottom: 1px solid #f0f0f0;\">\n <td style=\"padding: 8px 12px;\"><kbd style=\"background:#f5f5f5;padding:2px 8px;border-radius:4px;border:1px solid #ccc;font-family:monospace;\">Alt + H</kbd></td>\n <td style=\"padding: 8px 12px;\">Navigate to next heading</td>\n </tr>\n <tr style=\"border-bottom: 1px solid #f0f0f0;\">\n <td style=\"padding: 8px 12px;\"><kbd style=\"background:#f5f5f5;padding:2px 8px;border-radius:4px;border:1px solid #ccc;font-family:monospace;\">Alt + L</kbd></td>\n <td style=\"padding: 8px 12px;\">Navigate to next landmark</td>\n </tr>\n <tr style=\"border-bottom: 1px solid #f0f0f0;\">\n <td style=\"padding: 8px 12px;\"><kbd style=\"background:#f5f5f5;padding:2px 8px;border-radius:4px;border:1px solid #ccc;font-family:monospace;\">Alt + K</kbd></td>\n <td style=\"padding: 8px 12px;\">Toggle this help overlay</td>\n </tr>\n <tr style=\"border-bottom: 1px solid #f0f0f0;\">\n <td style=\"padding: 8px 12px;\"><kbd style=\"background:#f5f5f5;padding:2px 8px;border-radius:4px;border:1px solid #ccc;font-family:monospace;\">Tab</kbd></td>\n <td style=\"padding: 8px 12px;\">Move to next focusable element</td>\n </tr>\n <tr>\n <td style=\"padding: 8px 12px;\"><kbd style=\"background:#f5f5f5;padding:2px 8px;border-radius:4px;border:1px solid #ccc;font-family:monospace;\">Escape</kbd></td>\n <td style=\"padding: 8px 12px;\">Close this overlay</td>\n </tr>\n </tbody>\n </table>\n <button style=\"\n margin-top: 20px; padding: 8px 24px; background: #1a73e8; color: #fff;\n border: none; border-radius: 6px; cursor: pointer; font-size: 14px;\n \" id=\"accessify-keyboard-help-close\">Close</button>\n </div>\n </div>\n `;\n\n document.body.appendChild(overlay);\n\n // Focus management for the dialog\n const closeBtn = document.getElementById('accessify-keyboard-help-close');\n closeBtn?.focus();\n closeBtn?.addEventListener('click', () => {\n overlay.remove();\n helpOverlayVisible = false;\n });\n }\n\n // --- Tabindex injection for interactive elements ---\n\n function injectTabindex() {\n const selectors = [\n 'a[href]',\n 'button',\n 'input',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"switch\"]',\n '[contenteditable=\"true\"]',\n 'summary',\n ];\n\n const elements = document.querySelectorAll<HTMLElement>(selectors.join(', '));\n elements.forEach((el) => {\n // Only add tabindex if the element is not already focusable via native mechanism\n // and does not already have an explicit tabindex\n if (!el.hasAttribute('tabindex') && !isNativelyFocusable(el)) {\n el.setAttribute('tabindex', '0');\n el.dataset.accessifyTabindex = 'true';\n }\n });\n }\n\n function removeInjectedTabindex() {\n const elements = document.querySelectorAll<HTMLElement>('[data-accessify-tabindex=\"true\"]');\n elements.forEach((el) => {\n el.removeAttribute('tabindex');\n delete el.dataset.accessifyTabindex;\n });\n }\n\n function isNativelyFocusable(el: HTMLElement): boolean {\n const tag = el.tagName.toLowerCase();\n if (['a', 'button', 'input', 'select', 'textarea'].includes(tag)) {\n return true;\n }\n if (tag === 'a' && !(el as HTMLAnchorElement).href) {\n return false;\n }\n return false;\n }\n\n // --- Keyboard event handler ---\n\n function handleKeyDown(e: KeyboardEvent) {\n if (!enabled) return;\n\n // Close help overlay on Escape\n if (e.key === 'Escape' && helpOverlayVisible) {\n const overlay = document.getElementById(OVERLAY_ID);\n overlay?.remove();\n helpOverlayVisible = false;\n return;\n }\n\n if (!e.altKey) return;\n\n switch (e.key.toLowerCase()) {\n case 'h':\n e.preventDefault();\n navigateToNextHeading();\n break;\n case 'l':\n e.preventDefault();\n navigateToNextLandmark();\n break;\n case 'k':\n e.preventDefault();\n toggleHelpOverlay();\n break;\n }\n }\n\n // --- Styles for skip link ---\n\n function getStyles(): string {\n return `\n /* accessify keyboard navigation */\n #${SKIP_LINK_ID} {\n position: fixed;\n top: -100px;\n left: 50%;\n transform: translateX(-50%);\n background: #1a73e8;\n color: #fff;\n padding: 12px 24px;\n border-radius: 0 0 8px 8px;\n font-size: 16px;\n font-family: system-ui, sans-serif;\n text-decoration: none;\n z-index: 2147483647;\n transition: top 0.2s ease;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n }\n #${SKIP_LINK_ID}:focus {\n top: 0;\n outline: 3px solid #ffdd00;\n outline-offset: 2px;\n }\n `;\n }\n\n function injectStyles() {\n let styleEl = document.getElementById(STYLE_ID);\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = getStyles();\n }\n\n function removeStyles() {\n const styleEl = document.getElementById(STYLE_ID);\n styleEl?.remove();\n }\n\n // --- Module lifecycle ---\n\n function activate() {\n enabled = true;\n headingIndex = -1;\n landmarkIndex = -1;\n\n injectStyles();\n injectSkipLink();\n injectTabindex();\n document.addEventListener('keydown', handleKeyDown);\n localStorage.setItem(STORAGE_KEY, 'true');\n }\n\n function deactivate() {\n enabled = false;\n helpOverlayVisible = false;\n\n document.removeEventListener('keydown', handleKeyDown);\n removeSkipLink();\n removeInjectedTabindex();\n removeStyles();\n\n const overlay = document.getElementById(OVERLAY_ID);\n overlay?.remove();\n\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'keyboard-nav',\n name: () => 'Keyboard Navigation',\n description: 'Enhanced keyboard navigation with skip links, heading/landmark jumping, and shortcut help',\n icon: 'keyboard-nav',\n category: 'motor',\n activate,\n deactivate,\n getState: (): FeatureState => ({\n id: 'keyboard-nav',\n enabled,\n }),\n setState: (state: { enabled: boolean }) => {\n if (state.enabled) {\n activate();\n } else {\n deactivate();\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,54 +0,0 @@
1
- function createLineHeightModule() {
2
- let enabled = false;
3
- let currentValue = 1.8;
4
- const STYLE_ID = "accessify-line-height";
5
- const STORAGE_KEY = "accessify-line-height-value";
6
- function applyStyles(value) {
7
- let styleEl = document.getElementById(STYLE_ID);
8
- if (!enabled) {
9
- styleEl?.remove();
10
- return;
11
- }
12
- if (!styleEl) {
13
- styleEl = document.createElement("style");
14
- styleEl.id = STYLE_ID;
15
- document.head.appendChild(styleEl);
16
- }
17
- styleEl.textContent = `
18
- body, body p, body li, body td, body th, body dd, body dt,
19
- body span, body div, body label, body blockquote {
20
- line-height: ${value} !important;
21
- }
22
- `;
23
- }
24
- function activate() {
25
- enabled = true;
26
- const saved = localStorage.getItem(STORAGE_KEY);
27
- if (saved) currentValue = parseFloat(saved);
28
- applyStyles(currentValue);
29
- }
30
- function deactivate() {
31
- enabled = false;
32
- applyStyles(currentValue);
33
- localStorage.removeItem(STORAGE_KEY);
34
- }
35
- return {
36
- id: "line-height",
37
- name: () => "Line Height",
38
- description: "Increase space between lines of text",
39
- icon: "line-height",
40
- category: "visual",
41
- activate,
42
- deactivate,
43
- getState: () => ({ id: "line-height", enabled, value: currentValue }),
44
- setState: (value) => {
45
- currentValue = Math.min(3, Math.max(1, value));
46
- applyStyles(currentValue);
47
- localStorage.setItem(STORAGE_KEY, String(currentValue));
48
- }
49
- };
50
- }
51
- export {
52
- createLineHeightModule as default
53
- };
54
- //# sourceMappingURL=line-height-BT98qgEF.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"line-height-BT98qgEF.js","sources":["../src/features/line-height.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\nexport default function createLineHeightModule(): FeatureModule {\n let enabled = false;\n let currentValue = 1.8;\n const STYLE_ID = 'accessify-line-height';\n const STORAGE_KEY = 'accessify-line-height-value';\n\n function applyStyles(value: number) {\n let styleEl = document.getElementById(STYLE_ID);\n if (!enabled) {\n styleEl?.remove();\n return;\n }\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = `\n body, body p, body li, body td, body th, body dd, body dt,\n body span, body div, body label, body blockquote {\n line-height: ${value} !important;\n }\n `;\n }\n\n function activate() {\n enabled = true;\n const saved = localStorage.getItem(STORAGE_KEY);\n if (saved) currentValue = parseFloat(saved);\n applyStyles(currentValue);\n }\n\n function deactivate() {\n enabled = false;\n applyStyles(currentValue);\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'line-height',\n name: () => 'Line Height',\n description: 'Increase space between lines of text',\n icon: 'line-height',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'line-height', enabled, value: currentValue }),\n setState: (value: number) => {\n currentValue = Math.min(3, Math.max(1, value));\n applyStyles(currentValue);\n localStorage.setItem(STORAGE_KEY, String(currentValue));\n },\n };\n}\n"],"names":[],"mappings":"AAEA,SAAwB,yBAAwC;AAC9D,MAAI,UAAU;AACd,MAAI,eAAe;AACnB,QAAM,WAAW;AACjB,QAAM,cAAc;AAEpB,WAAS,YAAY,OAAe;AAClC,QAAI,UAAU,SAAS,eAAe,QAAQ;AAC9C,QAAI,CAAC,SAAS;AACZ,eAAS,OAAA;AACT;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,OAAO;AACxC,cAAQ,KAAK;AACb,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,YAAQ,cAAc;AAAA;AAAA;AAAA,uBAGH,KAAK;AAAA;AAAA;AAAA,EAG1B;AAEA,WAAS,WAAW;AAClB,cAAU;AACV,UAAM,QAAQ,aAAa,QAAQ,WAAW;AAC9C,QAAI,MAAO,gBAAe,WAAW,KAAK;AAC1C,gBAAY,YAAY;AAAA,EAC1B;AAEA,WAAS,aAAa;AACpB,cAAU;AACV,gBAAY,YAAY;AACxB,iBAAa,WAAW,WAAW;AAAA,EACrC;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,MAAM;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU,OAAqB,EAAE,IAAI,eAAe,SAAS,OAAO;IACpE,UAAU,CAAC,UAAkB;AAC3B,qBAAe,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AAC7C,kBAAY,YAAY;AACxB,mBAAa,QAAQ,aAAa,OAAO,YAAY,CAAC;AAAA,IACxD;AAAA,EAAA;AAEJ;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"page-structure-2X8mOSpC.js","sources":["../src/features/page-structure.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\nexport default function createPageStructureModule(): FeatureModule {\n let enabled = false;\n let panelEl: HTMLElement | null = null;\n const PANEL_ID = 'accessify-page-structure';\n\n function collectHeadings(): Array<{ tag: string; text: string; el: HTMLElement }> {\n const results: Array<{ tag: string; text: string; el: HTMLElement }> = [];\n const headings = document.querySelectorAll<HTMLElement>('h1, h2, h3, h4, h5, h6');\n headings.forEach((el) => {\n if (el.closest('#accessify-root')) return;\n const text = el.textContent?.trim() || '';\n if (text) results.push({ tag: el.tagName.toLowerCase(), text, el });\n });\n return results;\n }\n\n function collectLandmarks(): Array<{ role: string; label: string; el: HTMLElement }> {\n const results: Array<{ role: string; label: string; el: HTMLElement }> = [];\n const selectors = [\n 'main', 'nav', 'aside', 'header', 'footer', 'section[aria-label]',\n 'section[aria-labelledby]', '[role=\"main\"]', '[role=\"navigation\"]',\n '[role=\"complementary\"]', '[role=\"banner\"]', '[role=\"contentinfo\"]',\n '[role=\"search\"]',\n ];\n const els = document.querySelectorAll<HTMLElement>(selectors.join(','));\n els.forEach((el) => {\n if (el.closest('#accessify-root')) return;\n const role = el.getAttribute('role') || el.tagName.toLowerCase();\n const label = el.getAttribute('aria-label') || el.getAttribute('aria-labelledby') || role;\n results.push({ role, label, el });\n });\n return results;\n }\n\n function buildPanel() {\n panelEl = document.createElement('div');\n panelEl.id = PANEL_ID;\n panelEl.setAttribute('role', 'dialog');\n panelEl.setAttribute('aria-label', 'Page Structure');\n\n const headings = collectHeadings();\n const landmarks = collectLandmarks();\n\n const indent: Record<string, string> = {\n h1: '0', h2: '12px', h3: '24px', h4: '36px', h5: '48px', h6: '60px',\n };\n\n let html = `\n <style>\n #${PANEL_ID} {\n position: fixed; top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n z-index: 999998;\n background: #fff; color: #1a1a1a;\n border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.2);\n padding: 24px; width: 400px; max-height: 80vh;\n overflow-y: auto; font-family: system-ui, sans-serif;\n font-size: 14px; line-height: 1.5;\n }\n #${PANEL_ID} h3 { margin: 0 0 12px; font-size: 16px; }\n #${PANEL_ID} .ps-section { margin-bottom: 16px; }\n #${PANEL_ID} .ps-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: #888; margin-bottom: 6px; }\n #${PANEL_ID} .ps-item {\n display: block; width: 100%; text-align: left;\n padding: 6px 8px; border: none; background: none;\n cursor: pointer; border-radius: 6px; font-size: 13px;\n color: #1a1a1a; font-family: inherit;\n }\n #${PANEL_ID} .ps-item:hover { background: #f0f0f2; }\n #${PANEL_ID} .ps-item:focus-visible { outline: 2px solid #0055CC; outline-offset: 1px; }\n #${PANEL_ID} .ps-tag { color: #888; font-size: 11px; margin-right: 6px; }\n #${PANEL_ID} .ps-close {\n position: absolute; top: 12px; right: 12px;\n background: none; border: none; cursor: pointer;\n font-size: 18px; color: #888; padding: 4px 8px; border-radius: 4px;\n }\n #${PANEL_ID} .ps-close:hover { background: #f0f0f2; }\n @media (prefers-color-scheme: dark) {\n #${PANEL_ID} { background: #1a1a1a; color: #f0f0f0; }\n #${PANEL_ID} .ps-item { color: #f0f0f0; }\n #${PANEL_ID} .ps-item:hover { background: #2a2a2e; }\n #${PANEL_ID} .ps-close { color: #aaa; }\n #${PANEL_ID} .ps-close:hover { background: #2a2a2e; }\n }\n </style>\n <button class=\"ps-close\" aria-label=\"Close\">&times;</button>\n <h3>Page Structure</h3>\n `;\n\n if (headings.length > 0) {\n html += '<div class=\"ps-section\"><div class=\"ps-label\">Headings</div>';\n headings.forEach((h, i) => {\n html += `<button class=\"ps-item\" data-type=\"heading\" data-index=\"${i}\" style=\"padding-left:${indent[h.tag] || '0'}\">\n <span class=\"ps-tag\">${h.tag}</span>${escapeHtml(h.text.slice(0, 80))}\n </button>`;\n });\n html += '</div>';\n }\n\n if (landmarks.length > 0) {\n html += '<div class=\"ps-section\"><div class=\"ps-label\">Landmarks</div>';\n landmarks.forEach((lm, i) => {\n html += `<button class=\"ps-item\" data-type=\"landmark\" data-index=\"${i}\">\n <span class=\"ps-tag\">${escapeHtml(lm.role)}</span>${escapeHtml(lm.label.slice(0, 60))}\n </button>`;\n });\n html += '</div>';\n }\n\n if (headings.length === 0 && landmarks.length === 0) {\n html += '<p style=\"color:#888\">No headings or landmarks found on this page.</p>';\n }\n\n panelEl.innerHTML = html;\n\n // Event delegation\n panelEl.addEventListener('click', (e) => {\n const btn = (e.target as HTMLElement).closest<HTMLElement>('.ps-item');\n if (btn) {\n const type = btn.dataset.type;\n const idx = parseInt(btn.dataset.index || '0', 10);\n let target: HTMLElement | undefined;\n if (type === 'heading') target = headings[idx]?.el;\n else if (type === 'landmark') target = landmarks[idx]?.el;\n if (target) {\n target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n target.focus({ preventScroll: true });\n }\n }\n if ((e.target as HTMLElement).closest('.ps-close')) {\n deactivate();\n }\n });\n\n document.body.appendChild(panelEl);\n const firstBtn = panelEl.querySelector<HTMLElement>('.ps-item, .ps-close');\n firstBtn?.focus();\n }\n\n function escapeHtml(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n function activate() {\n enabled = true;\n buildPanel();\n }\n\n function deactivate() {\n enabled = false;\n panelEl?.remove();\n panelEl = null;\n }\n\n return {\n id: 'page-structure',\n name: () => 'Page Structure',\n description: 'View headings and landmarks for quick navigation',\n icon: 'page-structure',\n category: 'motor',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'page-structure', enabled }),\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,59 +0,0 @@
1
- function createSaturationModule() {
2
- let currentMode = "off";
3
- const STYLE_ID = "accessify-saturation";
4
- const STORAGE_KEY = "accessify-saturation-mode";
5
- function getStyles(mode) {
6
- switch (mode) {
7
- case "low":
8
- return "html { filter: saturate(0.3) !important; }";
9
- case "grayscale":
10
- return "html { filter: grayscale(1) !important; }";
11
- case "high":
12
- return "html { filter: saturate(1.8) !important; }";
13
- default:
14
- return "";
15
- }
16
- }
17
- function applyStyles(mode) {
18
- let styleEl = document.getElementById(STYLE_ID);
19
- if (mode === "off") {
20
- styleEl?.remove();
21
- return;
22
- }
23
- if (!styleEl) {
24
- styleEl = document.createElement("style");
25
- styleEl.id = STYLE_ID;
26
- document.head.appendChild(styleEl);
27
- }
28
- styleEl.textContent = getStyles(mode);
29
- }
30
- function activate() {
31
- const saved = localStorage.getItem(STORAGE_KEY);
32
- currentMode = saved || "grayscale";
33
- applyStyles(currentMode);
34
- }
35
- function deactivate() {
36
- currentMode = "off";
37
- applyStyles("off");
38
- localStorage.removeItem(STORAGE_KEY);
39
- }
40
- return {
41
- id: "saturation",
42
- name: () => "Saturation",
43
- description: "Adjust color saturation or grayscale",
44
- icon: "saturation",
45
- category: "visual",
46
- activate,
47
- deactivate,
48
- getState: () => ({ id: "saturation", enabled: currentMode !== "off", value: currentMode }),
49
- setState: (mode) => {
50
- currentMode = mode;
51
- applyStyles(mode);
52
- localStorage.setItem(STORAGE_KEY, mode);
53
- }
54
- };
55
- }
56
- export {
57
- createSaturationModule as default
58
- };
59
- //# sourceMappingURL=saturation-D8ZXpWAN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"saturation-D8ZXpWAN.js","sources":["../src/features/saturation.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\ntype SaturationMode = 'off' | 'low' | 'grayscale' | 'high';\n\nexport default function createSaturationModule(): FeatureModule {\n let currentMode: SaturationMode = 'off';\n const STYLE_ID = 'accessify-saturation';\n const STORAGE_KEY = 'accessify-saturation-mode';\n\n function getStyles(mode: SaturationMode): string {\n switch (mode) {\n case 'low':\n return 'html { filter: saturate(0.3) !important; }';\n case 'grayscale':\n return 'html { filter: grayscale(1) !important; }';\n case 'high':\n return 'html { filter: saturate(1.8) !important; }';\n default:\n return '';\n }\n }\n\n function applyStyles(mode: SaturationMode) {\n let styleEl = document.getElementById(STYLE_ID);\n if (mode === 'off') {\n styleEl?.remove();\n return;\n }\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = getStyles(mode);\n }\n\n function activate() {\n const saved = localStorage.getItem(STORAGE_KEY) as SaturationMode;\n currentMode = saved || 'grayscale';\n applyStyles(currentMode);\n }\n\n function deactivate() {\n currentMode = 'off';\n applyStyles('off');\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'saturation',\n name: () => 'Saturation',\n description: 'Adjust color saturation or grayscale',\n icon: 'saturation',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'saturation', enabled: currentMode !== 'off', value: currentMode }),\n setState: (mode: SaturationMode) => {\n currentMode = mode;\n applyStyles(mode);\n localStorage.setItem(STORAGE_KEY, mode);\n },\n };\n}\n"],"names":[],"mappings":"AAIA,SAAwB,yBAAwC;AAC9D,MAAI,cAA8B;AAClC,QAAM,WAAW;AACjB,QAAM,cAAc;AAEpB,WAAS,UAAU,MAA8B;AAC/C,YAAQ,MAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAEA,WAAS,YAAY,MAAsB;AACzC,QAAI,UAAU,SAAS,eAAe,QAAQ;AAC9C,QAAI,SAAS,OAAO;AAClB,eAAS,OAAA;AACT;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,OAAO;AACxC,cAAQ,KAAK;AACb,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,YAAQ,cAAc,UAAU,IAAI;AAAA,EACtC;AAEA,WAAS,WAAW;AAClB,UAAM,QAAQ,aAAa,QAAQ,WAAW;AAC9C,kBAAc,SAAS;AACvB,gBAAY,WAAW;AAAA,EACzB;AAEA,WAAS,aAAa;AACpB,kBAAc;AACd,gBAAY,KAAK;AACjB,iBAAa,WAAW,WAAW;AAAA,EACrC;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,MAAM;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU,OAAqB,EAAE,IAAI,cAAc,SAAS,gBAAgB,OAAO,OAAO;IAC1F,UAAU,CAAC,SAAyB;AAClC,oBAAc;AACd,kBAAY,IAAI;AAChB,mBAAa,QAAQ,aAAa,IAAI;AAAA,IACxC;AAAA,EAAA;AAEJ;"}
@@ -1,106 +0,0 @@
1
- const DEFAULT_VALUES = {
2
- lineHeight: 1.5,
3
- paragraphSpacing: 2,
4
- letterSpacing: 0.12,
5
- wordSpacing: 0.16
6
- };
7
- const MAX_VALUES = {
8
- lineHeight: 2.5,
9
- paragraphSpacing: 4,
10
- letterSpacing: 0.24,
11
- wordSpacing: 0.32
12
- };
13
- function createSpacingModule() {
14
- let enabled = false;
15
- let currentValues = { ...DEFAULT_VALUES };
16
- const STYLE_ID = "accessify-spacing";
17
- const STORAGE_KEY = "accessify-spacing";
18
- function applySpacing(values) {
19
- const root = document.documentElement;
20
- root.style.setProperty("--accessify-line-height", String(values.lineHeight));
21
- root.style.setProperty("--accessify-paragraph-spacing", `${values.paragraphSpacing}em`);
22
- root.style.setProperty("--accessify-letter-spacing", `${values.letterSpacing}em`);
23
- root.style.setProperty("--accessify-word-spacing", `${values.wordSpacing}em`);
24
- let styleEl = document.getElementById(STYLE_ID);
25
- if (!styleEl) {
26
- styleEl = document.createElement("style");
27
- styleEl.id = STYLE_ID;
28
- document.head.appendChild(styleEl);
29
- }
30
- styleEl.textContent = `
31
- /* accessify WCAG 1.4.12 text spacing adjustments */
32
- * {
33
- line-height: var(--accessify-line-height) !important;
34
- letter-spacing: var(--accessify-letter-spacing) !important;
35
- word-spacing: var(--accessify-word-spacing) !important;
36
- }
37
- p {
38
- margin-bottom: var(--accessify-paragraph-spacing) !important;
39
- }
40
- p + p {
41
- margin-top: var(--accessify-paragraph-spacing) !important;
42
- }
43
- `;
44
- }
45
- function removeSpacing() {
46
- const root = document.documentElement;
47
- root.style.removeProperty("--accessify-line-height");
48
- root.style.removeProperty("--accessify-paragraph-spacing");
49
- root.style.removeProperty("--accessify-letter-spacing");
50
- root.style.removeProperty("--accessify-word-spacing");
51
- const styleEl = document.getElementById(STYLE_ID);
52
- styleEl?.remove();
53
- }
54
- function clampValues(values) {
55
- return {
56
- lineHeight: Math.min(MAX_VALUES.lineHeight, Math.max(DEFAULT_VALUES.lineHeight, values.lineHeight ?? currentValues.lineHeight)),
57
- paragraphSpacing: Math.min(MAX_VALUES.paragraphSpacing, Math.max(DEFAULT_VALUES.paragraphSpacing, values.paragraphSpacing ?? currentValues.paragraphSpacing)),
58
- letterSpacing: Math.min(MAX_VALUES.letterSpacing, Math.max(DEFAULT_VALUES.letterSpacing, values.letterSpacing ?? currentValues.letterSpacing)),
59
- wordSpacing: Math.min(MAX_VALUES.wordSpacing, Math.max(DEFAULT_VALUES.wordSpacing, values.wordSpacing ?? currentValues.wordSpacing))
60
- };
61
- }
62
- function activate() {
63
- enabled = true;
64
- const saved = localStorage.getItem(STORAGE_KEY);
65
- if (saved) {
66
- try {
67
- currentValues = clampValues(JSON.parse(saved));
68
- } catch {
69
- currentValues = { ...DEFAULT_VALUES };
70
- }
71
- } else {
72
- currentValues = { ...DEFAULT_VALUES };
73
- }
74
- applySpacing(currentValues);
75
- }
76
- function deactivate() {
77
- enabled = false;
78
- removeSpacing();
79
- localStorage.removeItem(STORAGE_KEY);
80
- currentValues = { ...DEFAULT_VALUES };
81
- }
82
- return {
83
- id: "spacing",
84
- name: () => "Text Spacing",
85
- description: "Adjust line height, letter spacing, word spacing and paragraph spacing (WCAG 1.4.12)",
86
- icon: "spacing",
87
- category: "visual",
88
- activate,
89
- deactivate,
90
- getState: () => ({
91
- id: "spacing",
92
- enabled,
93
- value: { ...currentValues }
94
- }),
95
- setState: (values) => {
96
- currentValues = clampValues(values);
97
- applySpacing(currentValues);
98
- localStorage.setItem(STORAGE_KEY, JSON.stringify(currentValues));
99
- enabled = true;
100
- }
101
- };
102
- }
103
- export {
104
- createSpacingModule as default
105
- };
106
- //# sourceMappingURL=spacing-DENai3JU.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spacing-DENai3JU.js","sources":["../src/features/spacing.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\ninterface SpacingValues {\n lineHeight: number;\n paragraphSpacing: number;\n letterSpacing: number;\n wordSpacing: number;\n}\n\nconst DEFAULT_VALUES: SpacingValues = {\n lineHeight: 1.5,\n paragraphSpacing: 2,\n letterSpacing: 0.12,\n wordSpacing: 0.16,\n};\n\nconst MAX_VALUES: SpacingValues = {\n lineHeight: 2.5,\n paragraphSpacing: 4,\n letterSpacing: 0.24,\n wordSpacing: 0.32,\n};\n\nexport default function createSpacingModule(): FeatureModule {\n let enabled = false;\n let currentValues: SpacingValues = { ...DEFAULT_VALUES };\n const STYLE_ID = 'accessify-spacing';\n const STORAGE_KEY = 'accessify-spacing';\n\n function applySpacing(values: SpacingValues) {\n const root = document.documentElement;\n root.style.setProperty('--accessify-line-height', String(values.lineHeight));\n root.style.setProperty('--accessify-paragraph-spacing', `${values.paragraphSpacing}em`);\n root.style.setProperty('--accessify-letter-spacing', `${values.letterSpacing}em`);\n root.style.setProperty('--accessify-word-spacing', `${values.wordSpacing}em`);\n\n let styleEl = document.getElementById(STYLE_ID);\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = `\n /* accessify WCAG 1.4.12 text spacing adjustments */\n * {\n line-height: var(--accessify-line-height) !important;\n letter-spacing: var(--accessify-letter-spacing) !important;\n word-spacing: var(--accessify-word-spacing) !important;\n }\n p {\n margin-bottom: var(--accessify-paragraph-spacing) !important;\n }\n p + p {\n margin-top: var(--accessify-paragraph-spacing) !important;\n }\n `;\n }\n\n function removeSpacing() {\n const root = document.documentElement;\n root.style.removeProperty('--accessify-line-height');\n root.style.removeProperty('--accessify-paragraph-spacing');\n root.style.removeProperty('--accessify-letter-spacing');\n root.style.removeProperty('--accessify-word-spacing');\n const styleEl = document.getElementById(STYLE_ID);\n styleEl?.remove();\n }\n\n function clampValues(values: Partial<SpacingValues>): SpacingValues {\n return {\n lineHeight: Math.min(MAX_VALUES.lineHeight, Math.max(DEFAULT_VALUES.lineHeight, values.lineHeight ?? currentValues.lineHeight)),\n paragraphSpacing: Math.min(MAX_VALUES.paragraphSpacing, Math.max(DEFAULT_VALUES.paragraphSpacing, values.paragraphSpacing ?? currentValues.paragraphSpacing)),\n letterSpacing: Math.min(MAX_VALUES.letterSpacing, Math.max(DEFAULT_VALUES.letterSpacing, values.letterSpacing ?? currentValues.letterSpacing)),\n wordSpacing: Math.min(MAX_VALUES.wordSpacing, Math.max(DEFAULT_VALUES.wordSpacing, values.wordSpacing ?? currentValues.wordSpacing)),\n };\n }\n\n function activate() {\n enabled = true;\n const saved = localStorage.getItem(STORAGE_KEY);\n if (saved) {\n try {\n currentValues = clampValues(JSON.parse(saved));\n } catch {\n currentValues = { ...DEFAULT_VALUES };\n }\n } else {\n currentValues = { ...DEFAULT_VALUES };\n }\n applySpacing(currentValues);\n }\n\n function deactivate() {\n enabled = false;\n removeSpacing();\n localStorage.removeItem(STORAGE_KEY);\n currentValues = { ...DEFAULT_VALUES };\n }\n\n return {\n id: 'spacing',\n name: () => 'Text Spacing',\n description: 'Adjust line height, letter spacing, word spacing and paragraph spacing (WCAG 1.4.12)',\n icon: 'spacing',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({\n id: 'spacing',\n enabled,\n value: { ...currentValues },\n }),\n setState: (values: Partial<SpacingValues>) => {\n currentValues = clampValues(values);\n applySpacing(currentValues);\n localStorage.setItem(STORAGE_KEY, JSON.stringify(currentValues));\n enabled = true;\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,51 +0,0 @@
1
- function createTextAlignModule() {
2
- let currentMode = "off";
3
- const STYLE_ID = "accessify-text-align";
4
- const STORAGE_KEY = "accessify-text-align-mode";
5
- function applyStyles(mode) {
6
- let styleEl = document.getElementById(STYLE_ID);
7
- if (mode === "off") {
8
- styleEl?.remove();
9
- return;
10
- }
11
- if (!styleEl) {
12
- styleEl = document.createElement("style");
13
- styleEl.id = STYLE_ID;
14
- document.head.appendChild(styleEl);
15
- }
16
- styleEl.textContent = `
17
- body, body * {
18
- text-align: ${mode} !important;
19
- }
20
- `;
21
- }
22
- function activate() {
23
- const saved = localStorage.getItem(STORAGE_KEY);
24
- currentMode = saved || "left";
25
- applyStyles(currentMode);
26
- }
27
- function deactivate() {
28
- currentMode = "off";
29
- applyStyles("off");
30
- localStorage.removeItem(STORAGE_KEY);
31
- }
32
- return {
33
- id: "text-align",
34
- name: () => "Text Align",
35
- description: "Change text alignment across the page",
36
- icon: "text-align",
37
- category: "visual",
38
- activate,
39
- deactivate,
40
- getState: () => ({ id: "text-align", enabled: currentMode !== "off", value: currentMode }),
41
- setState: (mode) => {
42
- currentMode = mode;
43
- applyStyles(mode);
44
- localStorage.setItem(STORAGE_KEY, mode);
45
- }
46
- };
47
- }
48
- export {
49
- createTextAlignModule as default
50
- };
51
- //# sourceMappingURL=text-align-BDRPqPvl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"text-align-BDRPqPvl.js","sources":["../src/features/text-align.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\ntype AlignMode = 'off' | 'left' | 'center' | 'right' | 'justify';\n\nexport default function createTextAlignModule(): FeatureModule {\n let currentMode: AlignMode = 'off';\n const STYLE_ID = 'accessify-text-align';\n const STORAGE_KEY = 'accessify-text-align-mode';\n\n function applyStyles(mode: AlignMode) {\n let styleEl = document.getElementById(STYLE_ID);\n if (mode === 'off') {\n styleEl?.remove();\n return;\n }\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = `\n body, body * {\n text-align: ${mode} !important;\n }\n `;\n }\n\n function activate() {\n const saved = localStorage.getItem(STORAGE_KEY) as AlignMode;\n currentMode = saved || 'left';\n applyStyles(currentMode);\n }\n\n function deactivate() {\n currentMode = 'off';\n applyStyles('off');\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'text-align',\n name: () => 'Text Align',\n description: 'Change text alignment across the page',\n icon: 'text-align',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'text-align', enabled: currentMode !== 'off', value: currentMode }),\n setState: (mode: AlignMode) => {\n currentMode = mode;\n applyStyles(mode);\n localStorage.setItem(STORAGE_KEY, mode);\n },\n };\n}\n"],"names":[],"mappings":"AAIA,SAAwB,wBAAuC;AAC7D,MAAI,cAAyB;AAC7B,QAAM,WAAW;AACjB,QAAM,cAAc;AAEpB,WAAS,YAAY,MAAiB;AACpC,QAAI,UAAU,SAAS,eAAe,QAAQ;AAC9C,QAAI,SAAS,OAAO;AAClB,eAAS,OAAA;AACT;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,OAAO;AACxC,cAAQ,KAAK;AACb,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,YAAQ,cAAc;AAAA;AAAA,sBAEJ,IAAI;AAAA;AAAA;AAAA,EAGxB;AAEA,WAAS,WAAW;AAClB,UAAM,QAAQ,aAAa,QAAQ,WAAW;AAC9C,kBAAc,SAAS;AACvB,gBAAY,WAAW;AAAA,EACzB;AAEA,WAAS,aAAa;AACpB,kBAAc;AACd,gBAAY,KAAK;AACjB,iBAAa,WAAW,WAAW;AAAA,EACrC;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,MAAM;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU,OAAqB,EAAE,IAAI,cAAc,SAAS,gBAAgB,OAAO,OAAO;IAC1F,UAAU,CAAC,SAAoB;AAC7B,oBAAc;AACd,kBAAY,IAAI;AAChB,mBAAa,QAAQ,aAAa,IAAI;AAAA,IACxC;AAAA,EAAA;AAEJ;"}
@@ -1,69 +0,0 @@
1
- function createTextSizeModule() {
2
- let currentSize = 100;
3
- let originalFontSize = "";
4
- const STYLE_ID = "accessify-text-size";
5
- const STORAGE_KEY = "accessify-text-size";
6
- const MIN_SIZE = 100;
7
- const MAX_SIZE = 200;
8
- const STEP = 10;
9
- function applySize(percent) {
10
- let styleEl = document.getElementById(STYLE_ID);
11
- if (percent === 100) {
12
- styleEl?.remove();
13
- if (originalFontSize) {
14
- document.documentElement.style.fontSize = originalFontSize;
15
- } else {
16
- document.documentElement.style.removeProperty("font-size");
17
- }
18
- return;
19
- }
20
- if (!styleEl) {
21
- styleEl = document.createElement("style");
22
- styleEl.id = STYLE_ID;
23
- document.head.appendChild(styleEl);
24
- }
25
- const scale = percent / 100;
26
- document.documentElement.style.fontSize = `${scale * 100}%`;
27
- styleEl.textContent = `
28
- /* accessify text-size: ${percent}% */
29
- body { font-size: 1rem !important; }
30
- `;
31
- }
32
- function clamp(value) {
33
- return Math.min(MAX_SIZE, Math.max(MIN_SIZE, Math.round(value / STEP) * STEP));
34
- }
35
- function activate() {
36
- originalFontSize = document.documentElement.style.fontSize || "";
37
- const saved = localStorage.getItem(STORAGE_KEY);
38
- currentSize = saved ? clamp(parseInt(saved, 10)) : 150;
39
- applySize(currentSize);
40
- }
41
- function deactivate() {
42
- currentSize = 100;
43
- applySize(100);
44
- localStorage.removeItem(STORAGE_KEY);
45
- }
46
- return {
47
- id: "text-size",
48
- name: () => "Text Size",
49
- description: "Adjust text size from 100% to 200%",
50
- icon: "text-size",
51
- category: "visual",
52
- activate,
53
- deactivate,
54
- getState: () => ({
55
- id: "text-size",
56
- enabled: currentSize !== 100,
57
- value: currentSize
58
- }),
59
- setState: (size) => {
60
- currentSize = clamp(size);
61
- applySize(currentSize);
62
- localStorage.setItem(STORAGE_KEY, String(currentSize));
63
- }
64
- };
65
- }
66
- export {
67
- createTextSizeModule as default
68
- };
69
- //# sourceMappingURL=text-size-B-uv436p.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"text-size-B-uv436p.js","sources":["../src/features/text-size.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\nexport default function createTextSizeModule(): FeatureModule {\n let currentSize = 100;\n let originalFontSize = '';\n const STYLE_ID = 'accessify-text-size';\n const STORAGE_KEY = 'accessify-text-size';\n const MIN_SIZE = 100;\n const MAX_SIZE = 200;\n const STEP = 10;\n\n function applySize(percent: number) {\n let styleEl = document.getElementById(STYLE_ID);\n if (percent === 100) {\n styleEl?.remove();\n if (originalFontSize) {\n document.documentElement.style.fontSize = originalFontSize;\n } else {\n document.documentElement.style.removeProperty('font-size');\n }\n return;\n }\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n const scale = percent / 100;\n document.documentElement.style.fontSize = `${scale * 100}%`;\n styleEl.textContent = `\n /* accessify text-size: ${percent}% */\n body { font-size: 1rem !important; }\n `;\n }\n\n function clamp(value: number): number {\n return Math.min(MAX_SIZE, Math.max(MIN_SIZE, Math.round(value / STEP) * STEP));\n }\n\n function activate() {\n originalFontSize = document.documentElement.style.fontSize || '';\n const saved = localStorage.getItem(STORAGE_KEY);\n currentSize = saved ? clamp(parseInt(saved, 10)) : 150;\n applySize(currentSize);\n }\n\n function deactivate() {\n currentSize = 100;\n applySize(100);\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'text-size',\n name: () => 'Text Size',\n description: 'Adjust text size from 100% to 200%',\n icon: 'text-size',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({\n id: 'text-size',\n enabled: currentSize !== 100,\n value: currentSize,\n }),\n setState: (size: number) => {\n currentSize = clamp(size);\n applySize(currentSize);\n localStorage.setItem(STORAGE_KEY, String(currentSize));\n },\n };\n}\n"],"names":[],"mappings":"AAEA,SAAwB,uBAAsC;AAC5D,MAAI,cAAc;AAClB,MAAI,mBAAmB;AACvB,QAAM,WAAW;AACjB,QAAM,cAAc;AACpB,QAAM,WAAW;AACjB,QAAM,WAAW;AACjB,QAAM,OAAO;AAEb,WAAS,UAAU,SAAiB;AAClC,QAAI,UAAU,SAAS,eAAe,QAAQ;AAC9C,QAAI,YAAY,KAAK;AACnB,eAAS,OAAA;AACT,UAAI,kBAAkB;AACpB,iBAAS,gBAAgB,MAAM,WAAW;AAAA,MAC5C,OAAO;AACL,iBAAS,gBAAgB,MAAM,eAAe,WAAW;AAAA,MAC3D;AACA;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,OAAO;AACxC,cAAQ,KAAK;AACb,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,UAAM,QAAQ,UAAU;AACxB,aAAS,gBAAgB,MAAM,WAAW,GAAG,QAAQ,GAAG;AACxD,YAAQ,cAAc;AAAA,gCACM,OAAO;AAAA;AAAA;AAAA,EAGrC;AAEA,WAAS,MAAM,OAAuB;AACpC,WAAO,KAAK,IAAI,UAAU,KAAK,IAAI,UAAU,KAAK,MAAM,QAAQ,IAAI,IAAI,IAAI,CAAC;AAAA,EAC/E;AAEA,WAAS,WAAW;AAClB,uBAAmB,SAAS,gBAAgB,MAAM,YAAY;AAC9D,UAAM,QAAQ,aAAa,QAAQ,WAAW;AAC9C,kBAAc,QAAQ,MAAM,SAAS,OAAO,EAAE,CAAC,IAAI;AACnD,cAAU,WAAW;AAAA,EACvB;AAEA,WAAS,aAAa;AACpB,kBAAc;AACd,cAAU,GAAG;AACb,iBAAa,WAAW,WAAW;AAAA,EACrC;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,MAAM;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU,OAAqB;AAAA,MAC7B,IAAI;AAAA,MACJ,SAAS,gBAAgB;AAAA,MACzB,OAAO;AAAA,IAAA;AAAA,IAET,UAAU,CAAC,SAAiB;AAC1B,oBAAc,MAAM,IAAI;AACxB,gBAAU,WAAW;AACrB,mBAAa,QAAQ,aAAa,OAAO,WAAW,CAAC;AAAA,IACvD;AAAA,EAAA;AAEJ;"}