@contractspec/lib.accessibility 1.46.1 → 1.47.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.
- package/dist/preferences.js.map +1 -1
- package/package.json +8 -9
package/dist/preferences.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preferences.js","names":[
|
|
1
|
+
{"version":3,"file":"preferences.js","names":[],"sources":["../src/preferences.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nexport type TextSize = 's' | 'm' | 'l' | 'xl';\nexport type TextSpacing = 'normal' | 'increased';\nexport type LineHeight = 'normal' | 'increased';\nexport type UnderlineLinks = boolean;\nexport type FocusRing = 'normal' | 'thick';\nexport type ReduceMotion = 'system' | 'reduce' | 'no-preference';\nexport type HighContrast = boolean;\nexport type DyslexiaFont = boolean;\n\nexport interface AccessibilityPreferences {\n textSize: TextSize;\n textSpacing: TextSpacing;\n lineHeight: LineHeight;\n underlineLinks: UnderlineLinks;\n focusRing: FocusRing;\n reduceMotion: ReduceMotion;\n highContrast: HighContrast;\n dyslexiaFont: DyslexiaFont;\n}\n\nconst DEFAULT_PREFERENCES: AccessibilityPreferences = {\n textSize: 'm',\n textSpacing: 'normal',\n lineHeight: 'normal',\n underlineLinks: false,\n focusRing: 'normal',\n reduceMotion: 'system',\n highContrast: false,\n dyslexiaFont: false,\n};\n\nconst STORAGE_KEY = 'a11y:preferences:v1';\n\nfunction getStoredPreferences(): AccessibilityPreferences | null {\n try {\n const raw =\n typeof window !== 'undefined'\n ? window.localStorage.getItem(STORAGE_KEY)\n : null;\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n return { ...DEFAULT_PREFERENCES, ...parsed } as AccessibilityPreferences;\n } catch {\n return null;\n }\n}\n\nfunction savePreferences(prefs: AccessibilityPreferences) {\n try {\n if (typeof window !== 'undefined') {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));\n }\n } catch {\n // ignore\n }\n}\n\nfunction applyCssVariables(prefs: AccessibilityPreferences) {\n if (typeof document === 'undefined') return;\n const root = document.documentElement;\n const body = document.body;\n // Type scale (base multiplier)\n const sizeMap: Record<TextSize, string> = {\n s: '0.95',\n m: '1',\n l: '1.1',\n xl: '1.25',\n };\n root.style.setProperty('--a11y-text-scale', sizeMap[prefs.textSize]);\n // Target size: increase on larger text choices\n const targetMin =\n prefs.textSize === 'l' || prefs.textSize === 'xl' ? '44px' : '0px';\n root.style.setProperty('--a11y-target-min', targetMin);\n\n // Spacing per WCAG 1.4.12\n root.style.setProperty(\n '--a11y-letter-spacing',\n prefs.textSpacing === 'increased' ? '0.12em' : 'normal'\n );\n root.style.setProperty(\n '--a11y-word-spacing',\n prefs.textSpacing === 'increased' ? '0.16em' : 'normal'\n );\n root.style.setProperty(\n '--a11y-line-height',\n prefs.lineHeight === 'increased' ? '1.6' : '1.5'\n );\n\n // Links\n root.style.setProperty(\n '--a11y-underline-links',\n // Use 'revert' so we don't override the site's default when disabled\n prefs.underlineLinks ? 'underline' : 'revert'\n );\n\n // Focus ring\n root.style.setProperty(\n '--a11y-focus-ring-width',\n prefs.focusRing === 'thick' ? '4px' : '2px'\n );\n\n // Reduce motion\n root.style.setProperty('--a11y-reduce-motion', prefs.reduceMotion);\n\n // Contrast\n root.style.setProperty(\n '--a11y-contrast-mode',\n prefs.highContrast ? 'high' : 'normal'\n );\n if (prefs.highContrast) {\n root.setAttribute('data-contrast', 'high');\n } else {\n root.removeAttribute('data-contrast');\n }\n\n // Dyslexia-friendly font (consumer should map to an available font family)\n root.style.setProperty(\n '--a11y-font-family-alt-enabled',\n prefs.dyslexiaFont ? '1' : '0'\n );\n\n // Inline fallbacks in case global CSS variables are not wired/included by the app bundler.\n // These properties are inheritable, so setting them on <body> yields broad coverage.\n if (body) {\n if (prefs.textSpacing === 'increased') {\n body.style.letterSpacing = '0.12em';\n body.style.wordSpacing = '0.16em';\n } else {\n body.style.letterSpacing = '';\n body.style.wordSpacing = '';\n }\n\n body.style.lineHeight = prefs.lineHeight === 'increased' ? '1.6' : '';\n }\n}\n\ninterface PreferencesContextValue {\n preferences: AccessibilityPreferences;\n setPreferences: (\n updater:\n | Partial<AccessibilityPreferences>\n | ((p: AccessibilityPreferences) => AccessibilityPreferences)\n ) => void;\n}\n\nconst PreferencesContext = React.createContext<PreferencesContextValue | null>(\n null\n);\n\nexport function useA11YPreferences() {\n const ctx = React.useContext(PreferencesContext);\n if (!ctx)\n throw new Error(\n 'useA11YPreferences must be used within A11YPreferencesProvider'\n );\n return ctx;\n}\n\nexport function A11YPreferencesProvider({\n children,\n}: {\n children: React.ReactNode;\n}) {\n const [preferences, setPreferencesState] =\n React.useState<AccessibilityPreferences>(DEFAULT_PREFERENCES);\n const [hydrated, setHydrated] = React.useState(false);\n\n React.useEffect(() => {\n const stored = getStoredPreferences();\n const next = stored ?? DEFAULT_PREFERENCES;\n setPreferencesState(next);\n setHydrated(true);\n applyCssVariables(next);\n }, []);\n\n const setPreferences = React.useCallback<\n PreferencesContextValue['setPreferences']\n >((updater) => {\n setPreferencesState((prev) => {\n const next =\n typeof updater === 'function' ? updater(prev) : { ...prev, ...updater };\n savePreferences(next);\n applyCssVariables(next);\n try {\n if (typeof window !== 'undefined') {\n const changed: Partial<AccessibilityPreferences> = {};\n for (const key of Object.keys(\n next\n ) as (keyof AccessibilityPreferences)[]) {\n if (next[key] !== prev[key]) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n changed[key] = next[key] as any;\n }\n }\n window.dispatchEvent(\n new CustomEvent('a11y:pref_changed', {\n detail: {\n previous: prev,\n current: next,\n changed,\n },\n })\n );\n }\n } catch {\n /* noop */\n }\n return next;\n });\n }, []);\n\n const value = React.useMemo(\n () => ({ preferences, setPreferences }),\n [preferences, setPreferences]\n );\n\n return (\n <PreferencesContext value={value}>\n {children}\n {!hydrated ? null : null}\n </PreferencesContext>\n );\n}\n\n// Helper to compute className additions that respect tokens (optional)\nexport function a11yRootClassName() {\n return 'a11y-root';\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/lib.accessibility",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"description": "WCAG compliance utilities and validators",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contractspec",
|
|
@@ -23,14 +23,15 @@
|
|
|
23
23
|
"lint:check": "eslint src"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@contractspec/lib.design-system": "1.
|
|
27
|
-
"@contractspec/lib.ui-kit": "1.
|
|
28
|
-
"@contractspec/lib.ui-kit-web": "1.
|
|
26
|
+
"@contractspec/lib.design-system": "1.47.0",
|
|
27
|
+
"@contractspec/lib.ui-kit": "1.47.0",
|
|
28
|
+
"@contractspec/lib.ui-kit-web": "1.47.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@contractspec/tool.tsdown": "1.
|
|
32
|
-
"@contractspec/tool.typescript": "1.
|
|
33
|
-
"
|
|
31
|
+
"@contractspec/tool.tsdown": "1.47.0",
|
|
32
|
+
"@contractspec/tool.typescript": "1.47.0",
|
|
33
|
+
"react-native-css": "^3.0.0",
|
|
34
|
+
"tsdown": "^0.19.0",
|
|
34
35
|
"typescript": "^5.9.3"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
@@ -38,8 +39,6 @@
|
|
|
38
39
|
"next": "16.1.1"
|
|
39
40
|
},
|
|
40
41
|
"type": "module",
|
|
41
|
-
"main": "./dist/index.js",
|
|
42
|
-
"module": "./dist/index.js",
|
|
43
42
|
"types": "./dist/index.d.ts",
|
|
44
43
|
"sideEffects": [
|
|
45
44
|
"./dist/index.js",
|