@neuroequality/neuroadapt-mobile
Version:
Mobile accessibility features for React Native and cross-platform apps
546 lines (545 loc) • 20.8 kB
JavaScript
import require$$0, { createContext, useState, useEffect, useContext } from "react";
import { useColorScheme, AccessibilityInfo, Platform, Dimensions } from "react-native";
var jsxRuntime = { exports: {} };
var reactJsxRuntime_production = {};
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactJsxRuntime_production;
function requireReactJsxRuntime_production() {
if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
hasRequiredReactJsxRuntime_production = 1;
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
function jsxProd(type, config, maybeKey) {
var key = null;
void 0 !== maybeKey && (key = "" + maybeKey);
void 0 !== config.key && (key = "" + config.key);
if ("key" in config) {
maybeKey = {};
for (var propName in config)
"key" !== propName && (maybeKey[propName] = config[propName]);
} else maybeKey = config;
config = maybeKey.ref;
return {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
ref: void 0 !== config ? config : null,
props: maybeKey
};
}
reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
reactJsxRuntime_production.jsx = jsxProd;
reactJsxRuntime_production.jsxs = jsxProd;
return reactJsxRuntime_production;
}
var reactJsxRuntime_development = {};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactJsxRuntime_development;
function requireReactJsxRuntime_development() {
if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
hasRequiredReactJsxRuntime_development = 1;
"production" !== process.env.NODE_ENV && function() {
function getComponentNameFromType(type) {
if (null == type) return null;
if ("function" === typeof type)
return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
if ("string" === typeof type) return type;
switch (type) {
case REACT_FRAGMENT_TYPE:
return "Fragment";
case REACT_PROFILER_TYPE:
return "Profiler";
case REACT_STRICT_MODE_TYPE:
return "StrictMode";
case REACT_SUSPENSE_TYPE:
return "Suspense";
case REACT_SUSPENSE_LIST_TYPE:
return "SuspenseList";
case REACT_ACTIVITY_TYPE:
return "Activity";
}
if ("object" === typeof type)
switch ("number" === typeof type.tag && console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
), type.$$typeof) {
case REACT_PORTAL_TYPE:
return "Portal";
case REACT_CONTEXT_TYPE:
return (type.displayName || "Context") + ".Provider";
case REACT_CONSUMER_TYPE:
return (type._context.displayName || "Context") + ".Consumer";
case REACT_FORWARD_REF_TYPE:
var innerType = type.render;
type = type.displayName;
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
return type;
case REACT_MEMO_TYPE:
return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
case REACT_LAZY_TYPE:
innerType = type._payload;
type = type._init;
try {
return getComponentNameFromType(type(innerType));
} catch (x) {
}
}
return null;
}
function testStringCoercion(value) {
return "" + value;
}
function checkKeyStringCoercion(value) {
try {
testStringCoercion(value);
var JSCompiler_inline_result = false;
} catch (e) {
JSCompiler_inline_result = true;
}
if (JSCompiler_inline_result) {
JSCompiler_inline_result = console;
var JSCompiler_temp_const = JSCompiler_inline_result.error;
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
JSCompiler_temp_const.call(
JSCompiler_inline_result,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
JSCompiler_inline_result$jscomp$0
);
return testStringCoercion(value);
}
}
function getTaskName(type) {
if (type === REACT_FRAGMENT_TYPE) return "<>";
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE)
return "<...>";
try {
var name = getComponentNameFromType(type);
return name ? "<" + name + ">" : "<...>";
} catch (x) {
return "<...>";
}
}
function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
function UnknownOwner() {
return Error("react-stack-top-frame");
}
function hasValidKey(config) {
if (hasOwnProperty.call(config, "key")) {
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
if (getter && getter.isReactWarning) return false;
}
return void 0 !== config.key;
}
function defineKeyPropWarningGetter(props, displayName) {
function warnAboutAccessingKey() {
specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
displayName
));
}
warnAboutAccessingKey.isReactWarning = true;
Object.defineProperty(props, "key", {
get: warnAboutAccessingKey,
configurable: true
});
}
function elementRefGetterWithDeprecationWarning() {
var componentName = getComponentNameFromType(this.type);
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
));
componentName = this.props.ref;
return void 0 !== componentName ? componentName : null;
}
function ReactElement(type, key, self, source, owner, props, debugStack, debugTask) {
self = props.ref;
type = {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
props,
_owner: owner
};
null !== (void 0 !== self ? self : null) ? Object.defineProperty(type, "ref", {
enumerable: false,
get: elementRefGetterWithDeprecationWarning
}) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
type._store = {};
Object.defineProperty(type._store, "validated", {
configurable: false,
enumerable: false,
writable: true,
value: 0
});
Object.defineProperty(type, "_debugInfo", {
configurable: false,
enumerable: false,
writable: true,
value: null
});
Object.defineProperty(type, "_debugStack", {
configurable: false,
enumerable: false,
writable: true,
value: debugStack
});
Object.defineProperty(type, "_debugTask", {
configurable: false,
enumerable: false,
writable: true,
value: debugTask
});
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
return type;
}
function jsxDEVImpl(type, config, maybeKey, isStaticChildren, source, self, debugStack, debugTask) {
var children = config.children;
if (void 0 !== children)
if (isStaticChildren)
if (isArrayImpl(children)) {
for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++)
validateChildKeys(children[isStaticChildren]);
Object.freeze && Object.freeze(children);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else validateChildKeys(children);
if (hasOwnProperty.call(config, "key")) {
children = getComponentNameFromType(type);
var keys = Object.keys(config).filter(function(k) {
return "key" !== k;
});
isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error(
'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
isStaticChildren,
children,
keys,
children
), didWarnAboutKeySpread[children + isStaticChildren] = true);
}
children = null;
void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
if ("key" in config) {
maybeKey = {};
for (var propName in config)
"key" !== propName && (maybeKey[propName] = config[propName]);
} else maybeKey = config;
children && defineKeyPropWarningGetter(
maybeKey,
"function" === typeof type ? type.displayName || type.name || "Unknown" : type
);
return ReactElement(
type,
children,
self,
source,
getOwner(),
maybeKey,
debugStack,
debugTask
);
}
function validateChildKeys(node) {
"object" === typeof node && null !== node && node.$$typeof === REACT_ELEMENT_TYPE && node._store && (node._store.validated = 1);
}
var React = require$$0, REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler");
var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
return null;
};
React = {
"react-stack-bottom-frame": function(callStackForError) {
return callStackForError();
}
};
var specialPropKeyWarningShown;
var didWarnAboutElementRef = {};
var unknownOwnerDebugStack = React["react-stack-bottom-frame"].bind(
React,
UnknownOwner
)();
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
var didWarnAboutKeySpread = {};
reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
reactJsxRuntime_development.jsx = function(type, config, maybeKey, source, self) {
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
return jsxDEVImpl(
type,
config,
maybeKey,
false,
source,
self,
trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
);
};
reactJsxRuntime_development.jsxs = function(type, config, maybeKey, source, self) {
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
return jsxDEVImpl(
type,
config,
maybeKey,
true,
source,
self,
trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
);
};
}();
return reactJsxRuntime_development;
}
if (process.env.NODE_ENV === "production") {
jsxRuntime.exports = requireReactJsxRuntime_production();
} else {
jsxRuntime.exports = requireReactJsxRuntime_development();
}
var jsxRuntimeExports = jsxRuntime.exports;
const MobileAccessibilityContext = createContext(null);
const MobileAccessibilityProvider = ({
children,
initialPreferences,
onPreferencesChange,
hapticEnabled = true,
announcements = true
}) => {
const [state, setState] = useState({
screenReader: {
enabled: false,
type: null
},
reduceMotion: false,
reduceTransparency: false,
boldText: false,
largeText: false,
highContrast: false,
colorScheme: useColorScheme(),
deviceOrientation: "portrait",
screenSize: "medium",
hapticFeedback: hapticEnabled,
voiceControl: false,
grayscale: false
});
const [preferences, setPreferences] = useState(initialPreferences || null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeAccessibilityState = async () => {
try {
const screenReaderEnabled = await AccessibilityInfo.isScreenReaderEnabled();
const screenReaderType = Platform.OS === "ios" ? "voiceover" : "talkback";
const reduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled?.() || false;
let reduceTransparency = false;
let boldText = false;
let grayscale = false;
if (Platform.OS === "ios") {
reduceTransparency = await AccessibilityInfo.isReduceTransparencyEnabled?.() || false;
boldText = await AccessibilityInfo.isBoldTextEnabled?.() || false;
grayscale = await AccessibilityInfo.isGrayscaleEnabled?.() || false;
}
const { width, height } = Dimensions.get("window");
const screenSize = classifyScreenSize(width, height);
const deviceOrientation = width > height ? "landscape" : "portrait";
setState((prevState) => ({
...prevState,
screenReader: {
enabled: screenReaderEnabled,
type: screenReaderEnabled ? screenReaderType : null
},
reduceMotion: reduceMotionEnabled,
reduceTransparency,
boldText,
grayscale,
deviceOrientation,
screenSize
}));
setIsLoading(false);
} catch (error) {
console.warn("Error initializing accessibility state:", error);
setIsLoading(false);
}
};
initializeAccessibilityState();
const screenReaderListener = AccessibilityInfo.addEventListener(
"screenReaderChanged",
(enabled) => {
setState((prevState) => ({
...prevState,
screenReader: {
enabled,
type: enabled ? Platform.OS === "ios" ? "voiceover" : "talkback" : null
}
}));
}
);
const reduceMotionListener = AccessibilityInfo.addEventListener(
"reduceMotionChanged",
(enabled) => {
setState((prevState) => ({
...prevState,
reduceMotion: enabled
}));
}
);
const dimensionsListener = Dimensions.addEventListener("change", ({ window }) => {
const newOrientation = window.width > window.height ? "landscape" : "portrait";
const newScreenSize = classifyScreenSize(window.width, window.height);
setState((prevState) => ({
...prevState,
deviceOrientation: newOrientation,
screenSize: newScreenSize
}));
});
return () => {
screenReaderListener?.remove();
reduceMotionListener?.remove();
dimensionsListener?.remove();
};
}, []);
const actions = {
updatePreferences: (newPreferences) => {
const updatedPreferences = {
...preferences,
...newPreferences,
lastUpdated: /* @__PURE__ */ new Date()
};
setPreferences(updatedPreferences);
onPreferencesChange?.(updatedPreferences);
},
announceForAccessibility: (message) => {
if (announcements && state.screenReader.enabled) {
AccessibilityInfo.announceForAccessibility(message);
}
},
setFocusToElement: (elementRef) => {
if (elementRef && elementRef.current) {
AccessibilityInfo.setAccessibilityFocus(elementRef.current);
}
},
triggerHapticFeedback: (type) => {
if (!hapticEnabled || !state.hapticFeedback) return;
import("react-native").then(({ Haptics }) => {
if (Haptics) {
switch (type) {
case "light":
Haptics.impactAsync?.(Haptics.ImpactFeedbackStyle?.Light);
break;
case "medium":
Haptics.impactAsync?.(Haptics.ImpactFeedbackStyle?.Medium);
break;
case "heavy":
Haptics.impactAsync?.(Haptics.ImpactFeedbackStyle?.Heavy);
break;
case "selection":
Haptics.selectionAsync?.();
break;
}
}
}).catch(() => {
});
},
adjustFontSize: (scale) => {
actions.updatePreferences({
sensory: {
...preferences?.sensory,
fontSize: Math.max(12, Math.min(32, (preferences?.sensory?.fontSize || 16) * scale))
}
});
},
toggleHighContrast: () => {
actions.updatePreferences({
sensory: {
...preferences?.sensory,
highContrast: !preferences?.sensory?.highContrast
}
});
setState((prevState) => ({
...prevState,
highContrast: !prevState.highContrast
}));
},
toggleReduceMotion: () => {
actions.updatePreferences({
sensory: {
...preferences?.sensory,
motionReduction: !preferences?.sensory?.motionReduction
}
});
}
};
const contextValue = {
state,
actions,
preferences,
isLoading
};
return /* @__PURE__ */ jsxRuntimeExports.jsx(MobileAccessibilityContext.Provider, { value: contextValue, children });
};
const useMobileAccessibility = () => {
const context = useContext(MobileAccessibilityContext);
if (!context) {
throw new Error("useMobileAccessibility must be used within a MobileAccessibilityProvider");
}
return context;
};
const useScreenReader = () => {
const { state, actions } = useMobileAccessibility();
return {
isEnabled: state.screenReader.enabled,
type: state.screenReader.type,
announce: actions.announceForAccessibility,
setFocus: actions.setFocusToElement
};
};
const useHapticFeedback = () => {
const { state, actions } = useMobileAccessibility();
return {
isEnabled: state.hapticFeedback,
trigger: actions.triggerHapticFeedback
};
};
const useDeviceContext = () => {
const { state } = useMobileAccessibility();
return {
orientation: state.deviceOrientation,
screenSize: state.screenSize,
isLandscape: state.deviceOrientation === "landscape",
isPortrait: state.deviceOrientation === "portrait",
isSmallScreen: state.screenSize === "small",
isMediumScreen: state.screenSize === "medium",
isLargeScreen: state.screenSize === "large" || state.screenSize === "xlarge"
};
};
const classifyScreenSize = (width, height) => {
const maxDimension = Math.max(width, height);
if (maxDimension < 568) return "small";
if (maxDimension < 667) return "medium";
if (maxDimension < 896) return "large";
return "xlarge";
};
export {
MobileAccessibilityProvider as M,
useScreenReader as a,
useHapticFeedback as b,
useDeviceContext as c,
useMobileAccessibility as u
};