87 lines
3.0 KiB
JavaScript
87 lines
3.0 KiB
JavaScript
'use client';
|
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
import { createContext, use, useCallback, useEffect, useState } from 'react';
|
|
import { A11Y_COOKIE, A11Y_COOKIE_MAX_AGE, A11Y_DEFAULT, a11yAttributes, parseA11y, serializeA11y } from './state.js';
|
|
const A11yContext = /*#__PURE__*/ createContext(null);
|
|
function readCookie(name) {
|
|
if (typeof document === 'undefined') {
|
|
return undefined;
|
|
}
|
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
return match ? decodeURIComponent(match[1]) : undefined;
|
|
}
|
|
/**
|
|
* Provides accessibility preferences, persists them in a cookie, and applies them
|
|
* as data-attributes on <html> so the project's CSS can react. Like
|
|
* ConsentProvider for cookies — wrap the app once; the widget/button consume it.
|
|
*
|
|
* The plugin ships NO styles: it only sets attributes (data-a11y-*). The project
|
|
* writes CSS for those it supports (see docs/accessibility.md). This keeps the
|
|
* design in the project's hands.
|
|
*
|
|
* // layout.tsx
|
|
* import { AccessibilityProvider } from '@intecion/ipal-kit/client'
|
|
* <AccessibilityProvider>{children}</AccessibilityProvider>
|
|
*
|
|
* To avoid a flash, the project can read the a11y-prefs cookie server-side and
|
|
* set the attributes on <html> during SSR (see docs). This provider re-applies
|
|
* on the client and keeps them in sync.
|
|
*/ export function AccessibilityProvider({ children }) {
|
|
const [state, setState] = useState(A11Y_DEFAULT);
|
|
// Hydrate from cookie on mount.
|
|
useEffect(()=>{
|
|
setState(parseA11y(readCookie(A11Y_COOKIE)));
|
|
}, []);
|
|
// Apply attributes to <html> whenever state changes.
|
|
useEffect(()=>{
|
|
const el = document.documentElement;
|
|
const attrs = a11yAttributes(state);
|
|
for (const [attr, value] of Object.entries(attrs)){
|
|
if (value === null) {
|
|
el.removeAttribute(attr);
|
|
} else {
|
|
el.setAttribute(attr, value);
|
|
}
|
|
}
|
|
}, [
|
|
state
|
|
]);
|
|
const persist = useCallback((next)=>{
|
|
document.cookie = `${A11Y_COOKIE}=${encodeURIComponent(serializeA11y(next))}; path=/; max-age=${A11Y_COOKIE_MAX_AGE}; samesite=lax`;
|
|
}, []);
|
|
const set = useCallback((key, value)=>{
|
|
setState((prev)=>{
|
|
const next = {
|
|
...prev,
|
|
[key]: value
|
|
};
|
|
persist(next);
|
|
return next;
|
|
});
|
|
}, [
|
|
persist
|
|
]);
|
|
const reset = useCallback(()=>{
|
|
setState(A11Y_DEFAULT);
|
|
persist(A11Y_DEFAULT);
|
|
}, [
|
|
persist
|
|
]);
|
|
return /*#__PURE__*/ _jsx(A11yContext, {
|
|
value: {
|
|
reset,
|
|
set,
|
|
state
|
|
},
|
|
children: children
|
|
});
|
|
}
|
|
/** Access accessibility preferences + setters. Use inside AccessibilityProvider. */ export function useAccessibility() {
|
|
const ctx = use(A11yContext);
|
|
if (!ctx) {
|
|
throw new Error('useAccessibility must be used within <AccessibilityProvider>');
|
|
}
|
|
return ctx;
|
|
}
|
|
|
|
//# sourceMappingURL=AccessibilityProvider.js.map
|