1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-12 10:14:02 +02:00

Fix issue with ReactEditor.focus + tests (#5527)

* Fix issue with slate-react static ReactEditor.focus method

This will make sure we don't try to focus the editor while it's in the midst of applying operations.
If this is the case, retry setting focus in the next tick.

* Replace react-test-renderer with @testing-library/react

We need to be able to test against window features, like the DOM selection.
@testing-library/react has a very similar API, but have also these features,
which react-test-renderer is missing.

* Rewrite tests for @testing-library/react

This will rewrite the existing tests for Editable and move them into a own file.

* Add tests for ReactEditor.focus

* Add changeset
This commit is contained in:
Per-Kristian Nordnes
2023-11-10 17:19:10 +01:00
committed by GitHub
parent f9cca97f00
commit fc081816e0
7 changed files with 541 additions and 252 deletions

View File

@@ -0,0 +1,7 @@
---
'slate-react': minor
---
Fixes a bug with `ReactEditor.focus` where it would throw an error if the editor was in the middle of applying pending operations.
With this change, setting focus will be retried until the editor no longer has any pending operations.
Calling `ReactEditor.focus` on a editor without a current selection, will now make a selection in the top of the document.

View File

@@ -26,15 +26,14 @@
},
"devDependencies": {
"@babel/runtime": "^7.23.2",
"@testing-library/react": "^14.0.0",
"@types/jest": "29.5.6",
"@types/jsdom": "^21.1.4",
"@types/react": "^18.2.28",
"@types/react-dom": "^18.2.13",
"@types/react-test-renderer": "^18.0.3",
"@types/resize-observer-browser": "^0.1.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-test-renderer": "^18.2.0",
"slate": "^0.100.0",
"slate-hyperscript": "^0.100.0",
"source-map-loader": "^4.0.1"

View File

@@ -117,7 +117,7 @@ export interface ReactEditorInterface {
/**
* Focus the editor.
*/
focus: (editor: ReactEditor) => void
focus: (editor: ReactEditor, options?: { retries: number }) => void
/**
* Return the host window of the current editor.
@@ -411,19 +411,44 @@ export const ReactEditor: ReactEditorInterface = {
)
},
focus: editor => {
focus: (editor, options = { retries: 5 }) => {
// Return if already focused
if (IS_FOCUSED.get(editor)) {
return
}
// Retry setting focus if the editor has pending operations.
// The DOM (selection) is unstable while changes are applied.
// Retry until retries are exhausted or editor is focused.
if (options.retries <= 0) {
throw new Error(
'Could not set focus, editor seems stuck with pending operations'
)
}
if (editor.operations.length > 0) {
setTimeout(() => {
ReactEditor.focus(editor, { retries: options.retries - 1 })
}, 10)
return
}
const el = ReactEditor.toDOMNode(editor, editor)
const root = ReactEditor.findDocumentOrShadowRoot(editor)
IS_FOCUSED.set(editor, true)
if (root.activeElement !== el) {
// Ensure that the DOM selection state is set to the editor's selection
if (editor.selection && root instanceof Document) {
const domSelection = root.getSelection()
const domRange = ReactEditor.toDOMRange(editor, editor.selection)
domSelection?.removeAllRanges()
domSelection?.addRange(domRange)
}
// Create a new selection in the top of the document if missing
if (!editor.selection) {
Transforms.select(editor, Editor.start(editor, []))
editor.onChange()
}
el.focus({ preventScroll: true })
IS_FOCUSED.set(editor, true)
}
},

View File

@@ -0,0 +1,204 @@
import React, { useEffect } from 'react'
import { createEditor, Text, Transforms } from 'slate'
import { act, render } from '@testing-library/react'
import { Slate, withReact, Editable } from '../src'
describe('slate-react', () => {
describe('Editable', () => {
describe('NODE_TO_KEY logic', () => {
test('should not unmount the node that gets split on a split_node operation', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const mounts = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={() => {}}
>
<Editable
renderElement={({ children }) => {
useEffect(() => mounts(), [])
return children
}}
/>
</Slate>
)
})
// slate updates at next tick, so we need this to be async
await act(async () =>
Transforms.splitNodes(editor, { at: { path: [0, 0], offset: 2 } })
)
// 2 renders, one for the main element and one for the split element
expect(mounts).toHaveBeenCalledTimes(2)
})
test('should not unmount the node that gets merged into on a merge_node operation', async () => {
const editor = withReact(createEditor())
const initialValue = [
{ type: 'block', children: [{ text: 'te' }] },
{ type: 'block', children: [{ text: 'st' }] },
]
const mounts = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={() => {}}
>
<Editable
renderElement={({ children }) => {
useEffect(() => mounts(), [])
return children
}}
/>
</Slate>
)
})
// slate updates at next tick, so we need this to be async
await act(async () =>
Transforms.mergeNodes(editor, { at: { path: [0, 0], offset: 0 } })
)
// only 2 renders for the initial render
expect(mounts).toHaveBeenCalledTimes(2)
})
})
test('calls onSelectionChange when editor select change', async () => {
const editor = withReact(createEditor())
const initialValue = [
{ type: 'block', children: [{ text: 'te' }] },
{ type: 'block', children: [{ text: 'st' }] },
]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>
)
})
await act(async () =>
Transforms.select(editor, { path: [0, 0], offset: 2 })
)
expect(onSelectionChange).toHaveBeenCalled()
expect(onChange).toHaveBeenCalled()
expect(onValueChange).not.toHaveBeenCalled()
})
test('calls onValueChange when editor children change', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>
)
})
await act(async () => Transforms.insertText(editor, 'Hello word!'))
expect(onValueChange).toHaveBeenCalled()
expect(onChange).toHaveBeenCalled()
expect(onSelectionChange).not.toHaveBeenCalled()
})
test('calls onValueChange when editor setNodes', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>
)
})
await act(async () =>
Transforms.setNodes(
editor,
// @ts-ignore
{ bold: true },
{
at: { path: [0, 0], offset: 2 },
match: Text.isText,
split: true,
}
)
)
expect(onChange).toHaveBeenCalled()
expect(onValueChange).toHaveBeenCalled()
expect(onSelectionChange).not.toHaveBeenCalled()
})
test('calls onValueChange when editor children change', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
render(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>
)
})
await act(async () => Transforms.insertText(editor, 'Hello word!'))
expect(onValueChange).toHaveBeenCalled()
expect(onChange).toHaveBeenCalled()
expect(onSelectionChange).not.toHaveBeenCalled()
})
})
})

View File

@@ -1,201 +0,0 @@
import React, { useEffect } from 'react'
import { createEditor, Text, Transforms } from 'slate'
import { create, act, ReactTestRenderer } from 'react-test-renderer'
import { Slate, withReact, Editable } from '../src'
const createNodeMock = () => ({
ownerDocument: global.document,
getRootNode: () => global.document,
})
class MockResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
describe('slate-react', () => {
window.ResizeObserver = MockResizeObserver as any
describe('Editable', () => {
describe('NODE_TO_KEY logic', () => {
test('should not unmount the node that gets split on a split_node operation', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const mounts = jest.fn()
let el: ReactTestRenderer
act(() => {
el = create(
<Slate
editor={editor}
initialValue={initialValue}
onChange={() => {}}
>
<Editable
renderElement={({ children }) => {
useEffect(() => mounts(), [])
return children
}}
/>
</Slate>,
{ createNodeMock }
)
})
// slate updates at next tick, so we need this to be async
await act(async () =>
Transforms.splitNodes(editor, { at: { path: [0, 0], offset: 2 } })
)
// 2 renders, one for the main element and one for the split element
expect(mounts).toHaveBeenCalledTimes(2)
})
test('should not unmount the node that gets merged into on a merge_node operation', async () => {
const editor = withReact(createEditor())
const initialValue = [
{ type: 'block', children: [{ text: 'te' }] },
{ type: 'block', children: [{ text: 'st' }] },
]
const mounts = jest.fn()
let el: ReactTestRenderer
act(() => {
el = create(
<Slate
editor={editor}
initialValue={initialValue}
onChange={() => {}}
>
<Editable
renderElement={({ children }) => {
useEffect(() => mounts(), [])
return children
}}
/>
</Slate>,
{ createNodeMock }
)
})
// slate updates at next tick, so we need this to be async
await act(async () =>
Transforms.mergeNodes(editor, { at: { path: [0, 0], offset: 0 } })
)
// only 2 renders for the initial render
expect(mounts).toHaveBeenCalledTimes(2)
})
})
})
test('calls onSelectionChange when editor select change', async () => {
const editor = withReact(createEditor())
const initialValue = [
{ type: 'block', children: [{ text: 'te' }] },
{ type: 'block', children: [{ text: 'st' }] },
]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
create(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>,
{ createNodeMock }
)
})
await act(async () =>
Transforms.select(editor, { path: [0, 0], offset: 2 })
)
expect(onSelectionChange).toHaveBeenCalled()
expect(onChange).toHaveBeenCalled()
expect(onValueChange).not.toHaveBeenCalled()
})
test('calls onValueChange when editor children change', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
create(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>,
{ createNodeMock }
)
})
await act(async () => Transforms.insertText(editor, 'Hello word!'))
expect(onValueChange).toHaveBeenCalled()
expect(onChange).toHaveBeenCalled()
expect(onSelectionChange).not.toHaveBeenCalled()
})
test('calls onValueChange when editor setNodes', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const onChange = jest.fn()
const onValueChange = jest.fn()
const onSelectionChange = jest.fn()
act(() => {
create(
<Slate
editor={editor}
initialValue={initialValue}
onChange={onChange}
onValueChange={onValueChange}
onSelectionChange={onSelectionChange}
>
<Editable />
</Slate>,
{ createNodeMock }
)
})
await act(async () =>
Transforms.setNodes(
editor,
// @ts-ignore
{ bold: true },
{
at: { path: [0, 0], offset: 2 },
match: Text.isText,
split: true,
}
)
)
expect(onChange).toHaveBeenCalled()
expect(onValueChange).toHaveBeenCalled()
expect(onSelectionChange).not.toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,90 @@
import React, { useEffect } from 'react'
import { createEditor, Text, Transforms } from 'slate'
import { act, render } from '@testing-library/react'
import { Slate, withReact, Editable, ReactEditor } from '../src'
describe('slate-react', () => {
describe('ReactEditor', () => {
describe('.focus', () => {
test('should set focus in top of document with no editor selection', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const testSelection = {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 0], offset: 0 },
}
act(() => {
render(
<Slate editor={editor} initialValue={initialValue}>
<Editable />
</Slate>
)
})
expect(editor.selection).toBe(null)
await act(async () => {
ReactEditor.focus(editor)
})
expect(editor.selection).toEqual(testSelection)
await act(async () => {
const windowSelection = ReactEditor.getWindow(editor).getSelection()
expect(windowSelection?.focusNode?.textContent).toBe('test')
expect(windowSelection?.anchorNode?.textContent).toBe('test')
expect(windowSelection?.anchorOffset).toBe(
testSelection.anchor.offset
)
expect(windowSelection?.focusOffset).toBe(testSelection.focus.offset)
})
})
test('should be able to call .focus without getting toDOMNode errors', async () => {
const editor = withReact(createEditor())
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }]
const propagatedValue = [
{ type: 'block', children: [{ text: 'foo' }] },
{ type: 'block', children: [{ text: 'bar' }] },
]
const testSelection = {
anchor: { path: [1, 0], offset: 0 },
focus: { path: [1, 0], offset: 3 },
}
act(() => {
render(
<Slate editor={editor} initialValue={initialValue}>
<Editable />
</Slate>
)
})
await act(async () => {
Transforms.removeNodes(editor, { at: [0] })
Transforms.insertNodes(editor, propagatedValue)
ReactEditor.focus(editor) // Note: calling focus in the middle of these transformations.
Transforms.select(editor, testSelection)
})
expect(editor.selection).toEqual(testSelection)
await act(async () => {
ReactEditor.focus(editor)
})
await act(async () => {
const windowSelection = ReactEditor.getWindow(editor).getSelection()
expect(windowSelection?.focusNode?.textContent).toBe('bar')
expect(windowSelection?.anchorNode?.textContent).toBe('bar')
expect(windowSelection?.anchorOffset).toBe(
testSelection.anchor.offset
)
expect(windowSelection?.focusOffset).toBe(testSelection.focus.offset)
})
})
})
})
})

255
yarn.lock
View File

@@ -3223,6 +3223,36 @@ __metadata:
languageName: node
linkType: hard
"@testing-library/dom@npm:^9.0.0":
version: 9.3.3
resolution: "@testing-library/dom@npm:9.3.3"
dependencies:
"@babel/code-frame": ^7.10.4
"@babel/runtime": ^7.12.5
"@types/aria-query": ^5.0.1
aria-query: 5.1.3
chalk: ^4.1.0
dom-accessibility-api: ^0.5.9
lz-string: ^1.5.0
pretty-format: ^27.0.2
checksum: 34e0a564da7beb92aa9cc44a9080221e2412b1a132eb37be3d513fe6c58027674868deb9f86195756d98d15ba969a30fe00632a4e26e25df2a5a4f6ac0686e37
languageName: node
linkType: hard
"@testing-library/react@npm:^14.0.0":
version: 14.0.0
resolution: "@testing-library/react@npm:14.0.0"
dependencies:
"@babel/runtime": ^7.12.5
"@testing-library/dom": ^9.0.0
"@types/react-dom": ^18.0.0
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
checksum: 4a54c8f56cc4a39b50803205f84f06280bb76521d6d5d4b3b36651d760c7c7752ef142d857d52aaf4fad4848ed7a8be49afc793a5dda105955d2f8bef24901ac
languageName: node
linkType: hard
"@tootallnate/once@npm:1":
version: 1.1.2
resolution: "@tootallnate/once@npm:1.1.2"
@@ -3254,6 +3284,13 @@ __metadata:
languageName: node
linkType: hard
"@types/aria-query@npm:^5.0.1":
version: 5.0.4
resolution: "@types/aria-query@npm:5.0.4"
checksum: ad8b87e4ad64255db5f0a73bc2b4da9b146c38a3a8ab4d9306154334e0fc67ae64e76bfa298eebd1e71830591fb15987e5de7111bdb36a2221bdc379e3415fb0
languageName: node
linkType: hard
"@types/babel__core@npm:^7.1.14":
version: 7.1.15
resolution: "@types/babel__core@npm:7.1.15"
@@ -3470,6 +3507,15 @@ __metadata:
languageName: node
linkType: hard
"@types/react-dom@npm:^18.0.0":
version: 18.2.15
resolution: "@types/react-dom@npm:18.2.15"
dependencies:
"@types/react": "*"
checksum: 8e9631600c21ff561328e38a951d1991b3b3b20f538af4c0efbd1327c883a5573a63f50e1b945c34fa51b114b30e1ca5e62317bd54f21e063d6697b4be843a03
languageName: node
linkType: hard
"@types/react-dom@npm:^18.2.13":
version: 18.2.13
resolution: "@types/react-dom@npm:18.2.13"
@@ -3479,15 +3525,6 @@ __metadata:
languageName: node
linkType: hard
"@types/react-test-renderer@npm:^18.0.3":
version: 18.0.3
resolution: "@types/react-test-renderer@npm:18.0.3"
dependencies:
"@types/react": "*"
checksum: 6834c7c998d9e699b7b9aca31ce0f550a29a63526a9ab15f62764eeade28fcce634030e5cfd223a8417e8c53234e01bfb961906b35fd9a72dd513aba549181f0
languageName: node
linkType: hard
"@types/react@npm:*, @types/react@npm:^18.2.28":
version: 18.2.28
resolution: "@types/react@npm:18.2.28"
@@ -4014,6 +4051,15 @@ __metadata:
languageName: node
linkType: hard
"aria-query@npm:5.1.3":
version: 5.1.3
resolution: "aria-query@npm:5.1.3"
dependencies:
deep-equal: ^2.0.5
checksum: 929ff95f02857b650fb4cbcd2f41072eee2f46159a6605ea03bf63aa572e35ffdff43d69e815ddc462e16e07de8faba3978afc2813650b4448ee18c9895d982b
languageName: node
linkType: hard
"array-buffer-byte-length@npm:^1.0.0":
version: 1.0.0
resolution: "array-buffer-byte-length@npm:1.0.0"
@@ -5671,6 +5717,32 @@ __metadata:
languageName: node
linkType: hard
"deep-equal@npm:^2.0.5":
version: 2.2.2
resolution: "deep-equal@npm:2.2.2"
dependencies:
array-buffer-byte-length: ^1.0.0
call-bind: ^1.0.2
es-get-iterator: ^1.1.3
get-intrinsic: ^1.2.1
is-arguments: ^1.1.1
is-array-buffer: ^3.0.2
is-date-object: ^1.0.5
is-regex: ^1.1.4
is-shared-array-buffer: ^1.0.2
isarray: ^2.0.5
object-is: ^1.1.5
object-keys: ^1.1.1
object.assign: ^4.1.4
regexp.prototype.flags: ^1.5.0
side-channel: ^1.0.4
which-boxed-primitive: ^1.0.2
which-collection: ^1.0.1
which-typed-array: ^1.1.9
checksum: eb61c35157b6ecb96a5359b507b083fbff8ddb4c86a78a781ee38485f77a667465e45d63ee2ebd8a00e86d94c80e499906900cd82c2debb400237e1662cd5397
languageName: node
linkType: hard
"deep-is@npm:^0.1.3":
version: 0.1.4
resolution: "deep-is@npm:0.1.4"
@@ -5897,6 +5969,13 @@ __metadata:
languageName: node
linkType: hard
"dom-accessibility-api@npm:^0.5.9":
version: 0.5.16
resolution: "dom-accessibility-api@npm:0.5.16"
checksum: 005eb283caef57fc1adec4d5df4dd49189b628f2f575af45decb210e04d634459e3f1ee64f18b41e2dcf200c844bc1d9279d80807e686a30d69a4756151ad248
languageName: node
linkType: hard
"domexception@npm:^4.0.0":
version: 4.0.0
resolution: "domexception@npm:4.0.0"
@@ -6153,6 +6232,23 @@ __metadata:
languageName: node
linkType: hard
"es-get-iterator@npm:^1.1.3":
version: 1.1.3
resolution: "es-get-iterator@npm:1.1.3"
dependencies:
call-bind: ^1.0.2
get-intrinsic: ^1.1.3
has-symbols: ^1.0.3
is-arguments: ^1.1.1
is-map: ^2.0.2
is-set: ^2.0.2
is-string: ^1.0.7
isarray: ^2.0.5
stop-iteration-iterator: ^1.0.0
checksum: 8fa118da42667a01a7c7529f8a8cca514feeff243feec1ce0bb73baaa3514560bd09d2b3438873cf8a5aaec5d52da248131de153b28e2638a061b6e4df13267d
languageName: node
linkType: hard
"es-iterator-helpers@npm:^1.0.12":
version: 1.0.15
resolution: "es-iterator-helpers@npm:1.0.15"
@@ -7065,6 +7161,13 @@ __metadata:
languageName: node
linkType: hard
"function-bind@npm:^1.1.2":
version: 1.1.2
resolution: "function-bind@npm:1.1.2"
checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1
languageName: node
linkType: hard
"function.prototype.name@npm:^1.1.5, function.prototype.name@npm:^1.1.6":
version: 1.1.6
resolution: "function.prototype.name@npm:1.1.6"
@@ -7162,6 +7265,18 @@ __metadata:
languageName: node
linkType: hard
"get-intrinsic@npm:^1.2.2":
version: 1.2.2
resolution: "get-intrinsic@npm:1.2.2"
dependencies:
function-bind: ^1.1.2
has-proto: ^1.0.1
has-symbols: ^1.0.3
hasown: ^2.0.0
checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417
languageName: node
linkType: hard
"get-package-type@npm:^0.1.0":
version: 0.1.0
resolution: "get-package-type@npm:0.1.0"
@@ -7631,6 +7746,15 @@ __metadata:
languageName: node
linkType: hard
"hasown@npm:^2.0.0":
version: 2.0.0
resolution: "hasown@npm:2.0.0"
dependencies:
function-bind: ^1.1.2
checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176
languageName: node
linkType: hard
"he@npm:1.2.0":
version: 1.2.0
resolution: "he@npm:1.2.0"
@@ -8016,6 +8140,17 @@ __metadata:
languageName: node
linkType: hard
"internal-slot@npm:^1.0.4":
version: 1.0.6
resolution: "internal-slot@npm:1.0.6"
dependencies:
get-intrinsic: ^1.2.2
hasown: ^2.0.0
side-channel: ^1.0.4
checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549
languageName: node
linkType: hard
"internal-slot@npm:^1.0.5":
version: 1.0.5
resolution: "internal-slot@npm:1.0.5"
@@ -8041,6 +8176,16 @@ __metadata:
languageName: node
linkType: hard
"is-arguments@npm:^1.1.1":
version: 1.1.1
resolution: "is-arguments@npm:1.1.1"
dependencies:
call-bind: ^1.0.2
has-tostringtag: ^1.0.0
checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27
languageName: node
linkType: hard
"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2":
version: 3.0.2
resolution: "is-array-buffer@npm:3.0.2"
@@ -8278,7 +8423,7 @@ __metadata:
languageName: node
linkType: hard
"is-map@npm:^2.0.1":
"is-map@npm:^2.0.1, is-map@npm:^2.0.2":
version: 2.0.2
resolution: "is-map@npm:2.0.2"
checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728
@@ -8399,7 +8544,7 @@ __metadata:
languageName: node
linkType: hard
"is-set@npm:^2.0.1":
"is-set@npm:^2.0.1, is-set@npm:^2.0.2":
version: 2.0.2
resolution: "is-set@npm:2.0.2"
checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57
@@ -9892,6 +10037,15 @@ __metadata:
languageName: node
linkType: hard
"lz-string@npm:^1.5.0":
version: 1.5.0
resolution: "lz-string@npm:1.5.0"
bin:
lz-string: bin/bin.js
checksum: 1ee98b4580246fd90dd54da6e346fb1caefcf05f677c686d9af237a157fdea3fd7c83a4bc58f858cd5b10a34d27afe0fdcbd0505a47e0590726a873dc8b8f65d
languageName: node
linkType: hard
"magic-string@npm:^0.22.5":
version: 0.22.5
resolution: "magic-string@npm:0.22.5"
@@ -11036,6 +11190,16 @@ __metadata:
languageName: node
linkType: hard
"object-is@npm:^1.1.5":
version: 1.1.5
resolution: "object-is@npm:1.1.5"
dependencies:
call-bind: ^1.0.2
define-properties: ^1.1.3
checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe
languageName: node
linkType: hard
"object-keys@npm:^1.0.12, object-keys@npm:^1.1.1":
version: 1.1.1
resolution: "object-keys@npm:1.1.1"
@@ -11790,6 +11954,17 @@ __metadata:
languageName: node
linkType: hard
"pretty-format@npm:^27.0.2":
version: 27.5.1
resolution: "pretty-format@npm:27.5.1"
dependencies:
ansi-regex: ^5.0.1
ansi-styles: ^5.0.0
react-is: ^17.0.1
checksum: cf610cffcb793885d16f184a62162f2dd0df31642d9a18edf4ca298e909a8fe80bdbf556d5c9573992c102ce8bf948691da91bf9739bee0ffb6e79c8a8a6e088
languageName: node
linkType: hard
"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0":
version: 29.7.0
resolution: "pretty-format@npm:29.7.0"
@@ -12020,13 +12195,6 @@ __metadata:
languageName: node
linkType: hard
"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.2.0":
version: 18.2.0
resolution: "react-is@npm:18.2.0"
checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e
languageName: node
linkType: hard
"react-is@npm:^16.13.1, react-is@npm:^16.8.1":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
@@ -12034,6 +12202,20 @@ __metadata:
languageName: node
linkType: hard
"react-is@npm:^17.0.1":
version: 17.0.2
resolution: "react-is@npm:17.0.2"
checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8
languageName: node
linkType: hard
"react-is@npm:^18.0.0":
version: 18.2.0
resolution: "react-is@npm:18.2.0"
checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e
languageName: node
linkType: hard
"react-router-dom@npm:^6.17.0":
version: 6.17.0
resolution: "react-router-dom@npm:6.17.0"
@@ -12058,31 +12240,6 @@ __metadata:
languageName: node
linkType: hard
"react-shallow-renderer@npm:^16.15.0":
version: 16.15.0
resolution: "react-shallow-renderer@npm:16.15.0"
dependencies:
object-assign: ^4.1.1
react-is: ^16.12.0 || ^17.0.0 || ^18.0.0
peerDependencies:
react: ^16.0.0 || ^17.0.0 || ^18.0.0
checksum: 6052c7e3e9627485120ebd8257f128aad8f56386fe8d42374b7743eac1be457c33506d153c7886b4e32923c0c352d402ab805ef9ca02dbcd8393b2bdeb6e5af8
languageName: node
linkType: hard
"react-test-renderer@npm:^18.2.0":
version: 18.2.0
resolution: "react-test-renderer@npm:18.2.0"
dependencies:
react-is: ^18.2.0
react-shallow-renderer: ^16.15.0
scheduler: ^0.23.0
peerDependencies:
react: ^18.2.0
checksum: 6b6980ced93fa2b72662d5e4ab3b4896833586940047ce52ca9aca801e5432adf05fcbe28289b0af3ce6a2a7c590974e25dcc8aa43d0de658bfe8bbcd686f958
languageName: node
linkType: hard
"react-values@npm:^0.3.3":
version: 0.3.3
resolution: "react-values@npm:0.3.3"
@@ -13227,13 +13384,13 @@ __metadata:
dependencies:
"@babel/runtime": ^7.23.2
"@juggle/resize-observer": ^3.4.0
"@testing-library/react": ^14.0.0
"@types/is-hotkey": ^0.1.8
"@types/jest": 29.5.6
"@types/jsdom": ^21.1.4
"@types/lodash": ^4.14.200
"@types/react": ^18.2.28
"@types/react-dom": ^18.2.13
"@types/react-test-renderer": ^18.0.3
"@types/resize-observer-browser": ^0.1.8
direction: ^1.0.4
is-hotkey: ^0.2.0
@@ -13241,7 +13398,6 @@ __metadata:
lodash: ^4.17.21
react: ^18.2.0
react-dom: ^18.2.0
react-test-renderer: ^18.2.0
scroll-into-view-if-needed: ^3.1.0
slate: ^0.100.0
slate-hyperscript: ^0.100.0
@@ -13528,6 +13684,15 @@ __metadata:
languageName: node
linkType: hard
"stop-iteration-iterator@npm:^1.0.0":
version: 1.0.0
resolution: "stop-iteration-iterator@npm:1.0.0"
dependencies:
internal-slot: ^1.0.4
checksum: d04173690b2efa40e24ab70e5e51a3ff31d56d699550cfad084104ab3381390daccb36652b25755e420245f3b0737de66c1879eaa2a8d4fc0a78f9bf892fcb42
languageName: node
linkType: hard
"stream-transform@npm:^2.1.3":
version: 2.1.3
resolution: "stream-transform@npm:2.1.3"