@shopify/shop-minis-react 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/atoms/list.js +57 -65
- package/dist/components/atoms/list.js.map +1 -1
- package/dist/hooks/util/useImagePicker.js +13 -6
- package/dist/hooks/util/useImagePicker.js.map +1 -1
- package/dist/internal/utils/resizeImage.js +61 -0
- package/dist/internal/utils/resizeImage.js.map +1 -0
- package/dist/providers/ImagePickerProvider.js +123 -102
- package/dist/providers/ImagePickerProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/atoms/list.tsx +3 -12
- package/src/hooks/util/useImagePicker.test.tsx +193 -0
- package/src/hooks/util/useImagePicker.ts +24 -5
- package/src/internal/utils/resizeImage.test.ts +314 -0
- package/src/internal/utils/resizeImage.ts +108 -0
- package/src/providers/ImagePickerProvider.test.tsx +32 -1
- package/src/providers/ImagePickerProvider.tsx +108 -65
- package/dist/components/atoms/pagination.js +0 -10
- package/dist/components/atoms/pagination.js.map +0 -1
- package/dist/components/atoms/tracking-pixel.js +0 -32
- package/dist/components/atoms/tracking-pixel.js.map +0 -1
- package/dist/shop-minis-react/node_modules/.pnpm/react-intersection-observer@9.13.1_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.js +0 -135
- package/dist/shop-minis-react/node_modules/.pnpm/react-intersection-observer@9.13.1_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.js.map +0 -1
- package/src/components/atoms/pagination.tsx +0 -19
- package/src/components/atoms/tracking-pixel.tsx +0 -40
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ImageQuality,
|
|
3
|
+
CustomImageQuality,
|
|
4
|
+
} from '../../providers/ImagePickerProvider'
|
|
5
|
+
|
|
6
|
+
interface ResizeSettings {
|
|
7
|
+
size: number
|
|
8
|
+
compression: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ResizeImageParams {
|
|
12
|
+
file: File
|
|
13
|
+
quality: ImageQuality
|
|
14
|
+
customQuality?: CustomImageQuality
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const QUALITY_SETTINGS: {
|
|
18
|
+
[key in Exclude<ImageQuality, 'original'>]: ResizeSettings
|
|
19
|
+
} = {
|
|
20
|
+
low: {
|
|
21
|
+
size: 1080,
|
|
22
|
+
compression: 0.7,
|
|
23
|
+
},
|
|
24
|
+
medium: {
|
|
25
|
+
size: 1600,
|
|
26
|
+
compression: 0.85,
|
|
27
|
+
},
|
|
28
|
+
high: {
|
|
29
|
+
size: 2048,
|
|
30
|
+
compression: 0.92,
|
|
31
|
+
},
|
|
32
|
+
} as const
|
|
33
|
+
|
|
34
|
+
export function resizeImage({
|
|
35
|
+
file,
|
|
36
|
+
quality,
|
|
37
|
+
customQuality,
|
|
38
|
+
}: ResizeImageParams): Promise<File> {
|
|
39
|
+
if (quality === 'original') {
|
|
40
|
+
return Promise.resolve(file)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const defaultSettings = QUALITY_SETTINGS[quality]
|
|
44
|
+
const settings: ResizeSettings = customQuality
|
|
45
|
+
? {
|
|
46
|
+
size: customQuality.size ?? defaultSettings.size,
|
|
47
|
+
compression: customQuality.compression ?? defaultSettings.compression,
|
|
48
|
+
}
|
|
49
|
+
: defaultSettings
|
|
50
|
+
const maxSize = settings.size
|
|
51
|
+
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const img = new Image()
|
|
54
|
+
const url = URL.createObjectURL(file)
|
|
55
|
+
|
|
56
|
+
img.onerror = () => {
|
|
57
|
+
URL.revokeObjectURL(url)
|
|
58
|
+
reject(new Error('Failed to load image'))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
img.onload = () => {
|
|
62
|
+
URL.revokeObjectURL(url)
|
|
63
|
+
|
|
64
|
+
const canvas = document.createElement('canvas')
|
|
65
|
+
let width = img.width
|
|
66
|
+
let height = img.height
|
|
67
|
+
|
|
68
|
+
// Resize image dimensions maintaining aspect ratio
|
|
69
|
+
if (width > height) {
|
|
70
|
+
if (width > maxSize) {
|
|
71
|
+
height *= maxSize / width
|
|
72
|
+
width = maxSize
|
|
73
|
+
}
|
|
74
|
+
} else if (height > maxSize) {
|
|
75
|
+
width *= maxSize / height
|
|
76
|
+
height = maxSize
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
canvas.width = width
|
|
80
|
+
canvas.height = height
|
|
81
|
+
|
|
82
|
+
const ctx = canvas.getContext('2d')
|
|
83
|
+
if (!ctx) {
|
|
84
|
+
reject(new Error('Failed to get canvas context'))
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
ctx.drawImage(img, 0, 0, width, height)
|
|
88
|
+
|
|
89
|
+
canvas.toBlob(
|
|
90
|
+
blob => {
|
|
91
|
+
if (!blob) {
|
|
92
|
+
reject(new Error('Failed to create blob'))
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
const resizedFile = new File([blob], file.name, {
|
|
96
|
+
type: 'image/jpeg',
|
|
97
|
+
lastModified: Date.now(),
|
|
98
|
+
})
|
|
99
|
+
resolve(resizedFile)
|
|
100
|
+
},
|
|
101
|
+
'image/jpeg',
|
|
102
|
+
settings.compression
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
img.src = url
|
|
107
|
+
})
|
|
108
|
+
}
|
|
@@ -34,6 +34,37 @@ describe('ImagePickerProvider', () => {
|
|
|
34
34
|
mockRequestPermission.mockResolvedValue({granted: true})
|
|
35
35
|
// Clear interaction reporting mock
|
|
36
36
|
mockReportInteraction.mockClear()
|
|
37
|
+
|
|
38
|
+
// Mock URL.createObjectURL and URL.revokeObjectURL for jsdom
|
|
39
|
+
global.URL.createObjectURL = vi.fn(() => 'blob:mock-url')
|
|
40
|
+
global.URL.revokeObjectURL = vi.fn()
|
|
41
|
+
|
|
42
|
+
// Mock Image constructor for resizing
|
|
43
|
+
global.Image = class MockImage {
|
|
44
|
+
width = 1920
|
|
45
|
+
height = 1080
|
|
46
|
+
onload = null as any
|
|
47
|
+
onerror = null as any
|
|
48
|
+
src = ''
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
if (this.onload) {
|
|
53
|
+
this.onload()
|
|
54
|
+
}
|
|
55
|
+
}, 0)
|
|
56
|
+
}
|
|
57
|
+
} as any
|
|
58
|
+
|
|
59
|
+
// Mock canvas methods
|
|
60
|
+
HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
|
|
61
|
+
drawImage: vi.fn(),
|
|
62
|
+
})) as any
|
|
63
|
+
|
|
64
|
+
HTMLCanvasElement.prototype.toBlob = vi.fn(callback => {
|
|
65
|
+
const blob = new Blob(['mock'], {type: 'image/jpeg'})
|
|
66
|
+
callback(blob)
|
|
67
|
+
}) as any
|
|
37
68
|
})
|
|
38
69
|
|
|
39
70
|
afterEach(() => {
|
|
@@ -334,7 +365,7 @@ describe('ImagePickerProvider', () => {
|
|
|
334
365
|
<button
|
|
335
366
|
type="button"
|
|
336
367
|
onClick={() =>
|
|
337
|
-
openCamera('front').catch(() => {
|
|
368
|
+
openCamera({cameraFacing: 'front'}).catch(() => {
|
|
338
369
|
// Ignore errors from cleanup
|
|
339
370
|
})
|
|
340
371
|
}
|
|
@@ -9,12 +9,29 @@ import React, {
|
|
|
9
9
|
|
|
10
10
|
import {useRequestPermissions} from '../hooks/util/useRequestPermissions'
|
|
11
11
|
import {useReportInteraction} from '../internal/useReportInteraction'
|
|
12
|
+
import {resizeImage} from '../internal/utils/resizeImage'
|
|
12
13
|
|
|
14
|
+
export type ImageQuality = 'low' | 'medium' | 'high' | 'original'
|
|
13
15
|
export type CameraFacing = 'front' | 'back'
|
|
16
|
+
export interface CustomImageQuality {
|
|
17
|
+
size?: number
|
|
18
|
+
compression?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface OpenCameraParams {
|
|
22
|
+
cameraFacing?: CameraFacing
|
|
23
|
+
quality?: ImageQuality
|
|
24
|
+
customQuality?: CustomImageQuality
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface OpenGalleryParams {
|
|
28
|
+
quality?: ImageQuality
|
|
29
|
+
customQuality?: CustomImageQuality
|
|
30
|
+
}
|
|
14
31
|
|
|
15
32
|
interface ImagePickerContextValue {
|
|
16
|
-
openCamera: (
|
|
17
|
-
openGallery: () => Promise<File>
|
|
33
|
+
openCamera: (params?: OpenCameraParams) => Promise<File>
|
|
34
|
+
openGallery: (params?: OpenGalleryParams) => Promise<File>
|
|
18
35
|
}
|
|
19
36
|
|
|
20
37
|
const ImagePickerContext = createContext<ImagePickerContextValue | null>(null)
|
|
@@ -44,7 +61,8 @@ export function ImagePickerProvider({children}: ImagePickerProviderProps) {
|
|
|
44
61
|
handler: () => void
|
|
45
62
|
} | null>(null)
|
|
46
63
|
const activeOperationRef = useRef<'gallery' | 'camera' | null>(null)
|
|
47
|
-
|
|
64
|
+
const qualityRef = useRef<ImageQuality>('medium')
|
|
65
|
+
const customQualityRef = useRef<CustomImageQuality>(undefined)
|
|
48
66
|
const {requestPermission} = useRequestPermissions()
|
|
49
67
|
const {reportInteraction} = useReportInteraction()
|
|
50
68
|
|
|
@@ -77,26 +95,41 @@ export function ImagePickerProvider({children}: ImagePickerProviderProps) {
|
|
|
77
95
|
resolveRef.current = null
|
|
78
96
|
rejectRef.current = null
|
|
79
97
|
activeOperationRef.current = null
|
|
98
|
+
qualityRef.current = 'medium'
|
|
99
|
+
customQualityRef.current = undefined
|
|
80
100
|
}
|
|
81
101
|
}, [reportInteraction])
|
|
82
102
|
|
|
83
103
|
const handleFileChange = useCallback(
|
|
84
|
-
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
85
|
-
const
|
|
104
|
+
async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
105
|
+
const {target} = event
|
|
106
|
+
const file = target.files?.[0]
|
|
86
107
|
|
|
87
108
|
if (file && resolveRef.current) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
} else if (activeOperationRef.current === 'camera') {
|
|
94
|
-
reportInteraction({
|
|
95
|
-
interactionType: 'camera_success',
|
|
109
|
+
try {
|
|
110
|
+
const resizedFile = await resizeImage({
|
|
111
|
+
file,
|
|
112
|
+
quality: qualityRef.current,
|
|
113
|
+
customQuality: customQualityRef.current,
|
|
96
114
|
})
|
|
97
|
-
}
|
|
98
115
|
|
|
99
|
-
|
|
116
|
+
if (activeOperationRef.current === 'gallery') {
|
|
117
|
+
reportInteraction({
|
|
118
|
+
interactionType: 'image_picker_success',
|
|
119
|
+
})
|
|
120
|
+
} else if (activeOperationRef.current === 'camera') {
|
|
121
|
+
reportInteraction({
|
|
122
|
+
interactionType: 'camera_success',
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
resolveRef.current(resizedFile)
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.warn('Image resize failed, using original:', error)
|
|
129
|
+
if (resolveRef.current) {
|
|
130
|
+
resolveRef.current(file)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
100
133
|
|
|
101
134
|
resolveRef.current = null
|
|
102
135
|
rejectRef.current = null
|
|
@@ -105,80 +138,90 @@ export function ImagePickerProvider({children}: ImagePickerProviderProps) {
|
|
|
105
138
|
cleanupCancelHandler()
|
|
106
139
|
}
|
|
107
140
|
|
|
108
|
-
|
|
141
|
+
target.value = ''
|
|
109
142
|
},
|
|
110
143
|
[cleanupCancelHandler, reportInteraction]
|
|
111
144
|
)
|
|
112
145
|
|
|
113
|
-
const openGallery = useCallback(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
resolveRef.current = resolve
|
|
119
|
-
rejectRef.current = reject
|
|
120
|
-
activeOperationRef.current = 'gallery'
|
|
121
|
-
|
|
122
|
-
const input = galleryInputRef.current
|
|
146
|
+
const openGallery = useCallback(
|
|
147
|
+
({quality = 'medium', customQuality}: OpenGalleryParams = {}) => {
|
|
148
|
+
return new Promise<File>((resolve, reject) => {
|
|
149
|
+
rejectPendingPromise()
|
|
150
|
+
cleanupCancelHandler()
|
|
123
151
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
reject(error)
|
|
131
|
-
resolveRef.current = null
|
|
132
|
-
rejectRef.current = null
|
|
133
|
-
activeOperationRef.current = null
|
|
134
|
-
return
|
|
135
|
-
}
|
|
152
|
+
qualityRef.current = quality
|
|
153
|
+
customQualityRef.current = customQuality
|
|
154
|
+
resolveRef.current = resolve
|
|
155
|
+
rejectRef.current = reject
|
|
156
|
+
activeOperationRef.current = 'gallery'
|
|
157
|
+
const input = galleryInputRef.current
|
|
136
158
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const error = new Error('User cancelled file selection')
|
|
159
|
+
if (!input) {
|
|
160
|
+
const error = new Error('Gallery input not found')
|
|
140
161
|
reportInteraction({
|
|
141
162
|
interactionType: 'image_picker_error',
|
|
142
163
|
interactionValue: error.message,
|
|
143
164
|
})
|
|
144
|
-
|
|
165
|
+
reject(error)
|
|
145
166
|
resolveRef.current = null
|
|
146
167
|
rejectRef.current = null
|
|
147
168
|
activeOperationRef.current = null
|
|
169
|
+
return
|
|
148
170
|
}
|
|
149
|
-
cleanupCancelHandler()
|
|
150
|
-
}
|
|
151
171
|
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
const handleCancel = () => {
|
|
173
|
+
if (rejectRef.current) {
|
|
174
|
+
const error = new Error('User cancelled file selection')
|
|
175
|
+
reportInteraction({
|
|
176
|
+
interactionType: 'image_picker_error',
|
|
177
|
+
interactionValue: error.message,
|
|
178
|
+
})
|
|
179
|
+
rejectRef.current(error)
|
|
180
|
+
resolveRef.current = null
|
|
181
|
+
rejectRef.current = null
|
|
182
|
+
activeOperationRef.current = null
|
|
183
|
+
}
|
|
184
|
+
cleanupCancelHandler()
|
|
185
|
+
}
|
|
154
186
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
})
|
|
187
|
+
input.addEventListener('cancel', handleCancel)
|
|
188
|
+
activeCancelHandlerRef.current = {input, handler: handleCancel}
|
|
158
189
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// This will show both Camera and Gallery
|
|
162
|
-
input.click()
|
|
163
|
-
})
|
|
164
|
-
.catch(() => {
|
|
165
|
-
// Show only Gallery
|
|
166
|
-
input.click()
|
|
190
|
+
reportInteraction({
|
|
191
|
+
interactionType: 'image_picker_open',
|
|
167
192
|
})
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
193
|
+
|
|
194
|
+
requestPermission({permission: 'CAMERA'})
|
|
195
|
+
.then(() => {
|
|
196
|
+
// This will show both Camera and Gallery
|
|
197
|
+
input.click()
|
|
198
|
+
})
|
|
199
|
+
.catch(() => {
|
|
200
|
+
// Show only Gallery
|
|
201
|
+
input.click()
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
},
|
|
205
|
+
[
|
|
206
|
+
rejectPendingPromise,
|
|
207
|
+
cleanupCancelHandler,
|
|
208
|
+
requestPermission,
|
|
209
|
+
reportInteraction,
|
|
210
|
+
]
|
|
211
|
+
)
|
|
175
212
|
|
|
176
213
|
const openCamera = useCallback(
|
|
177
|
-
(
|
|
214
|
+
({
|
|
215
|
+
cameraFacing = 'back',
|
|
216
|
+
quality = 'medium',
|
|
217
|
+
customQuality,
|
|
218
|
+
}: OpenCameraParams = {}) => {
|
|
178
219
|
return new Promise<File>((resolve, reject) => {
|
|
179
220
|
rejectPendingPromise()
|
|
180
221
|
cleanupCancelHandler()
|
|
181
222
|
|
|
223
|
+
qualityRef.current = quality
|
|
224
|
+
customQualityRef.current = customQuality
|
|
182
225
|
resolveRef.current = resolve
|
|
183
226
|
rejectRef.current = reject
|
|
184
227
|
activeOperationRef.current = 'camera'
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
-
import { Skeleton as e } from "../ui/skeleton.js";
|
|
3
|
-
import { TrackingPixel as i } from "./tracking-pixel.js";
|
|
4
|
-
function c({ loadingComponent: r, fetchMore: n }) {
|
|
5
|
-
return /* @__PURE__ */ o(i, { onImpression: n, children: r ?? /* @__PURE__ */ o(e, { className: "h-10 w-full p-8" }) });
|
|
6
|
-
}
|
|
7
|
-
export {
|
|
8
|
-
c as Pagination
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=pagination.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sources":["../../../src/components/atoms/pagination.tsx"],"sourcesContent":["import {Skeleton} from '../ui/skeleton'\n\nimport {TrackingPixel} from './tracking-pixel'\n\ninterface Props {\n loadingComponent?: React.ReactNode\n isFetchingMore?: boolean\n fetchMore: () => void\n}\n\nexport function Pagination({loadingComponent, fetchMore}: Props) {\n const loadingPlaceholder = loadingComponent ?? (\n <Skeleton className=\"h-10 w-full p-8\" />\n )\n\n return (\n <TrackingPixel onImpression={fetchMore}>{loadingPlaceholder}</TrackingPixel>\n )\n}\n"],"names":["Pagination","loadingComponent","fetchMore","jsx","TrackingPixel","Skeleton"],"mappings":";;;AAUO,SAASA,EAAW,EAAC,kBAAAC,GAAkB,WAAAC,KAAmB;AAK/D,SACG,gBAAAC,EAAAC,GAAA,EAAc,cAAcF,GAAY,UALhBD,KACxB,gBAAAE,EAAAE,GAAA,EAAS,WAAU,mBAAkB,GAIsB;AAEhE;"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsx as m } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback as n } from "react";
|
|
3
|
-
import { InView as c } from "../../shop-minis-react/node_modules/.pnpm/react-intersection-observer@9.13.1_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.js";
|
|
4
|
-
const x = ({
|
|
5
|
-
children: o,
|
|
6
|
-
onImpression: r,
|
|
7
|
-
triggerOnce: i = !1,
|
|
8
|
-
threshold: t,
|
|
9
|
-
className: a
|
|
10
|
-
}) => {
|
|
11
|
-
const e = n(
|
|
12
|
-
(f) => {
|
|
13
|
-
f && r?.();
|
|
14
|
-
},
|
|
15
|
-
[r]
|
|
16
|
-
);
|
|
17
|
-
return /* @__PURE__ */ m(
|
|
18
|
-
c,
|
|
19
|
-
{
|
|
20
|
-
as: "div",
|
|
21
|
-
onChange: e,
|
|
22
|
-
triggerOnce: i,
|
|
23
|
-
className: a,
|
|
24
|
-
threshold: t,
|
|
25
|
-
children: o
|
|
26
|
-
}
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
export {
|
|
30
|
-
x as TrackingPixel
|
|
31
|
-
};
|
|
32
|
-
//# sourceMappingURL=tracking-pixel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tracking-pixel.js","sources":["../../../src/components/atoms/tracking-pixel.tsx"],"sourcesContent":["import {useCallback} from 'react'\n\nimport {InView} from 'react-intersection-observer'\n\ninterface Props {\n children: React.ReactNode\n onImpression?: () => void\n triggerOnce?: boolean\n threshold?: number\n className?: string\n}\n\nexport const TrackingPixel = ({\n children,\n onImpression,\n triggerOnce = false,\n threshold,\n className,\n}: Props) => {\n const onChange = useCallback(\n (inView: boolean) => {\n if (inView) {\n onImpression?.()\n }\n },\n [onImpression]\n )\n\n return (\n <InView\n as=\"div\"\n onChange={onChange}\n triggerOnce={triggerOnce}\n className={className}\n threshold={threshold}\n >\n {children}\n </InView>\n )\n}\n"],"names":["TrackingPixel","children","onImpression","triggerOnce","threshold","className","onChange","useCallback","inView","jsx","InView"],"mappings":";;;AAYO,MAAMA,IAAgB,CAAC;AAAA,EAC5B,UAAAC;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,WAAAC;AAAA,EACA,WAAAC;AACF,MAAa;AACX,QAAMC,IAAWC;AAAA,IACf,CAACC,MAAoB;AACnB,MAAIA,KACaN,IAAA;AAAA,IAEnB;AAAA,IACA,CAACA,CAAY;AAAA,EACf;AAGE,SAAA,gBAAAO;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,IAAG;AAAA,MACH,UAAAJ;AAAA,MACA,aAAAH;AAAA,MACA,WAAAE;AAAA,MACA,WAAAD;AAAA,MAEC,UAAAH;AAAA,IAAA;AAAA,EACH;AAEJ;"}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import * as b from "react";
|
|
2
|
-
var V = Object.defineProperty, w = (e, t, i) => t in e ? V(e, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[t] = i, u = (e, t, i) => w(e, typeof t != "symbol" ? t + "" : t, i), p = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new WeakMap(), f = 0, _ = void 0;
|
|
3
|
-
function I(e) {
|
|
4
|
-
return e ? (l.has(e) || (f += 1, l.set(e, f.toString())), l.get(e)) : "0";
|
|
5
|
-
}
|
|
6
|
-
function y(e) {
|
|
7
|
-
return Object.keys(e).sort().filter(
|
|
8
|
-
(t) => e[t] !== void 0
|
|
9
|
-
).map((t) => `${t}_${t === "root" ? I(e.root) : e[t]}`).toString();
|
|
10
|
-
}
|
|
11
|
-
function m(e) {
|
|
12
|
-
const t = y(e);
|
|
13
|
-
let i = p.get(t);
|
|
14
|
-
if (!i) {
|
|
15
|
-
const r = /* @__PURE__ */ new Map();
|
|
16
|
-
let d;
|
|
17
|
-
const n = new IntersectionObserver((o) => {
|
|
18
|
-
o.forEach((s) => {
|
|
19
|
-
var h;
|
|
20
|
-
const c = s.isIntersecting && d.some((a) => s.intersectionRatio >= a);
|
|
21
|
-
e.trackVisibility && typeof s.isVisible > "u" && (s.isVisible = c), (h = r.get(s.target)) == null || h.forEach((a) => {
|
|
22
|
-
a(c, s);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
}, e);
|
|
26
|
-
d = n.thresholds || (Array.isArray(e.threshold) ? e.threshold : [e.threshold || 0]), i = {
|
|
27
|
-
id: t,
|
|
28
|
-
observer: n,
|
|
29
|
-
elements: r
|
|
30
|
-
}, p.set(t, i);
|
|
31
|
-
}
|
|
32
|
-
return i;
|
|
33
|
-
}
|
|
34
|
-
function M(e, t, i = {}, r = _) {
|
|
35
|
-
if (typeof window.IntersectionObserver > "u" && r !== void 0) {
|
|
36
|
-
const h = e.getBoundingClientRect();
|
|
37
|
-
return t(r, {
|
|
38
|
-
isIntersecting: r,
|
|
39
|
-
target: e,
|
|
40
|
-
intersectionRatio: typeof i.threshold == "number" ? i.threshold : 0,
|
|
41
|
-
time: 0,
|
|
42
|
-
boundingClientRect: h,
|
|
43
|
-
intersectionRect: h,
|
|
44
|
-
rootBounds: h
|
|
45
|
-
}), () => {
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
const { id: d, observer: n, elements: o } = m(i), s = o.get(e) || [];
|
|
49
|
-
return o.has(e) || o.set(e, s), s.push(t), n.observe(e), function() {
|
|
50
|
-
s.splice(s.indexOf(t), 1), s.length === 0 && (o.delete(e), n.unobserve(e)), o.size === 0 && (n.disconnect(), p.delete(d));
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function O(e) {
|
|
54
|
-
return typeof e.children != "function";
|
|
55
|
-
}
|
|
56
|
-
var R = class extends b.Component {
|
|
57
|
-
constructor(e) {
|
|
58
|
-
super(e), u(this, "node", null), u(this, "_unobserveCb", null), u(this, "handleNode", (t) => {
|
|
59
|
-
this.node && (this.unobserve(), !t && !this.props.triggerOnce && !this.props.skip && this.setState({ inView: !!this.props.initialInView, entry: void 0 })), this.node = t || null, this.observeNode();
|
|
60
|
-
}), u(this, "handleChange", (t, i) => {
|
|
61
|
-
t && this.props.triggerOnce && this.unobserve(), O(this.props) || this.setState({ inView: t, entry: i }), this.props.onChange && this.props.onChange(t, i);
|
|
62
|
-
}), this.state = {
|
|
63
|
-
inView: !!e.initialInView,
|
|
64
|
-
entry: void 0
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
componentDidMount() {
|
|
68
|
-
this.unobserve(), this.observeNode();
|
|
69
|
-
}
|
|
70
|
-
componentDidUpdate(e) {
|
|
71
|
-
(e.rootMargin !== this.props.rootMargin || e.root !== this.props.root || e.threshold !== this.props.threshold || e.skip !== this.props.skip || e.trackVisibility !== this.props.trackVisibility || e.delay !== this.props.delay) && (this.unobserve(), this.observeNode());
|
|
72
|
-
}
|
|
73
|
-
componentWillUnmount() {
|
|
74
|
-
this.unobserve();
|
|
75
|
-
}
|
|
76
|
-
observeNode() {
|
|
77
|
-
if (!this.node || this.props.skip) return;
|
|
78
|
-
const {
|
|
79
|
-
threshold: e,
|
|
80
|
-
root: t,
|
|
81
|
-
rootMargin: i,
|
|
82
|
-
trackVisibility: r,
|
|
83
|
-
delay: d,
|
|
84
|
-
fallbackInView: n
|
|
85
|
-
} = this.props;
|
|
86
|
-
this._unobserveCb = M(
|
|
87
|
-
this.node,
|
|
88
|
-
this.handleChange,
|
|
89
|
-
{
|
|
90
|
-
threshold: e,
|
|
91
|
-
root: t,
|
|
92
|
-
rootMargin: i,
|
|
93
|
-
// @ts-ignore
|
|
94
|
-
trackVisibility: r,
|
|
95
|
-
// @ts-ignore
|
|
96
|
-
delay: d
|
|
97
|
-
},
|
|
98
|
-
n
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
unobserve() {
|
|
102
|
-
this._unobserveCb && (this._unobserveCb(), this._unobserveCb = null);
|
|
103
|
-
}
|
|
104
|
-
render() {
|
|
105
|
-
const { children: e } = this.props;
|
|
106
|
-
if (typeof e == "function") {
|
|
107
|
-
const { inView: g, entry: C } = this.state;
|
|
108
|
-
return e({ inView: g, entry: C, ref: this.handleNode });
|
|
109
|
-
}
|
|
110
|
-
const {
|
|
111
|
-
as: t,
|
|
112
|
-
triggerOnce: i,
|
|
113
|
-
threshold: r,
|
|
114
|
-
root: d,
|
|
115
|
-
rootMargin: n,
|
|
116
|
-
onChange: o,
|
|
117
|
-
skip: s,
|
|
118
|
-
trackVisibility: h,
|
|
119
|
-
delay: c,
|
|
120
|
-
initialInView: a,
|
|
121
|
-
fallbackInView: N,
|
|
122
|
-
...v
|
|
123
|
-
} = this.props;
|
|
124
|
-
return b.createElement(
|
|
125
|
-
t || "div",
|
|
126
|
-
{ ref: this.handleNode, ...v },
|
|
127
|
-
e
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
export {
|
|
132
|
-
R as InView,
|
|
133
|
-
M as observe
|
|
134
|
-
};
|
|
135
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../../../../node_modules/.pnpm/react-intersection-observer@9.13.1_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.mjs"],"sourcesContent":["\"use client\";\nvar __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n\n// src/InView.tsx\nimport * as React from \"react\";\n\n// src/observe.ts\nvar observerMap = /* @__PURE__ */ new Map();\nvar RootIds = /* @__PURE__ */ new WeakMap();\nvar rootId = 0;\nvar unsupportedValue = void 0;\nfunction defaultFallbackInView(inView) {\n unsupportedValue = inView;\n}\nfunction getRootId(root) {\n if (!root) return \"0\";\n if (RootIds.has(root)) return RootIds.get(root);\n rootId += 1;\n RootIds.set(root, rootId.toString());\n return RootIds.get(root);\n}\nfunction optionsToId(options) {\n return Object.keys(options).sort().filter(\n (key) => options[key] !== void 0\n ).map((key) => {\n return `${key}_${key === \"root\" ? getRootId(options.root) : options[key]}`;\n }).toString();\n}\nfunction createObserver(options) {\n const id = optionsToId(options);\n let instance = observerMap.get(id);\n if (!instance) {\n const elements = /* @__PURE__ */ new Map();\n let thresholds;\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n var _a;\n const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold);\n if (options.trackVisibility && typeof entry.isVisible === \"undefined\") {\n entry.isVisible = inView;\n }\n (_a = elements.get(entry.target)) == null ? void 0 : _a.forEach((callback) => {\n callback(inView, entry);\n });\n });\n }, options);\n thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);\n instance = {\n id,\n observer,\n elements\n };\n observerMap.set(id, instance);\n }\n return instance;\n}\nfunction observe(element, callback, options = {}, fallbackInView = unsupportedValue) {\n if (typeof window.IntersectionObserver === \"undefined\" && fallbackInView !== void 0) {\n const bounds = element.getBoundingClientRect();\n callback(fallbackInView, {\n isIntersecting: fallbackInView,\n target: element,\n intersectionRatio: typeof options.threshold === \"number\" ? options.threshold : 0,\n time: 0,\n boundingClientRect: bounds,\n intersectionRect: bounds,\n rootBounds: bounds\n });\n return () => {\n };\n }\n const { id, observer, elements } = createObserver(options);\n const callbacks = elements.get(element) || [];\n if (!elements.has(element)) {\n elements.set(element, callbacks);\n }\n callbacks.push(callback);\n observer.observe(element);\n return function unobserve() {\n callbacks.splice(callbacks.indexOf(callback), 1);\n if (callbacks.length === 0) {\n elements.delete(element);\n observer.unobserve(element);\n }\n if (elements.size === 0) {\n observer.disconnect();\n observerMap.delete(id);\n }\n };\n}\n\n// src/InView.tsx\nfunction isPlainChildren(props) {\n return typeof props.children !== \"function\";\n}\nvar InView = class extends React.Component {\n constructor(props) {\n super(props);\n __publicField(this, \"node\", null);\n __publicField(this, \"_unobserveCb\", null);\n __publicField(this, \"handleNode\", (node) => {\n if (this.node) {\n this.unobserve();\n if (!node && !this.props.triggerOnce && !this.props.skip) {\n this.setState({ inView: !!this.props.initialInView, entry: void 0 });\n }\n }\n this.node = node ? node : null;\n this.observeNode();\n });\n __publicField(this, \"handleChange\", (inView, entry) => {\n if (inView && this.props.triggerOnce) {\n this.unobserve();\n }\n if (!isPlainChildren(this.props)) {\n this.setState({ inView, entry });\n }\n if (this.props.onChange) {\n this.props.onChange(inView, entry);\n }\n });\n this.state = {\n inView: !!props.initialInView,\n entry: void 0\n };\n }\n componentDidMount() {\n this.unobserve();\n this.observeNode();\n }\n componentDidUpdate(prevProps) {\n if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {\n this.unobserve();\n this.observeNode();\n }\n }\n componentWillUnmount() {\n this.unobserve();\n }\n observeNode() {\n if (!this.node || this.props.skip) return;\n const {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n fallbackInView\n } = this.props;\n this._unobserveCb = observe(\n this.node,\n this.handleChange,\n {\n threshold,\n root,\n rootMargin,\n // @ts-ignore\n trackVisibility,\n // @ts-ignore\n delay\n },\n fallbackInView\n );\n }\n unobserve() {\n if (this._unobserveCb) {\n this._unobserveCb();\n this._unobserveCb = null;\n }\n }\n render() {\n const { children } = this.props;\n if (typeof children === \"function\") {\n const { inView, entry } = this.state;\n return children({ inView, entry, ref: this.handleNode });\n }\n const {\n as,\n triggerOnce,\n threshold,\n root,\n rootMargin,\n onChange,\n skip,\n trackVisibility,\n delay,\n initialInView,\n fallbackInView,\n ...props\n } = this.props;\n return React.createElement(\n as || \"div\",\n { ref: this.handleNode, ...props },\n children\n );\n }\n};\n\n// src/useInView.tsx\nimport * as React2 from \"react\";\nfunction useInView({\n threshold,\n delay,\n trackVisibility,\n rootMargin,\n root,\n triggerOnce,\n skip,\n initialInView,\n fallbackInView,\n onChange\n} = {}) {\n var _a;\n const [ref, setRef] = React2.useState(null);\n const callback = React2.useRef();\n const [state, setState] = React2.useState({\n inView: !!initialInView,\n entry: void 0\n });\n callback.current = onChange;\n React2.useEffect(\n () => {\n if (skip || !ref) return;\n let unobserve;\n unobserve = observe(\n ref,\n (inView, entry) => {\n setState({\n inView,\n entry\n });\n if (callback.current) callback.current(inView, entry);\n if (entry.isIntersecting && triggerOnce && unobserve) {\n unobserve();\n unobserve = void 0;\n }\n },\n {\n root,\n rootMargin,\n threshold,\n // @ts-ignore\n trackVisibility,\n // @ts-ignore\n delay\n },\n fallbackInView\n );\n return () => {\n if (unobserve) {\n unobserve();\n }\n };\n },\n // We break the rule here, because we aren't including the actual `threshold` variable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n // If the threshold is an array, convert it to a string, so it won't change between renders.\n Array.isArray(threshold) ? threshold.toString() : threshold,\n ref,\n root,\n rootMargin,\n triggerOnce,\n skip,\n trackVisibility,\n fallbackInView,\n delay\n ]\n );\n const entryTarget = (_a = state.entry) == null ? void 0 : _a.target;\n const previousEntryTarget = React2.useRef();\n if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) {\n previousEntryTarget.current = entryTarget;\n setState({\n inView: !!initialInView,\n entry: void 0\n });\n }\n const result = [setRef, state.inView, state.entry];\n result.ref = result[0];\n result.inView = result[1];\n result.entry = result[2];\n return result;\n}\nexport {\n InView,\n defaultFallbackInView,\n observe,\n useInView\n};\n//# sourceMappingURL=index.mjs.map"],"names":["__defProp","__defNormalProp","obj","key","value","__publicField","observerMap","RootIds","rootId","unsupportedValue","getRootId","root","optionsToId","options","createObserver","id","instance","elements","thresholds","observer","entries","entry","_a","inView","threshold","callback","observe","element","fallbackInView","bounds","callbacks","isPlainChildren","props","InView","React","node","prevProps","rootMargin","trackVisibility","delay","children","as","triggerOnce","onChange","skip","initialInView"],"mappings":";AACA,IAAIA,IAAY,OAAO,gBACnBC,IAAkB,CAACC,GAAKC,GAAKC,MAAUD,KAAOD,IAAMF,EAAUE,GAAKC,GAAK,EAAE,YAAY,IAAM,cAAc,IAAM,UAAU,IAAM,OAAAC,EAAK,CAAE,IAAIF,EAAIC,CAAG,IAAIC,GACtJC,IAAgB,CAACH,GAAKC,GAAKC,MAAUH,EAAgBC,GAAK,OAAOC,KAAQ,WAAWA,IAAM,KAAKA,GAAKC,CAAK,GAMzGE,IAA8B,oBAAI,IAAK,GACvCC,IAA0B,oBAAI,QAAS,GACvCC,IAAS,GACTC,IAAmB;AAIvB,SAASC,EAAUC,GAAM;AACvB,SAAKA,KACDJ,EAAQ,IAAII,CAAI,MACpBH,KAAU,GACVD,EAAQ,IAAII,GAAMH,EAAO,SAAQ,CAAE,IAC5BD,EAAQ,IAAII,CAAI,KAJL;AAKpB;AACA,SAASC,EAAYC,GAAS;AAC5B,SAAO,OAAO,KAAKA,CAAO,EAAE,KAAM,EAAC;AAAA,IACjC,CAACV,MAAQU,EAAQV,CAAG,MAAM;AAAA,EAC9B,EAAI,IAAI,CAACA,MACE,GAAGA,CAAG,IAAIA,MAAQ,SAASO,EAAUG,EAAQ,IAAI,IAAIA,EAAQV,CAAG,CAAC,EACzE,EAAE,SAAU;AACf;AACA,SAASW,EAAeD,GAAS;AAC/B,QAAME,IAAKH,EAAYC,CAAO;AAC9B,MAAIG,IAAWV,EAAY,IAAIS,CAAE;AACjC,MAAI,CAACC,GAAU;AACb,UAAMC,IAA2B,oBAAI,IAAK;AAC1C,QAAIC;AACJ,UAAMC,IAAW,IAAI,qBAAqB,CAACC,MAAY;AACrD,MAAAA,EAAQ,QAAQ,CAACC,MAAU;AACzB,YAAIC;AACJ,cAAMC,IAASF,EAAM,kBAAkBH,EAAW,KAAK,CAACM,MAAcH,EAAM,qBAAqBG,CAAS;AAC1G,QAAIX,EAAQ,mBAAmB,OAAOQ,EAAM,YAAc,QACxDA,EAAM,YAAYE,KAEnBD,IAAKL,EAAS,IAAII,EAAM,MAAM,MAAM,QAAgBC,EAAG,QAAQ,CAACG,MAAa;AAC5E,UAAAA,EAASF,GAAQF,CAAK;AAAA,QAChC,CAAS;AAAA,MACT,CAAO;AAAA,IACF,GAAER,CAAO;AACV,IAAAK,IAAaC,EAAS,eAAe,MAAM,QAAQN,EAAQ,SAAS,IAAIA,EAAQ,YAAY,CAACA,EAAQ,aAAa,CAAC,IACnHG,IAAW;AAAA,MACT,IAAAD;AAAA,MACA,UAAAI;AAAA,MACA,UAAAF;AAAA,IACD,GACDX,EAAY,IAAIS,GAAIC,CAAQ;AAAA,EAChC;AACE,SAAOA;AACT;AACA,SAASU,EAAQC,GAASF,GAAUZ,IAAU,CAAE,GAAEe,IAAiBnB,GAAkB;AACnF,MAAI,OAAO,OAAO,uBAAyB,OAAemB,MAAmB,QAAQ;AACnF,UAAMC,IAASF,EAAQ,sBAAuB;AAC9C,WAAAF,EAASG,GAAgB;AAAA,MACvB,gBAAgBA;AAAA,MAChB,QAAQD;AAAA,MACR,mBAAmB,OAAOd,EAAQ,aAAc,WAAWA,EAAQ,YAAY;AAAA,MAC/E,MAAM;AAAA,MACN,oBAAoBgB;AAAA,MACpB,kBAAkBA;AAAA,MAClB,YAAYA;AAAA,IAClB,CAAK,GACM,MAAM;AAAA,IACZ;AAAA,EACL;AACE,QAAM,EAAE,IAAAd,GAAI,UAAAI,GAAU,UAAAF,EAAQ,IAAKH,EAAeD,CAAO,GACnDiB,IAAYb,EAAS,IAAIU,CAAO,KAAK,CAAE;AAC7C,SAAKV,EAAS,IAAIU,CAAO,KACvBV,EAAS,IAAIU,GAASG,CAAS,GAEjCA,EAAU,KAAKL,CAAQ,GACvBN,EAAS,QAAQQ,CAAO,GACjB,WAAqB;AAC1B,IAAAG,EAAU,OAAOA,EAAU,QAAQL,CAAQ,GAAG,CAAC,GAC3CK,EAAU,WAAW,MACvBb,EAAS,OAAOU,CAAO,GACvBR,EAAS,UAAUQ,CAAO,IAExBV,EAAS,SAAS,MACpBE,EAAS,WAAY,GACrBb,EAAY,OAAOS,CAAE;AAAA,EAExB;AACH;AAGA,SAASgB,EAAgBC,GAAO;AAC9B,SAAO,OAAOA,EAAM,YAAa;AACnC;AACG,IAACC,IAAS,cAAcC,EAAM,UAAU;AAAA,EACzC,YAAYF,GAAO;AACjB,UAAMA,CAAK,GACX3B,EAAc,MAAM,QAAQ,IAAI,GAChCA,EAAc,MAAM,gBAAgB,IAAI,GACxCA,EAAc,MAAM,cAAc,CAAC8B,MAAS;AAC1C,MAAI,KAAK,SACP,KAAK,UAAW,GACZ,CAACA,KAAQ,CAAC,KAAK,MAAM,eAAe,CAAC,KAAK,MAAM,QAClD,KAAK,SAAS,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,eAAe,OAAO,QAAQ,IAGvE,KAAK,OAAOA,KAAc,MAC1B,KAAK,YAAa;AAAA,IACxB,CAAK,GACD9B,EAAc,MAAM,gBAAgB,CAACkB,GAAQF,MAAU;AACrD,MAAIE,KAAU,KAAK,MAAM,eACvB,KAAK,UAAW,GAEbQ,EAAgB,KAAK,KAAK,KAC7B,KAAK,SAAS,EAAE,QAAAR,GAAQ,OAAAF,EAAK,CAAE,GAE7B,KAAK,MAAM,YACb,KAAK,MAAM,SAASE,GAAQF,CAAK;AAAA,IAEzC,CAAK,GACD,KAAK,QAAQ;AAAA,MACX,QAAQ,CAAC,CAACW,EAAM;AAAA,MAChB,OAAO;AAAA,IACR;AAAA,EACL;AAAA,EACE,oBAAoB;AAClB,SAAK,UAAW,GAChB,KAAK,YAAa;AAAA,EACtB;AAAA,EACE,mBAAmBI,GAAW;AAC5B,KAAIA,EAAU,eAAe,KAAK,MAAM,cAAcA,EAAU,SAAS,KAAK,MAAM,QAAQA,EAAU,cAAc,KAAK,MAAM,aAAaA,EAAU,SAAS,KAAK,MAAM,QAAQA,EAAU,oBAAoB,KAAK,MAAM,mBAAmBA,EAAU,UAAU,KAAK,MAAM,WAC3Q,KAAK,UAAW,GAChB,KAAK,YAAa;AAAA,EAExB;AAAA,EACE,uBAAuB;AACrB,SAAK,UAAW;AAAA,EACpB;AAAA,EACE,cAAc;AACZ,QAAI,CAAC,KAAK,QAAQ,KAAK,MAAM,KAAM;AACnC,UAAM;AAAA,MACJ,WAAAZ;AAAA,MACA,MAAAb;AAAA,MACA,YAAA0B;AAAA,MACA,iBAAAC;AAAA,MACA,OAAAC;AAAA,MACA,gBAAAX;AAAA,IACD,IAAG,KAAK;AACT,SAAK,eAAeF;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE,WAAAF;AAAA,QACA,MAAAb;AAAA,QACA,YAAA0B;AAAA;AAAA,QAEA,iBAAAC;AAAA;AAAA,QAEA,OAAAC;AAAA,MACD;AAAA,MACDX;AAAA,IACD;AAAA,EACL;AAAA,EACE,YAAY;AACV,IAAI,KAAK,iBACP,KAAK,aAAc,GACnB,KAAK,eAAe;AAAA,EAE1B;AAAA,EACE,SAAS;AACP,UAAM,EAAE,UAAAY,MAAa,KAAK;AAC1B,QAAI,OAAOA,KAAa,YAAY;AAClC,YAAM,EAAE,QAAAjB,GAAQ,OAAAF,EAAO,IAAG,KAAK;AAC/B,aAAOmB,EAAS,EAAE,QAAAjB,GAAQ,OAAAF,GAAO,KAAK,KAAK,YAAY;AAAA,IAC7D;AACI,UAAM;AAAA,MACJ,IAAAoB;AAAA,MACA,aAAAC;AAAA,MACA,WAAAlB;AAAA,MACA,MAAAb;AAAA,MACA,YAAA0B;AAAA,MACA,UAAAM;AAAA,MACA,MAAAC;AAAA,MACA,iBAAAN;AAAA,MACA,OAAAC;AAAA,MACA,eAAAM;AAAA,MACA,gBAAAjB;AAAA,MACA,GAAGI;AAAA,IACJ,IAAG,KAAK;AACT,WAAOE,EAAM;AAAA,MACXO,KAAM;AAAA,MACN,EAAE,KAAK,KAAK,YAAY,GAAGT,EAAO;AAAA,MAClCQ;AAAA,IACD;AAAA,EACL;AACA;","x_google_ignoreList":[0]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {Skeleton} from '../ui/skeleton'
|
|
2
|
-
|
|
3
|
-
import {TrackingPixel} from './tracking-pixel'
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
loadingComponent?: React.ReactNode
|
|
7
|
-
isFetchingMore?: boolean
|
|
8
|
-
fetchMore: () => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function Pagination({loadingComponent, fetchMore}: Props) {
|
|
12
|
-
const loadingPlaceholder = loadingComponent ?? (
|
|
13
|
-
<Skeleton className="h-10 w-full p-8" />
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<TrackingPixel onImpression={fetchMore}>{loadingPlaceholder}</TrackingPixel>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {useCallback} from 'react'
|
|
2
|
-
|
|
3
|
-
import {InView} from 'react-intersection-observer'
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
children: React.ReactNode
|
|
7
|
-
onImpression?: () => void
|
|
8
|
-
triggerOnce?: boolean
|
|
9
|
-
threshold?: number
|
|
10
|
-
className?: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const TrackingPixel = ({
|
|
14
|
-
children,
|
|
15
|
-
onImpression,
|
|
16
|
-
triggerOnce = false,
|
|
17
|
-
threshold,
|
|
18
|
-
className,
|
|
19
|
-
}: Props) => {
|
|
20
|
-
const onChange = useCallback(
|
|
21
|
-
(inView: boolean) => {
|
|
22
|
-
if (inView) {
|
|
23
|
-
onImpression?.()
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
[onImpression]
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<InView
|
|
31
|
-
as="div"
|
|
32
|
-
onChange={onChange}
|
|
33
|
-
triggerOnce={triggerOnce}
|
|
34
|
-
className={className}
|
|
35
|
-
threshold={threshold}
|
|
36
|
-
>
|
|
37
|
-
{children}
|
|
38
|
-
</InView>
|
|
39
|
-
)
|
|
40
|
-
}
|