diff --git a/categories/web/action/react/package.json b/categories/web/action/react/package.json index 9bbbab4..5043c7d 100644 --- a/categories/web/action/react/package.json +++ b/categories/web/action/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/blob/react/package.json b/categories/web/blob/react/package.json index 816b394..d095d59 100644 --- a/categories/web/blob/react/package.json +++ b/categories/web/blob/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.test.tsx b/categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.test.tsx index 40e96d6..f83448e 100644 --- a/categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.test.tsx +++ b/categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.test.tsx @@ -3,6 +3,7 @@ import { render, screen, cleanup, + fireEvent, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { @@ -16,10 +17,48 @@ import matchers from '@testing-library/jest-dom/matchers'; import { FileSelectBox, FileSelectBoxDerivedElement, + DELETE_KEYS, SELECT_KEYS, } from '.'; expect.extend(matchers); +const userEventDrop = async ( + dropZoneElement: HTMLElement, + fileOrFiles: File | File[], + targetInputElement: HTMLInputElement, +) => { + const dummyInput = window.document.createElement('input'); + dummyInput.type = 'file'; + await userEvent.upload(dummyInput, fileOrFiles); + + // targeting change event on the input element + await userEvent.upload(targetInputElement, fileOrFiles); + + fireEvent.drop(dropZoneElement, { + dataTransfer: { + files: dummyInput.files, + }, + }); +}; + +const userEventPaste = async ( + dropZoneElement: HTMLElement, + fileOrFiles: File | File[], +) => { + const dummyInput = window.document.createElement('input'); + dummyInput.type = 'file'; + await userEvent.upload(dummyInput, fileOrFiles); + + // targeting change event on the input element + await userEvent.upload(dropZoneElement, fileOrFiles); + + fireEvent.paste(dropZoneElement, { + clipboardData: { + files: dummyInput.files, + }, + }); +}; + describe('FileSelectBox', () => { afterEach(() => { cleanup(); @@ -35,42 +74,82 @@ describe('FileSelectBox', () => { }); it('renders a border', () => { - render( - , - ); - const border = screen.getByTestId('border'); - expect(border).toBeInTheDocument(); - }); - - it('renders a label', () => { - render( - , - ); - const textbox = screen.getByLabelText('foo'); - expect(textbox).toBeInTheDocument(); - const label = screen.getByTestId('label'); - expect(label).toHaveTextContent('foo'); - }); - - it('renders a hidden label', () => { - render( - , - ); - const textbox = screen.getByLabelText('foo'); - expect(textbox).toBeInTheDocument(); - const label = screen.queryByTestId('label'); - expect(label).toBeInTheDocument(); - expect(label).toHaveClass('sr-only'); - }); - - describe('enhanced', () => { + render( + , + ); + const border = screen.getByTestId('border'); + expect(border).toBeInTheDocument(); + }); + + it('renders a block component', () => { + render( + , + ); + const root = screen.getByTestId('root'); + expect(root).toHaveClass('flex w-full'); + }); + + it('renders a label', () => { + render( + , + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.getByTestId('label'); + expect(label).toHaveTextContent('foo'); + }); + + it('renders a hidden label', () => { + render( + , + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.queryByTestId('label'); + expect(label).toBeInTheDocument(); + expect(label).toHaveClass('sr-only'); + }); + + it('handles a change event', async () => { + const onChange = vi.fn(); + + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + expect(onChange).toBeCalledTimes(1); + }); + + it('handles a blur event', async () => { + const onBlur = vi.fn(); + + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + input.focus(); + input.blur(); + expect(onBlur).toBeCalledTimes(1); + }); + + describe('when enhanced', () => { it('renders a hint', () => { render( { hint="foo" />, ); + const hint = screen.getByTestId('hint'); expect(hint).toBeInTheDocument(); }); + + it('renders a preview for a single file', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + expect(input.files).toHaveLength(1); + const preview = screen.getByTestId('preview'); + expect(preview).toBeInTheDocument(); + }); + + it('renders a preview for a single file without name', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new Blob(['foo'], {type: 'text/plain'}); + await userEvent.upload(input, file as unknown as File); + expect(input.files).toHaveLength(1); + const preview = screen.getByTestId('preview'); + expect(preview).toBeInTheDocument(); + }); + + it('renders a preview for a single file without name', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const { size: _size, ...partialFile } = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, partialFile as unknown as File); + expect(input.files).toHaveLength(1); + const preview = screen.getByTestId('preview'); + expect(preview).toBeInTheDocument(); + }); + + it('renders a preview for multiple files', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const files = [ + new File(['foo'], 'foo.txt', {type: 'text/plain'}), + new File(['bar'], 'bar.txt', {type: 'text/plain'}), + ]; + await userEvent.upload(input, files); + expect(input.files).toHaveLength(files.length); + const preview = screen.getByTestId('preview'); + expect(preview).toBeInTheDocument(); + }); + + it('renders a preview for multiple files without names', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const files = [ + new Blob(['foo'], {type: 'text/plain'}), + new Blob(['bar'], {type: 'text/plain'}), + ]; + await userEvent.upload(input, files as unknown as File[]); + expect(input.files).toHaveLength(files.length); + const preview = screen.getByTestId('preview'); + expect(preview).toBeInTheDocument(); + }); + + it('renders actions when at least one file is selected', async () => { + render( + , + ); + + const input = screen.getByTestId('input'); + const files = [ + new File(['foo'], 'foo.txt', {type: 'text/plain'}), + new File(['bar'], 'bar.txt', {type: 'text/plain'}), + ]; + await userEvent.upload(input, files); + const actions = screen.getByTestId('actions'); + expect(actions).toBeInTheDocument(); + }); + + it('clears selected files through the clear button', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + + const clearButton = screen.getByTestId('clear'); + await userEvent.click(clearButton); + + expect(input.files).toHaveLength(0); + }); + + it.each(DELETE_KEYS)('clears selected files through pressing %s key', async (key) => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + input.focus(); + await userEvent.keyboard(`{${key}}`); + expect(input.files).toHaveLength(0); + }); + + it('ignores other key presses when input is focused', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + input.focus(); + await userEvent.keyboard('a'); + expect(input.files).toHaveLength(1); + }); + + it.each(SELECT_KEYS)('opens picker on pressing %s when input is in focus', async (key) => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + input.focus(); + await userEvent.keyboard(`{${key}}`); + // how to assert? + }); + + it('opens picker when files are previously selected (showPicker)', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const showPicker = vi.fn(); + input.showPicker = showPicker; + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + + const clearButton = screen.getByTestId('reselect'); + await userEvent.click(clearButton); + + expect(showPicker).toBeCalledTimes(1); + }); + + it('opens picker when files are previously selected (no showPicker)', async () => { + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const showPicker = vi.spyOn(input, 'click'); + const file = new File(['foo'], 'foo.txt', {type: 'text/plain'}); + await userEvent.upload(input, file); + + const clearButton = screen.getByTestId('reselect'); + await userEvent.click(clearButton); + + expect(showPicker).toBeCalledTimes(1); + }); + + it('accepts drop files', async () => { + const onChange = vi.fn(); + + render( + , + ); + + const root = screen.getByTestId('root'); + const file = new File(['foo'], 'foo.txt', { type: 'text/plain' }); + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + + await userEventDrop(root, file, input); + expect(onChange).toBeCalledTimes(1); + }); + + it('accepts pasted files', async () => { + const onChange = vi.fn(); + + render( + , + ); + + const input = screen.getByTestId('input') as FileSelectBoxDerivedElement; + const file = new File(['foo'], 'foo.txt', { type: 'text/plain' }); + + await userEventPaste(input, file); + expect(onChange).toBeCalledTimes(1); + }); }); }); diff --git a/categories/web/blob/react/src/components/FileSelectBox/index.tsx b/categories/web/blob/react/src/components/FileSelectBox/index.tsx index 9ebd6be..e55b031 100644 --- a/categories/web/blob/react/src/components/FileSelectBox/index.tsx +++ b/categories/web/blob/react/src/components/FileSelectBox/index.tsx @@ -79,12 +79,14 @@ export interface FileSelectBoxProps< clearLabel?: string, } +export type FileSelectBoxDefaultPreviewComponentDerivedElement = HTMLDivElement; + /** * Default component for the {@link FileSelectBoxProps.previewComponent|previewComponent prop} * of the {@link FileSelectBox} component. */ export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< - HTMLDivElement, + FileSelectBoxDefaultPreviewComponentDerivedElement, CommonPreviewComponentProps >(({ file, @@ -101,40 +103,40 @@ export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< > {file?.name ?? ( - - File - + + File + )} {!mini && ( - <> - {typeof file?.type === 'string' && ( - {file?.type} - )} - {typeof file?.size === 'number' && ( - - {new Intl.NumberFormat(undefined, { - style: 'unit', - unit: 'kilobyte', - unitDisplay: 'long', - }).format(file.size ?? 0)} - - )} - {typeof file?.lastModified === 'number' && ( - - - {new Date(file.lastModified).toDateString()} - - - )} - > + <> + {typeof file?.type === 'string' && ( + {file?.type} + )} + {typeof file?.size === 'number' && ( + + {new Intl.NumberFormat(undefined, { + style: 'unit', + unit: 'kilobyte', + unitDisplay: 'long', + }).format(file.size)} + + )} + {typeof file?.lastModified === 'number' && ( + + + {new Date(file.lastModified).toDateString()} + + + )} + > )} )); @@ -149,6 +151,16 @@ const isMouseUpEvent = (e: React.SyntheticEvent): e is React.MouseEvent => e.typ const isDropEvent = (e: React.SyntheticEvent): e is React.DragEvent => e.type === 'drop'; +const isPasteEvent = (e: React.SyntheticEvent): e is React.ClipboardEvent => e.type === 'paste'; + +export const DELETE_KEYS = ['Backspace', 'Delete'] as const; + +type DeleteKey = typeof DELETE_KEYS[number]; + +export const SELECT_KEYS = ['Enter', 'Space', 'Return'] as const; + +type SelectKey = typeof SELECT_KEYS[number]; + /** * Component for selecting files. */ @@ -171,6 +183,7 @@ export const FileSelectBox = React.forwardRef(); const [lastUpdated, setLastUpdated] = React.useState(); const clearFileListRef = React.useRef(false); - const [deleteKeyPressed, setDeleteKeyPressed] = React.useState(false); + const [aboutToClear, setAboutToClear] = React.useState(false); const [aboutToSelect, setAboutToSelect] = React.useState(false); const clearFiles = ( fileInput: FileSelectBoxDerivedElement, clearRef: React.MutableRefObject, ) => { - const clearRefMut = clearRef; + const clearRefMut = clearRef as unknown as Record; clearRefMut.current = true; - const fileInputMut = fileInput; + const fileInputMut = fileInput as unknown as Record; fileInputMut.value = ''; setFileList(undefined); @@ -200,28 +213,26 @@ export const FileSelectBox = React.forwardRef | React.MouseEvent | React.DragEvent - | React.KeyboardEvent, + | React.KeyboardEvent + | React.ClipboardEvent, FileSelectBoxDerivedElement >({ forwardedRef, valueSetterFn: (e) => { - const fileInput = defaultRef.current; - if (!fileInput) { - return; - } - if (isButtonElement(e.currentTarget) && isMouseUpEvent(e)) { + const fileInput = defaultRef.current as FileSelectBoxDerivedElement; + if (isMouseUpEvent(e) && isButtonElement(e.currentTarget)) { clearFiles(fileInput, clearFileListRef); return; } - if (isInputElement(e.currentTarget) && isKeyUpEvent(e)) { + if (isKeyUpEvent(e) && isInputElement(e.currentTarget) && e.currentTarget === fileInput) { // delete via keyboard const { code } = e; - if (!(code === 'Backspace' || code === 'Delete')) { - return; + if (DELETE_KEYS.includes(code as DeleteKey)) { + clearFiles(fileInput, clearFileListRef); + setAboutToClear(false); } - clearFiles(e.currentTarget, clearFileListRef); return; } if (isDropEvent(e)) { @@ -229,12 +240,31 @@ export const FileSelectBox = React.forwardRef 0) { - setFileList(fileInput.files = files); + try { + fileInput.files = files; + } catch { + // noop, the assignment throws for test environments + } + setFileList(files); setLastUpdated(Date.now()); } return; } - console.warn('Unhandled event', e); + if (isPasteEvent(e)) { + const { clipboardData } = e; + const { files } = clipboardData; + if (files && files.length > 0) { + try { + fileInput.files = files; + } catch { + // noop, the assignment throws for test environments + } + setFileList(files); + setLastUpdated(Date.now()); + } + return; + } + // Unhandled event }, }); const labelId = React.useId(); @@ -254,45 +284,32 @@ export const FileSelectBox = React.forwardRef = React.useCallback((e) => { const { currentTarget } = e; - if (clientSide && currentTarget.files && currentTarget.files.length > 0) { + if (currentTarget.files && currentTarget.files.length > 0) { setFileList(currentTarget.files); setLastUpdated(Date.now()); setAboutToSelect(false); - onChange?.(e); - return; - } - if (clientSide && clearFileListRef.current) { + } else if (clearFileListRef.current) { clearFileListRef.current = false; setFileList(undefined); setLastUpdated(Date.now()); - onChange?.(e); - return; } - e.preventDefault(); - e.currentTarget.files = fileList ?? null; - setAboutToSelect(false); - }, [clientSide, fileList, onChange]); + onChange?.(e); + }, [clearFileListRef, onChange]); const handleKeyDown: React.KeyboardEventHandler< FileSelectBoxDerivedElement > = React.useCallback((e) => { const { code } = e; - if (code === 'Backspace' || code === 'Delete') { - setDeleteKeyPressed(true); - } else if (code === 'Enter' || code === 'Space' || code === 'Return') { - setAboutToSelect(true); + if (DELETE_KEYS.includes(code as DeleteKey)) { + setAboutToClear(true); + return; } - }, []); - const handleKeyUp: React.KeyboardEventHandler< - FileSelectBoxDerivedElement - > = React.useCallback((e) => { - const { code } = e; - if (code === 'Backspace' || code === 'Delete') { - doSetFileList(e); - setDeleteKeyPressed(false); + if (SELECT_KEYS.includes(code as SelectKey)) { + setAboutToSelect(true); } - }, [doSetFileList]); + // ignore other keys + }, []); const handleReselectMouseDown: React.MouseEventHandler< HTMLButtonElement @@ -308,13 +325,17 @@ export const FileSelectBox = React.forwardRef = React.useCallback(() => { const fileInput = defaultRef.current as FileSelectBoxDerivedElement; + if (typeof fileInput.showPicker !== 'function') { + fileInput.click(); + return; + } fileInput.showPicker(); }, [defaultRef]); const handleDeleteMouseDown: React.MouseEventHandler< HTMLButtonElement > = React.useCallback(() => { - setDeleteKeyPressed(true); + setAboutToClear(true); setTimeout(() => { const fileInput = defaultRef.current as FileSelectBoxDerivedElement; fileInput.focus(); @@ -325,14 +346,14 @@ export const FileSelectBox = React.forwardRef = React.useCallback((e) => { setAboutToSelect(false); - setDeleteKeyPressed(false); + setAboutToClear(false); onBlur?.(e); }, [onBlur]); React.useEffect(() => { const handleLabelMouseUp = () => { setAboutToSelect(false); - setDeleteKeyPressed(false); + setAboutToClear(false); }; window.addEventListener('mouseup', handleLabelMouseUp, { capture: true }); @@ -342,6 +363,7 @@ export const FileSelectBox = React.forwardRef 0 && clientSide && ( - - + + {multiple && ( - {Array.from(fileList ?? []).map((file) => ( + {fileListArray.map((file, i) => ( @@ -458,9 +486,9 @@ export const FileSelectBox = React.forwardRef )} {!multiple - && Array.from(fileList ?? []).map((file) => ( + && fileListArray.map((file, i) => ( ))} - + diff --git a/categories/web/choice/react/package.json b/categories/web/choice/react/package.json index 035060e..1b03f35 100644 --- a/categories/web/choice/react/package.json +++ b/categories/web/choice/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/color/react/package.json b/categories/web/color/react/package.json index 7428d29..c0595ae 100644 --- a/categories/web/color/react/package.json +++ b/categories/web/color/react/package.json @@ -25,7 +25,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/formatted/react/package.json b/categories/web/formatted/react/package.json index b45a577..08c2706 100644 --- a/categories/web/formatted/react/package.json +++ b/categories/web/formatted/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/freeform/react/package.json b/categories/web/freeform/react/package.json index 2336f46..55ceca4 100644 --- a/categories/web/freeform/react/package.json +++ b/categories/web/freeform/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/information/react/package.json b/categories/web/information/react/package.json index 2060098..4f59b5c 100644 --- a/categories/web/information/react/package.json +++ b/categories/web/information/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/multichoice/react/package.json b/categories/web/multichoice/react/package.json index 5c2e0a0..d6fd682 100644 --- a/categories/web/multichoice/react/package.json +++ b/categories/web/multichoice/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/navigation/react/package.json b/categories/web/navigation/react/package.json index a0e530d..e281dd2 100644 --- a/categories/web/navigation/react/package.json +++ b/categories/web/navigation/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/number/react/package.json b/categories/web/number/react/package.json index 66d31b3..48addf8 100644 --- a/categories/web/number/react/package.json +++ b/categories/web/number/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/categories/web/temporal/react/package.json b/categories/web/temporal/react/package.json index 5fb864d..75df01f 100644 --- a/categories/web/temporal/react/package.json +++ b/categories/web/temporal/react/package.json @@ -23,7 +23,7 @@ "@vitest/coverage-v8": "^0.33.0", "eslint": "^8.46.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", + "jsdom": "^22.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/react-binary-data-canvas/package.json b/packages/react-binary-data-canvas/package.json index 3fb4a78..a351304 100644 --- a/packages/react-binary-data-canvas/package.json +++ b/packages/react-binary-data-canvas/package.json @@ -20,7 +20,6 @@ "@types/react": "^18.2.18", "eslint": "^8.35.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/react-blob-previews/package.json b/packages/react-blob-previews/package.json index 5505588..86189e7 100644 --- a/packages/react-blob-previews/package.json +++ b/packages/react-blob-previews/package.json @@ -20,7 +20,6 @@ "@types/react": "^18.2.18", "eslint": "^8.35.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/react-refractor/package.json b/packages/react-refractor/package.json index 445366a..03652b8 100644 --- a/packages/react-refractor/package.json +++ b/packages/react-refractor/package.json @@ -20,7 +20,6 @@ "@types/react": "^18.2.18", "eslint": "^8.35.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/react-utils/package.json b/packages/react-utils/package.json index 5505588..86189e7 100644 --- a/packages/react-utils/package.json +++ b/packages/react-utils/package.json @@ -20,7 +20,6 @@ "@types/react": "^18.2.18", "eslint": "^8.35.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/react-wavesurfer/package.json b/packages/react-wavesurfer/package.json index 464ebda..a8883d0 100644 --- a/packages/react-wavesurfer/package.json +++ b/packages/react-wavesurfer/package.json @@ -20,7 +20,6 @@ "@types/react": "^18.2.18", "eslint": "^8.35.0", "eslint-config-lxsmnsyc": "^0.5.0", - "jsdom": "^21.1.0", "pridepack": "2.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e1ca0d..3618e7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 categories/web/action/react: dependencies: @@ -73,8 +73,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -95,7 +95,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/blob/react: dependencies: @@ -137,8 +137,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -159,7 +159,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/choice/react: dependencies: @@ -207,8 +207,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -229,7 +229,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/color/react: dependencies: @@ -283,8 +283,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -305,7 +305,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/formatted/react: dependencies: @@ -353,8 +353,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -375,7 +375,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/freeform/react: dependencies: @@ -420,8 +420,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -442,7 +442,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/information/react: dependencies: @@ -481,8 +481,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -503,7 +503,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/multichoice/react: dependencies: @@ -551,8 +551,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -573,7 +573,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/navigation/react: dependencies: @@ -615,8 +615,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -637,7 +637,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/number/react: dependencies: @@ -685,8 +685,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -707,7 +707,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) categories/web/temporal/react: dependencies: @@ -755,8 +755,8 @@ importers: specifier: ^0.5.0 version: 0.5.0(eslint@8.46.0)(typescript@5.2.2) jsdom: - specifier: ^21.1.0 - version: 21.1.0 + specifier: ^22.1.0 + version: 22.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.46.0)(tslib@2.6.0)(typescript@5.2.2) @@ -777,7 +777,7 @@ importers: version: 5.2.2 vitest: specifier: ^0.34.1 - version: 0.34.1(jsdom@21.1.0) + version: 0.34.1(jsdom@22.1.0) packages/amanuensis: dependencies: @@ -829,7 +829,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/audio-utils: dependencies: @@ -860,7 +860,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/blob-utils: dependencies: @@ -894,7 +894,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/image-utils: dependencies: @@ -934,7 +934,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/react-binary-data-canvas: devDependencies: @@ -959,9 +959,6 @@ importers: eslint-config-lxsmnsyc: specifier: ^0.5.0 version: 0.5.0(eslint@8.43.0)(typescript@4.9.5) - jsdom: - specifier: ^21.1.0 - version: 21.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.43.0)(tslib@2.6.0)(typescript@4.9.5) @@ -982,7 +979,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/react-blob-previews: devDependencies: @@ -1007,9 +1004,6 @@ importers: eslint-config-lxsmnsyc: specifier: ^0.5.0 version: 0.5.0(eslint@8.43.0)(typescript@4.9.5) - jsdom: - specifier: ^21.1.0 - version: 21.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.43.0)(tslib@2.6.0)(typescript@4.9.5) @@ -1030,7 +1024,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/react-refractor: dependencies: @@ -1068,9 +1062,6 @@ importers: eslint-config-lxsmnsyc: specifier: ^0.5.0 version: 0.5.0(eslint@8.43.0)(typescript@4.9.5) - jsdom: - specifier: ^21.1.0 - version: 21.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.43.0)(tslib@2.6.0)(typescript@4.9.5) @@ -1094,7 +1085,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/react-utils: devDependencies: @@ -1119,9 +1110,6 @@ importers: eslint-config-lxsmnsyc: specifier: ^0.5.0 version: 0.5.0(eslint@8.43.0)(typescript@4.9.5) - jsdom: - specifier: ^21.1.0 - version: 21.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.43.0)(tslib@2.6.0)(typescript@4.9.5) @@ -1142,7 +1130,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/react-wavesurfer: dependencies: @@ -1186,9 +1174,6 @@ importers: eslint-config-lxsmnsyc: specifier: ^0.5.0 version: 0.5.0(eslint@8.43.0)(typescript@4.9.5) - jsdom: - specifier: ^21.1.0 - version: 21.1.0 pridepack: specifier: 2.4.4 version: 2.4.4(eslint@8.43.0)(tslib@2.6.0)(typescript@4.9.5) @@ -1209,7 +1194,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/text-utils: dependencies: @@ -1246,7 +1231,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages/video-utils: devDependencies: @@ -1273,7 +1258,7 @@ importers: version: 4.9.5 vitest: specifier: ^0.28.1 - version: 0.28.1(jsdom@21.1.0) + version: 0.28.1 packages: @@ -3260,7 +3245,7 @@ packages: std-env: 3.3.3 test-exclude: 6.0.0 v8-to-istanbul: 9.1.0 - vitest: 0.34.1(jsdom@21.1.0) + vitest: 0.34.1(jsdom@22.1.0) transitivePeerDependencies: - supports-color dev: true @@ -3339,13 +3324,6 @@ packages: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true - /acorn-globals@7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - dependencies: - acorn: 8.9.0 - acorn-walk: 8.2.0 - dev: true - /acorn-jsx@5.3.2(acorn@7.4.1): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -4014,19 +3992,11 @@ packages: engines: {node: '>=4'} hasBin: true - /cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - dev: true - - /cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - dev: true - - /cssstyle@2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} + /cssstyle@3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} dependencies: - cssom: 0.3.8 + rrweb-cssom: 0.6.0 dev: true /csstype@3.1.2: @@ -4053,13 +4023,13 @@ packages: resolution: {integrity: sha512-Cp+jOa8QJef5nXS5hU7M1DWzXPEIoVR3kbV0dQuVGwROZg8bGf1DcCnkmajBTnvghTtSNMUdRrPjgaT6ZQucbw==} dev: false - /data-urls@3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} + /data-urls@4.0.0: + resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} + engines: {node: '>=14'} dependencies: abab: 2.0.6 whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 + whatwg-url: 12.0.1 dev: true /debug@3.2.7: @@ -6368,9 +6338,9 @@ packages: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} dev: false - /jsdom@21.1.0: - resolution: {integrity: sha512-m0lzlP7qOtthD918nenK3hdItSd2I+V3W9IrBcB36sqDwG+KnUs66IF5GY7laGWUnlM9vTsD0W1QwSEBYWWcJg==} - engines: {node: '>=14'} + /jsdom@22.1.0: + resolution: {integrity: sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==} + engines: {node: '>=16'} peerDependencies: canvas: ^2.5.0 peerDependenciesMeta: @@ -6378,21 +6348,18 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.9.0 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 + cssstyle: 3.0.0 + data-urls: 4.0.0 decimal.js: 10.4.3 domexception: 4.0.0 - escodegen: 2.1.0 form-data: 4.0.0 html-encoding-sniffer: 3.0.0 http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.6 + nwsapi: 2.2.7 parse5: 7.1.2 + rrweb-cssom: 0.6.0 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 4.1.3 @@ -6400,7 +6367,7 @@ packages: webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 + whatwg-url: 12.0.1 ws: 8.13.0 xml-name-validator: 4.0.0 transitivePeerDependencies: @@ -7101,8 +7068,8 @@ packages: boolbase: 1.0.0 dev: true - /nwsapi@2.2.6: - resolution: {integrity: sha512-vSZ4miHQ4FojLjmz2+ux4B0/XA16jfwt/LBzIUftDpRd8tujHFkXjMyLwjS08fIZCzesj2z7gJukOKJwqebJAQ==} + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true /oauth-sign@0.9.0: @@ -8007,6 +7974,10 @@ packages: fsevents: 2.3.3 dev: true + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + /run-applescript@5.0.0: resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} engines: {node: '>=12'} @@ -8548,9 +8519,9 @@ packages: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true - /tr46@3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} + /tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} dependencies: punycode: 2.3.0 dev: true @@ -9002,7 +8973,7 @@ packages: fsevents: 2.3.3 dev: true - /vitest@0.28.1(jsdom@21.1.0): + /vitest@0.28.1: resolution: {integrity: sha512-F6wAO3K5+UqJCCGt0YAl3Ila2f+fpBrJhl9n7qWEhREwfzQeXlMkkCqGqGtzBxCSa8kv5QHrkshX8AaPTXYACQ==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9036,7 +9007,6 @@ packages: cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 - jsdom: 21.1.0 local-pkg: 0.4.3 pathe: 1.1.1 picocolors: 1.0.0 @@ -9058,7 +9028,7 @@ packages: - terser dev: true - /vitest@0.34.1(jsdom@21.1.0): + /vitest@0.34.1(jsdom@22.1.0): resolution: {integrity: sha512-G1PzuBEq9A75XSU88yO5G4vPT20UovbC/2osB2KEuV/FisSIIsw7m5y2xMdB7RsAGHAfg2lPmp2qKr3KWliVlQ==} engines: {node: '>=v14.18.0'} hasBin: true @@ -9102,7 +9072,7 @@ packages: cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 - jsdom: 21.1.0 + jsdom: 22.1.0 local-pkg: 0.4.3 magic-string: 0.30.1 pathe: 1.1.1 @@ -9209,11 +9179,11 @@ packages: engines: {node: '>=12'} dev: true - /whatwg-url@11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} + /whatwg-url@12.0.1: + resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} + engines: {node: '>=14'} dependencies: - tr46: 3.0.0 + tr46: 4.1.1 webidl-conversions: 7.0.0 dev: true