Skip to content

Commit 60381a8

Browse files
committed
feat: fix ts
1 parent 6a0108b commit 60381a8

File tree

3 files changed

+117
-44
lines changed

3 files changed

+117
-44
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { useMemo, useState } from "react"
2+
import useIsomorphicLayoutEffect from "./useIsomorphicLayoutEffect"
3+
4+
export type UseMeasureRect = Pick<
5+
DOMRectReadOnly,
6+
"x" | "y" | "top" | "left" | "right" | "bottom" | "height" | "width"
7+
>
8+
export type UseMeasureRef<E extends Element = Element> = (element: E) => void
9+
export type UseMeasureResult<E extends Element = Element> = [
10+
UseMeasureRef<E>,
11+
UseMeasureRect,
12+
E | null,
13+
]
14+
15+
const defaultState: UseMeasureRect = {
16+
x: 0,
17+
y: 0,
18+
width: 0,
19+
height: 0,
20+
top: 0,
21+
left: 0,
22+
bottom: 0,
23+
right: 0,
24+
}
25+
26+
export function useMeasure<E extends Element = Element>(): UseMeasureResult<E> {
27+
const [element, setElement] = useState<E | null>(null)
28+
const [rect, setRect] = useState<UseMeasureRect>(defaultState)
29+
30+
const observer = useMemo(
31+
() =>
32+
new ResizeObserver((entries) => {
33+
if (entries[0]) {
34+
const { x, y, width, height, top, left, bottom, right } =
35+
entries[0].contentRect
36+
setRect({ x, y, width, height, top, left, bottom, right })
37+
}
38+
}),
39+
[],
40+
)
41+
42+
useIsomorphicLayoutEffect(() => {
43+
if (!element) return
44+
observer.observe(element)
45+
return () => {
46+
observer.disconnect()
47+
}
48+
}, [element])
49+
50+
return [setElement, rect, element]
51+
}

packages/react-reader/src/gallery/GalleryDialog.tsx

+23-44
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { Box, Button } from "@chakra-ui/react"
2-
import { type SpineItem, isShallowEqual } from "@prose-reader/core"
2+
import type { SpineItem } from "@prose-reader/core"
33
import { memo } from "react"
44
import { useObserve, useSubscribe } from "reactjrx"
5-
import { NEVER, distinctUntilChanged, filter, map, switchMap, tap } from "rxjs"
6-
import useMeasure from "../common/useMeasure"
5+
import { useMeasure } from "../common/useMeasure"
76
import {
87
DialogActionTrigger,
98
DialogBody,
@@ -14,34 +13,14 @@ import {
1413
DialogRoot,
1514
DialogTitle,
1615
} from "../components/ui/dialog"
17-
import { hasGalleryEnhancer, useReader } from "../context/useReader"
16+
import { useReader } from "../context/useReader"
17+
import { useAttachSnapshot } from "./useAttachSnapshot"
1818

19-
const GalleryItem = ({ item }: { item: SpineItem }) => {
19+
const GalleryItem = memo(({ item }: { item: SpineItem }) => {
2020
const reader = useReader()
2121
const [setElement, measures, element] = useMeasure()
22-
const readerWithGalleryEnhancer = hasGalleryEnhancer(reader)
23-
? reader
24-
: undefined
2522

26-
useSubscribe(() => {
27-
if (!readerWithGalleryEnhancer || !element) return NEVER
28-
29-
const itemReadyAndLayoutChanged$ = item.isReady$.pipe(
30-
filter((isReady) => isReady),
31-
map(() => item.layout.layoutInfo),
32-
distinctUntilChanged(isShallowEqual),
33-
)
34-
35-
return itemReadyAndLayoutChanged$.pipe(
36-
switchMap(() =>
37-
readerWithGalleryEnhancer?.gallery.snapshot(item, measures),
38-
),
39-
tap((snapshot) => {
40-
element.innerHTML = ""
41-
element.appendChild(snapshot)
42-
}),
43-
)
44-
}, [readerWithGalleryEnhancer, item, measures, element])
23+
useAttachSnapshot(element, item, measures)
4524

4625
useSubscribe(
4726
() => reader?.spine.spineItemsLoader.forceOpen([item]),
@@ -57,11 +36,9 @@ const GalleryItem = ({ item }: { item: SpineItem }) => {
5736
borderColor="border"
5837
borderRadius="md"
5938
data-grid-item
60-
>
61-
{item.item.id}
62-
</Box>
39+
/>
6340
)
64-
}
41+
})
6542

6643
export const GalleryDialog = memo(
6744
({
@@ -87,19 +64,21 @@ export const GalleryDialog = memo(
8764
<DialogHeader>
8865
<DialogTitle>Gallery</DialogTitle>
8966
</DialogHeader>
90-
<DialogBody
91-
gridTemplateColumns={[
92-
"repeat(2, minmax(0, 1fr))",
93-
"repeat(2, minmax(0, 1fr))",
94-
]}
95-
display="grid"
96-
gap={2}
97-
pt={2}
98-
data-grid
99-
>
100-
{items?.map((item) => (
101-
<GalleryItem key={item.item.id} item={item} />
102-
))}
67+
<DialogBody>
68+
<Box
69+
gridTemplateColumns={[
70+
"repeat(2, minmax(0, 1fr))",
71+
"repeat(3, minmax(0, 1fr))",
72+
]}
73+
display="grid"
74+
gap={[2, 4]}
75+
pt={2}
76+
data-grid
77+
>
78+
{items?.map((item) => (
79+
<GalleryItem key={item.item.id} item={item} />
80+
))}
81+
</Box>
10382
</DialogBody>
10483
<DialogFooter>
10584
<DialogActionTrigger asChild>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { distinctUntilChanged, switchMap, tap } from "rxjs"
2+
3+
import { map } from "rxjs"
4+
5+
import { NEVER } from "rxjs"
6+
7+
import { type SpineItem, isShallowEqual } from "@prose-reader/core"
8+
import { useSubscribe } from "reactjrx"
9+
import { filter } from "rxjs"
10+
import type { UseMeasureRect } from "../common/useMeasure"
11+
import { useReader } from "../context/useReader"
12+
import { hasGalleryEnhancer } from "../context/useReader"
13+
14+
export const useAttachSnapshot = (
15+
element: Element | null,
16+
item: SpineItem,
17+
measures: UseMeasureRect,
18+
) => {
19+
const reader = useReader()
20+
const readerWithGalleryEnhancer = hasGalleryEnhancer(reader)
21+
? reader
22+
: undefined
23+
24+
useSubscribe(() => {
25+
if (!readerWithGalleryEnhancer || !element) return NEVER
26+
27+
const itemReadyAndLayoutChanged$ = item.isReady$.pipe(
28+
filter((isReady) => isReady),
29+
map(() => item.layout.layoutInfo),
30+
distinctUntilChanged(isShallowEqual),
31+
)
32+
33+
return itemReadyAndLayoutChanged$.pipe(
34+
switchMap(() =>
35+
readerWithGalleryEnhancer?.gallery.snapshot(item, measures),
36+
),
37+
tap((snapshot) => {
38+
element.innerHTML = ""
39+
element.appendChild(snapshot)
40+
}),
41+
)
42+
}, [readerWithGalleryEnhancer, item, measures, element])
43+
}

0 commit comments

Comments
 (0)