mirror of
https://github.com/zhigang1992/react.git
synced 2026-04-29 04:35:32 +08:00
refactor: export all hooks functions directly from main module
refactor: rename the modules to make sure tree-shaking works
This commit is contained in:
57
components/use-clipboard/__tests__/clipboard.test.tsx
Normal file
57
components/use-clipboard/__tests__/clipboard.test.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useClipboard } from 'components'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
|
||||
describe('UseClipboard', () => {
|
||||
beforeAll(() => {
|
||||
window.getSelection = jest.fn().mockImplementation(() => ({
|
||||
removeAllRanges: jest.fn(),
|
||||
addRange: jest.fn(),
|
||||
}))
|
||||
document.createRange = jest.fn().mockImplementation(() => ({
|
||||
selectNode: jest.fn(),
|
||||
}))
|
||||
})
|
||||
|
||||
it('should work correctly', () => {
|
||||
document.execCommand = jest.fn()
|
||||
const { result } = renderHook(() => useClipboard())
|
||||
result.current.copy('test')
|
||||
expect(document.execCommand).toHaveBeenCalled()
|
||||
;(document.execCommand as jest.Mock).mockClear()
|
||||
})
|
||||
|
||||
it('should capture copy erros', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||
document.execCommand = jest.fn().mockImplementation(() => {
|
||||
throw new Error('test')
|
||||
})
|
||||
const { result } = renderHook(() => useClipboard())
|
||||
result.current.copy('space speace breaks $@#')
|
||||
|
||||
expect(errorSpy).toHaveBeenCalled()
|
||||
;(document.execCommand as jest.Mock).mockClear()
|
||||
errorSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('should work correctly without text', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||
document.execCommand = jest.fn()
|
||||
const { result } = renderHook(() => useClipboard())
|
||||
result.current.copy('')
|
||||
expect(errorSpy).not.toHaveBeenCalled()
|
||||
;(document.execCommand as jest.Mock).mockClear()
|
||||
errorSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('should not throw errors when the browser does not support', () => {
|
||||
window.getSelection = jest.fn().mockImplementation(() => undefined)
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||
document.execCommand = jest.fn()
|
||||
const { result } = renderHook(() => useClipboard())
|
||||
result.current.copy('test')
|
||||
expect(errorSpy).not.toHaveBeenCalled()
|
||||
;(document.execCommand as jest.Mock).mockClear()
|
||||
;(window.getSelection as jest.Mock).mockClear()
|
||||
errorSpy.mockRestore()
|
||||
})
|
||||
})
|
||||
3
components/use-clipboard/index.ts
Normal file
3
components/use-clipboard/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import useClipboard from './use-clipboard'
|
||||
|
||||
export default useClipboard
|
||||
54
components/use-clipboard/use-clipboard.ts
Normal file
54
components/use-clipboard/use-clipboard.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import usePortal from '../utils/use-portal'
|
||||
import useWarning from '../utils/use-warning'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
export type UseClipboardOptions = {
|
||||
onError: Function
|
||||
}
|
||||
|
||||
export type UseClipboardResult = {
|
||||
copy: (text: string) => void
|
||||
}
|
||||
|
||||
const defaultOptions: UseClipboardOptions = {
|
||||
onError: () => useWarning('Failed to copy.', 'use-clipboard'),
|
||||
}
|
||||
|
||||
const useClipboard = (options: UseClipboardOptions = defaultOptions): UseClipboardResult => {
|
||||
const el = usePortal('clipboard')
|
||||
|
||||
const copyText = (el: HTMLElement | null, text: string) => {
|
||||
if (!el || !text) return
|
||||
const selection = window.getSelection()
|
||||
if (!selection) return
|
||||
|
||||
el.style.whiteSpace = 'pre'
|
||||
el.textContent = text
|
||||
|
||||
const range = window.document.createRange()
|
||||
selection.removeAllRanges()
|
||||
range.selectNode(el)
|
||||
selection.addRange(range)
|
||||
try {
|
||||
window.document.execCommand('copy')
|
||||
} catch (e) {
|
||||
options.onError && options.onError()
|
||||
}
|
||||
|
||||
selection.removeAllRanges()
|
||||
if (el) {
|
||||
el.textContent = ''
|
||||
}
|
||||
}
|
||||
|
||||
const copy = useCallback(
|
||||
(text: string) => {
|
||||
copyText(el, text)
|
||||
},
|
||||
[el],
|
||||
)
|
||||
|
||||
return { copy }
|
||||
}
|
||||
|
||||
export default useClipboard
|
||||
Reference in New Issue
Block a user