-
Notifications
You must be signed in to change notification settings - Fork 137
/
Selection.tsx
90 lines (86 loc) · 2.84 KB
/
Selection.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { useState, useRef, useEffect } from 'react'
import { ReactReader } from '../../lib/index'
import type { Contents, Rendition } from 'epubjs'
import { DEMO_URL, DEMO_NAME } from '../components/config'
import { Example } from '../components/Example'
type ITextSelection = {
text: string
cfiRange: string
}
export const Selection = () => {
const [selections, setSelections] = useState<ITextSelection[]>([])
const [rendition, setRendition] = useState<Rendition | undefined>(undefined)
const [location, setLocation] = useState<string | number>(0)
useEffect(() => {
if (rendition) {
function setRenderSelection(cfiRange: string, contents: Contents) {
if (rendition) {
setSelections((list) =>
list.concat({
text: rendition.getRange(cfiRange).toString(),
cfiRange,
})
)
rendition.annotations.add(
'highlight',
cfiRange,
{},
(e: MouseEvent) => console.log('click on selection', cfiRange, e),
'hl',
{ fill: 'red', 'fill-opacity': '0.5', 'mix-blend-mode': 'multiply' }
)
const selection = contents.window.getSelection()
selection?.removeAllRanges()
}
}
rendition.on('selected', setRenderSelection)
return () => {
rendition?.off('selected', setRenderSelection)
}
}
}, [setSelections, rendition])
return (
<Example
title="Selection example"
above={
<div className="border border-stone-400 bg-white min-h-[100px] p-2 rounded">
<h2 className="font-bold mb-1">Selections</h2>
<ul className="grid grid-cols-1 divide-y divide-stone-400 border-t border-stone-400 -mx-2">
{selections.map(({ text, cfiRange }, i) => (
<li key={i} className="p-2">
<span>{text}</span>
<button
className="underline hover:no-underline text-sm mx-1"
onClick={() => {
rendition?.display(cfiRange)
}}
>
Show
</button>
<button
className="underline hover:no-underline text-sm mx-1"
onClick={() => {
rendition?.annotations.remove(cfiRange, 'highlight')
setSelections(selections.filter((item, j) => j !== i))
}}
>
Remove
</button>
</li>
))}
</ul>
</div>
}
>
<ReactReader
url={DEMO_URL}
title={DEMO_NAME}
location={location}
locationChanged={(loc: string) => setLocation(loc)}
getRendition={(_rendition: Rendition) => {
setRendition(_rendition)
}}
/>
</Example>
)
}