import { Singleton } from '@ephox/katamari'; import { Chain } from '../api/Chain'; import * as GeneralSteps from '../api/GeneralSteps'; import type { Step } from '../api/Step'; import { createFileList } from './FileList'; interface Props { files: PropertyDescriptor; click: () => void; } const inputPrototypeState = Singleton.value(); const createChangeEvent = (win: Window): Event => { const event: any = document.createEvent('CustomEvent'); event.initCustomEvent('change', true, true, null); event.view = win; event.ctrlKey = false; event.altKey = false; event.shiftKey = false; event.metaKey = false; event.button = 0; event.relatedTarget = null; event.screenX = 0; event.screenY = 0; return event; }; const cPatchInputElement = (files: File[]) => Chain.op(() => { const HTMLInputElement = window.HTMLInputElement; const currentProps = { files: Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'files'), // eslint-disable-next-line @typescript-eslint/unbound-method click: HTMLInputElement.prototype.click }; inputPrototypeState.set(currentProps); Object.defineProperty(HTMLInputElement.prototype, 'files', { get: () => createFileList(files) }); HTMLInputElement.prototype.click = function () { this.dispatchEvent(createChangeEvent(this.ownerDocument.defaultView)); }; }); const cUnpatchInputElement = Chain.op(() => { const HTMLInputElement = window.HTMLInputElement; inputPrototypeState.on((props) => { Object.defineProperty(HTMLInputElement.prototype, 'files', props.files); HTMLInputElement.prototype.click = props.click; }); }); const sRunOnPatchedFileInput = (files: File[], step: Step): Step => GeneralSteps.sequence([ Chain.asStep({}, [ cPatchInputElement(files) ]), step, Chain.asStep({}, [ cUnpatchInputElement ]) ]); const cRunOnPatchedFileInput = (files: File[], chain: Chain): Chain => Chain.fromChains([ cPatchInputElement(files), chain, cUnpatchInputElement ]); const pRunOnPatchedFileInput = (files: File[], action: () => Promise): Promise => Chain.toPromise(cRunOnPatchedFileInput(files, Chain.fromPromise(action)))(undefined); export { sRunOnPatchedFileInput, cRunOnPatchedFileInput, pRunOnPatchedFileInput };