Files
Foundry-VTT-Docker/resources/app/node_modules/@pixi/accessibility/lib/AccessibilityManager.mjs.map
2025-01-04 00:34:03 +01:00

1 line
25 KiB
Plaintext

{"version":3,"file":"AccessibilityManager.mjs","sources":["../src/AccessibilityManager.ts"],"sourcesContent":["import { extensions, ExtensionType, utils } from '@pixi/core';\nimport { DisplayObject } from '@pixi/display';\nimport { FederatedEvent } from '@pixi/events';\nimport { accessibleTarget } from './accessibleTarget';\n\nimport type { ExtensionMetadata, IRenderer, Rectangle } from '@pixi/core';\nimport type { Container } from '@pixi/display';\nimport type { IAccessibleHTMLElement } from './accessibleTarget';\n\n// add some extra variables to the container..\nDisplayObject.mixin(accessibleTarget);\n\nconst KEY_CODE_TAB = 9;\n\nconst DIV_TOUCH_SIZE = 100;\nconst DIV_TOUCH_POS_X = 0;\nconst DIV_TOUCH_POS_Y = 0;\nconst DIV_TOUCH_ZINDEX = 2;\n\nconst DIV_HOOK_SIZE = 1;\nconst DIV_HOOK_POS_X = -1000;\nconst DIV_HOOK_POS_Y = -1000;\nconst DIV_HOOK_ZINDEX = 2;\n\n/**\n * The Accessibility manager recreates the ability to tab and have content read by screen readers.\n * This is very important as it can possibly help people with disabilities access PixiJS content.\n *\n * A DisplayObject can be made accessible just like it can be made interactive. This manager will map the\n * events as if the mouse was being used, minimizing the effort required to implement.\n *\n * An instance of this class is automatically created by default, and can be found at `renderer.plugins.accessibility`\n * @class\n * @memberof PIXI\n */\nexport class AccessibilityManager\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n name: 'accessibility',\n type: [\n ExtensionType.RendererPlugin,\n ExtensionType.CanvasRendererPlugin,\n ],\n };\n\n /** Setting this to true will visually show the divs. */\n public debug = false;\n\n /**\n * The renderer this accessibility manager works for.\n * @type {PIXI.CanvasRenderer|PIXI.Renderer}\n */\n public renderer: IRenderer;\n\n /** Internal variable, see isActive getter. */\n private _isActive = false;\n\n /** Internal variable, see isMobileAccessibility getter. */\n private _isMobileAccessibility = false;\n\n /** Button element for handling touch hooks. */\n private _hookDiv: HTMLElement;\n\n /** This is the dom element that will sit over the PixiJS element. This is where the div overlays will go. */\n private div: HTMLElement;\n\n /** A simple pool for storing divs. */\n private pool: IAccessibleHTMLElement[] = [];\n\n /** This is a tick used to check if an object is no longer being rendered. */\n private renderId = 0;\n\n /** The array of currently active accessible items. */\n private children: DisplayObject[] = [];\n\n /** Count to throttle div updates on android devices. */\n private androidUpdateCount = 0;\n\n /** The frequency to update the div elements. */\n private androidUpdateFrequency = 500; // 2fps\n\n /**\n * @param {PIXI.CanvasRenderer|PIXI.Renderer} renderer - A reference to the current renderer\n */\n constructor(renderer: IRenderer)\n {\n this._hookDiv = null;\n\n if (utils.isMobile.tablet || utils.isMobile.phone)\n {\n this.createTouchHook();\n }\n\n // first we create a div that will sit over the PixiJS element. This is where the div overlays will go.\n const div = document.createElement('div');\n\n div.style.width = `${DIV_TOUCH_SIZE}px`;\n div.style.height = `${DIV_TOUCH_SIZE}px`;\n div.style.position = 'absolute';\n div.style.top = `${DIV_TOUCH_POS_X}px`;\n div.style.left = `${DIV_TOUCH_POS_Y}px`;\n div.style.zIndex = DIV_TOUCH_ZINDEX.toString();\n\n this.div = div;\n this.renderer = renderer;\n\n /**\n * pre-bind the functions\n * @type {Function}\n * @private\n */\n this._onKeyDown = this._onKeyDown.bind(this);\n\n /**\n * pre-bind the functions\n * @type {Function}\n * @private\n */\n this._onMouseMove = this._onMouseMove.bind(this);\n\n // let listen for tab.. once pressed we can fire up and show the accessibility layer\n globalThis.addEventListener('keydown', this._onKeyDown, false);\n }\n\n /**\n * Value of `true` if accessibility is currently active and accessibility layers are showing.\n * @member {boolean}\n * @readonly\n */\n get isActive(): boolean\n {\n return this._isActive;\n }\n\n /**\n * Value of `true` if accessibility is enabled for touch devices.\n * @member {boolean}\n * @readonly\n */\n get isMobileAccessibility(): boolean\n {\n return this._isMobileAccessibility;\n }\n\n /**\n * Creates the touch hooks.\n * @private\n */\n private createTouchHook(): void\n {\n const hookDiv = document.createElement('button');\n\n hookDiv.style.width = `${DIV_HOOK_SIZE}px`;\n hookDiv.style.height = `${DIV_HOOK_SIZE}px`;\n hookDiv.style.position = 'absolute';\n hookDiv.style.top = `${DIV_HOOK_POS_X}px`;\n hookDiv.style.left = `${DIV_HOOK_POS_Y}px`;\n hookDiv.style.zIndex = DIV_HOOK_ZINDEX.toString();\n hookDiv.style.backgroundColor = '#FF0000';\n hookDiv.title = 'select to enable accessibility for this content';\n\n hookDiv.addEventListener('focus', () =>\n {\n this._isMobileAccessibility = true;\n this.activate();\n this.destroyTouchHook();\n });\n\n document.body.appendChild(hookDiv);\n this._hookDiv = hookDiv;\n }\n\n /**\n * Destroys the touch hooks.\n * @private\n */\n private destroyTouchHook(): void\n {\n if (!this._hookDiv)\n {\n return;\n }\n document.body.removeChild(this._hookDiv);\n this._hookDiv = null;\n }\n\n /**\n * Activating will cause the Accessibility layer to be shown.\n * This is called when a user presses the tab key.\n * @private\n */\n private activate(): void\n {\n if (this._isActive)\n {\n return;\n }\n\n this._isActive = true;\n\n globalThis.document.addEventListener('mousemove', this._onMouseMove, true);\n globalThis.removeEventListener('keydown', this._onKeyDown, false);\n\n this.renderer.on('postrender', this.update, this);\n this.renderer.view.parentNode?.appendChild(this.div);\n }\n\n /**\n * Deactivating will cause the Accessibility layer to be hidden.\n * This is called when a user moves the mouse.\n * @private\n */\n private deactivate(): void\n {\n if (!this._isActive || this._isMobileAccessibility)\n {\n return;\n }\n\n this._isActive = false;\n\n globalThis.document.removeEventListener('mousemove', this._onMouseMove, true);\n globalThis.addEventListener('keydown', this._onKeyDown, false);\n\n this.renderer.off('postrender', this.update);\n this.div.parentNode?.removeChild(this.div);\n }\n\n /**\n * This recursive function will run through the scene graph and add any new accessible objects to the DOM layer.\n * @private\n * @param {PIXI.Container} displayObject - The DisplayObject to check.\n */\n private updateAccessibleObjects(displayObject: Container): void\n {\n if (!displayObject.visible || !displayObject.accessibleChildren)\n {\n return;\n }\n\n if (displayObject.accessible && displayObject.isInteractive())\n {\n if (!displayObject._accessibleActive)\n {\n this.addChild(displayObject);\n }\n\n displayObject.renderId = this.renderId;\n }\n\n const children = displayObject.children;\n\n if (children)\n {\n for (let i = 0; i < children.length; i++)\n {\n this.updateAccessibleObjects(children[i] as Container);\n }\n }\n }\n\n /**\n * Before each render this function will ensure that all divs are mapped correctly to their DisplayObjects.\n * @private\n */\n private update(): void\n {\n /* On Android default web browser, tab order seems to be calculated by position rather than tabIndex,\n * moving buttons can cause focus to flicker between two buttons making it hard/impossible to navigate,\n * so I am just running update every half a second, seems to fix it.\n */\n const now = performance.now();\n\n if (utils.isMobile.android.device && now < this.androidUpdateCount)\n {\n return;\n }\n\n this.androidUpdateCount = now + this.androidUpdateFrequency;\n\n if (!this.renderer.renderingToScreen)\n {\n return;\n }\n\n // update children...\n if (this.renderer.lastObjectRendered)\n {\n this.updateAccessibleObjects(this.renderer.lastObjectRendered as Container);\n }\n\n const { x, y, width, height } = this.renderer.view.getBoundingClientRect();\n const { width: viewWidth, height: viewHeight, resolution } = this.renderer;\n\n const sx = (width / viewWidth) * resolution;\n const sy = (height / viewHeight) * resolution;\n\n let div = this.div;\n\n div.style.left = `${x}px`;\n div.style.top = `${y}px`;\n div.style.width = `${viewWidth}px`;\n div.style.height = `${viewHeight}px`;\n\n for (let i = 0; i < this.children.length; i++)\n {\n const child = this.children[i];\n\n if (child.renderId !== this.renderId)\n {\n child._accessibleActive = false;\n\n utils.removeItems(this.children, i, 1);\n this.div.removeChild(child._accessibleDiv);\n this.pool.push(child._accessibleDiv);\n child._accessibleDiv = null;\n\n i--;\n }\n else\n {\n // map div to display..\n div = child._accessibleDiv;\n let hitArea = child.hitArea as Rectangle;\n const wt = child.worldTransform;\n\n if (child.hitArea)\n {\n div.style.left = `${(wt.tx + (hitArea.x * wt.a)) * sx}px`;\n div.style.top = `${(wt.ty + (hitArea.y * wt.d)) * sy}px`;\n\n div.style.width = `${hitArea.width * wt.a * sx}px`;\n div.style.height = `${hitArea.height * wt.d * sy}px`;\n }\n else\n {\n hitArea = child.getBounds();\n\n this.capHitArea(hitArea);\n\n div.style.left = `${hitArea.x * sx}px`;\n div.style.top = `${hitArea.y * sy}px`;\n\n div.style.width = `${hitArea.width * sx}px`;\n div.style.height = `${hitArea.height * sy}px`;\n\n // update button titles and hints if they exist and they've changed\n if (div.title !== child.accessibleTitle && child.accessibleTitle !== null)\n {\n div.title = child.accessibleTitle;\n }\n if (div.getAttribute('aria-label') !== child.accessibleHint\n && child.accessibleHint !== null)\n {\n div.setAttribute('aria-label', child.accessibleHint);\n }\n }\n\n // the title or index may have changed, if so lets update it!\n if (child.accessibleTitle !== div.title || child.tabIndex !== div.tabIndex)\n {\n div.title = child.accessibleTitle;\n div.tabIndex = child.tabIndex;\n if (this.debug) this.updateDebugHTML(div);\n }\n }\n }\n\n // increment the render id..\n this.renderId++;\n }\n\n /**\n * private function that will visually add the information to the\n * accessability div\n * @param {HTMLElement} div -\n */\n public updateDebugHTML(div: IAccessibleHTMLElement): void\n {\n div.innerHTML = `type: ${div.type}</br> title : ${div.title}</br> tabIndex: ${div.tabIndex}`;\n }\n\n /**\n * Adjust the hit area based on the bounds of a display object\n * @param {PIXI.Rectangle} hitArea - Bounds of the child\n */\n public capHitArea(hitArea: Rectangle): void\n {\n if (hitArea.x < 0)\n {\n hitArea.width += hitArea.x;\n hitArea.x = 0;\n }\n\n if (hitArea.y < 0)\n {\n hitArea.height += hitArea.y;\n hitArea.y = 0;\n }\n\n const { width: viewWidth, height: viewHeight } = this.renderer;\n\n if (hitArea.x + hitArea.width > viewWidth)\n {\n hitArea.width = viewWidth - hitArea.x;\n }\n\n if (hitArea.y + hitArea.height > viewHeight)\n {\n hitArea.height = viewHeight - hitArea.y;\n }\n }\n\n /**\n * Adds a DisplayObject to the accessibility manager\n * @private\n * @param {PIXI.DisplayObject} displayObject - The child to make accessible.\n */\n private addChild<T extends DisplayObject>(displayObject: T): void\n {\n // this.activate();\n\n let div = this.pool.pop();\n\n if (!div)\n {\n div = document.createElement('button');\n\n div.style.width = `${DIV_TOUCH_SIZE}px`;\n div.style.height = `${DIV_TOUCH_SIZE}px`;\n div.style.backgroundColor = this.debug ? 'rgba(255,255,255,0.5)' : 'transparent';\n div.style.position = 'absolute';\n div.style.zIndex = DIV_TOUCH_ZINDEX.toString();\n div.style.borderStyle = 'none';\n\n // ARIA attributes ensure that button title and hint updates are announced properly\n if (navigator.userAgent.toLowerCase().includes('chrome'))\n {\n // Chrome doesn't need aria-live to work as intended; in fact it just gets more confused.\n div.setAttribute('aria-live', 'off');\n }\n else\n {\n div.setAttribute('aria-live', 'polite');\n }\n\n if (navigator.userAgent.match(/rv:.*Gecko\\//))\n {\n // FireFox needs this to announce only the new button name\n div.setAttribute('aria-relevant', 'additions');\n }\n else\n {\n // required by IE, other browsers don't much care\n div.setAttribute('aria-relevant', 'text');\n }\n\n div.addEventListener('click', this._onClick.bind(this));\n div.addEventListener('focus', this._onFocus.bind(this));\n div.addEventListener('focusout', this._onFocusOut.bind(this));\n }\n\n // set pointer events\n div.style.pointerEvents = displayObject.accessiblePointerEvents;\n // set the type, this defaults to button!\n div.type = displayObject.accessibleType;\n\n if (displayObject.accessibleTitle && displayObject.accessibleTitle !== null)\n {\n div.title = displayObject.accessibleTitle;\n }\n else if (!displayObject.accessibleHint\n || displayObject.accessibleHint === null)\n {\n div.title = `displayObject ${displayObject.tabIndex}`;\n }\n\n if (displayObject.accessibleHint\n && displayObject.accessibleHint !== null)\n {\n div.setAttribute('aria-label', displayObject.accessibleHint);\n }\n\n if (this.debug) this.updateDebugHTML(div);\n\n displayObject._accessibleActive = true;\n displayObject._accessibleDiv = div;\n div.displayObject = displayObject;\n\n this.children.push(displayObject);\n this.div.appendChild(displayObject._accessibleDiv);\n displayObject._accessibleDiv.tabIndex = displayObject.tabIndex;\n }\n\n /**\n * Dispatch events with the EventSystem.\n * @param e\n * @param type\n * @private\n */\n private _dispatchEvent(e: UIEvent, type: string[]): void\n {\n const { displayObject: target } = e.target as IAccessibleHTMLElement;\n const boundry = this.renderer.events.rootBoundary;\n const event: FederatedEvent = Object.assign(new FederatedEvent(boundry), { target });\n\n boundry.rootTarget = this.renderer.lastObjectRendered as DisplayObject;\n type.forEach((type) => boundry.dispatchEvent(event, type));\n }\n\n /**\n * Maps the div button press to pixi's EventSystem (click)\n * @private\n * @param {MouseEvent} e - The click event.\n */\n private _onClick(e: MouseEvent): void\n {\n this._dispatchEvent(e, ['click', 'pointertap', 'tap']);\n }\n\n /**\n * Maps the div focus events to pixi's EventSystem (mouseover)\n * @private\n * @param {FocusEvent} e - The focus event.\n */\n private _onFocus(e: FocusEvent): void\n {\n if (!(e.target as Element).getAttribute('aria-live'))\n {\n (e.target as Element).setAttribute('aria-live', 'assertive');\n }\n\n this._dispatchEvent(e, ['mouseover']);\n }\n\n /**\n * Maps the div focus events to pixi's EventSystem (mouseout)\n * @private\n * @param {FocusEvent} e - The focusout event.\n */\n private _onFocusOut(e: FocusEvent): void\n {\n if (!(e.target as Element).getAttribute('aria-live'))\n {\n (e.target as Element).setAttribute('aria-live', 'polite');\n }\n\n this._dispatchEvent(e, ['mouseout']);\n }\n\n /**\n * Is called when a key is pressed\n * @private\n * @param {KeyboardEvent} e - The keydown event.\n */\n private _onKeyDown(e: KeyboardEvent): void\n {\n if (e.keyCode !== KEY_CODE_TAB)\n {\n return;\n }\n\n this.activate();\n }\n\n /**\n * Is called when the mouse moves across the renderer element\n * @private\n * @param {MouseEvent} e - The mouse event.\n */\n private _onMouseMove(e: MouseEvent): void\n {\n if (e.movementX === 0 && e.movementY === 0)\n {\n return;\n }\n\n this.deactivate();\n }\n\n /** Destroys the accessibility manager */\n public destroy(): void\n {\n this.destroyTouchHook();\n this.div = null;\n\n globalThis.document.removeEventListener('mousemove', this._onMouseMove, true);\n globalThis.removeEventListener('keydown', this._onKeyDown);\n\n this.pool = null;\n this.children = null;\n this.renderer = null;\n }\n}\n\nextensions.add(AccessibilityManager);\n"],"names":["type"],"mappings":"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"}