@mmmmzxe/react-360-viewer 0.1.12 → 0.1.14

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -663
  3. package/dist/inject-styles.js +1 -1
  4. package/dist/styles.css +1 -1
  5. package/package.json +3 -3
  6. package/src/components/ui/Badge/index.tsx +0 -45
  7. package/src/components/ui/Button/index.tsx +0 -67
  8. package/src/components/ui/Card/index.tsx +0 -74
  9. package/src/components/ui/Item/index.tsx +0 -136
  10. package/src/components/ui/Label/index.tsx +0 -20
  11. package/src/components/ui/Popover/index.tsx +0 -56
  12. package/src/components/ui/Separator/index.tsx +0 -30
  13. package/src/components/ui/Spinner/index.tsx +0 -11
  14. package/src/components/utils/index.ts +0 -6
  15. package/src/constants/viewer360ClassNames.ts +0 -42
  16. package/src/constants/viewer360Config.ts +0 -11
  17. package/src/constants/viewer360Labels.ts +0 -14
  18. package/src/constants/viewer360MarkerLabels.ts +0 -3
  19. package/src/feature/Viewer360.test.tsx +0 -47
  20. package/src/feature/Viewer360.tsx +0 -223
  21. package/src/feature/Viewer360AddModeBanner.tsx +0 -20
  22. package/src/feature/Viewer360FrameIndicator.tsx +0 -20
  23. package/src/feature/Viewer360HotspotOverlay.tsx +0 -57
  24. package/src/feature/Viewer360LoadingOverlay.tsx +0 -28
  25. package/src/feature/Viewer360MarkerPin.tsx +0 -105
  26. package/src/feature/Viewer360Toolbar.tsx +0 -75
  27. package/src/helpers/adjustViewerZoom.test.ts +0 -29
  28. package/src/helpers/adjustViewerZoom.ts +0 -64
  29. package/src/helpers/computeDragFrameIndex.test.ts +0 -20
  30. package/src/helpers/computeDragFrameIndex.ts +0 -23
  31. package/src/helpers/computeViewerImageLayout.test.ts +0 -48
  32. package/src/helpers/computeViewerImageLayout.ts +0 -114
  33. package/src/helpers/computeViewerPanOffset.ts +0 -18
  34. package/src/helpers/markerHelpers.test.ts +0 -38
  35. package/src/helpers/markerHelpers.ts +0 -33
  36. package/src/helpers/viewer360PropsHelpers.ts +0 -46
  37. package/src/helpers/viewerHelpers.ts +0 -74
  38. package/src/hooks/useViewer360.ts +0 -306
  39. package/src/index.ts +0 -68
  40. package/src/styles.css +0 -80
  41. package/src/types/Viewer360Hotspot.ts +0 -67
  42. package/src/types/Viewer360Marker.ts +0 -52
  43. package/src/types/Viewer360Props.ts +0 -108
  44. package/src/types/index.ts +0 -30
  45. package/src/utils/index.ts +0 -6
@@ -1,74 +0,0 @@
1
- import type { Viewer360Frame } from '../types';
2
-
3
- import { computeViewerImageLayout, type PanOffset } from './computeViewerImageLayout';
4
-
5
- type DrawFrameOnCanvasParams = {
6
- canvas: HTMLCanvasElement;
7
- container: HTMLDivElement;
8
- image: HTMLImageElement;
9
- zoom: number;
10
- pan: PanOffset;
11
- };
12
-
13
- export function drawFrameOnCanvas({ canvas, container, image, zoom, pan }: DrawFrameOnCanvasParams): void {
14
- if (!image.complete || !image.naturalWidth) return;
15
-
16
- const rect = container.getBoundingClientRect();
17
- const dpr = window.devicePixelRatio || 1;
18
-
19
- canvas.width = rect.width * dpr;
20
- canvas.height = rect.height * dpr;
21
- canvas.style.width = `${rect.width}px`;
22
- canvas.style.height = `${rect.height}px`;
23
-
24
- const ctx = canvas.getContext('2d');
25
- if (!ctx) return;
26
-
27
- ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
28
- ctx.clearRect(0, 0, rect.width, rect.height);
29
-
30
- const layout = computeViewerImageLayout({
31
- containerWidth: rect.width,
32
- containerHeight: rect.height,
33
- imageWidth: image.naturalWidth,
34
- imageHeight: image.naturalHeight,
35
- pan,
36
- });
37
-
38
- ctx.save();
39
- ctx.translate(layout.centerX, layout.centerY);
40
- ctx.scale(zoom, zoom);
41
- ctx.translate(-layout.centerX, -layout.centerY);
42
- ctx.drawImage(image, layout.offsetX, layout.offsetY, layout.drawWidth, layout.drawHeight);
43
- ctx.restore();
44
- }
45
-
46
- export function getFramesSignature(frames: Viewer360Frame[]): string {
47
- return frames.map((frame) => frame.id).join('-');
48
- }
49
-
50
- export function preloadFrameImage(frame: Viewer360Frame): Promise<HTMLImageElement> {
51
- return new Promise((resolve, reject) => {
52
- const img = new Image();
53
- img.onload = (): void => resolve(img);
54
- img.onerror = (): void => reject(new Error(`Failed to load frame: ${frame.src}`));
55
- img.src = frame.src;
56
- });
57
- }
58
-
59
- export async function preloadViewerFrames(frames: Viewer360Frame[]): Promise<HTMLImageElement[]> {
60
- const results = await Promise.allSettled(frames.map(preloadFrameImage));
61
-
62
- return results.map((result) => (result.status === 'fulfilled' ? result.value : new Image()));
63
- }
64
-
65
- export function hasLoadedViewerFrame(images: HTMLImageElement[]): boolean {
66
- return images.some((image) => image.complete && image.naturalWidth > 0);
67
- }
68
-
69
- export function filterHotspotsByFrame<TData>(
70
- hotspots: Array<{ frameIndex: number; data?: TData }>,
71
- frameIndex: number
72
- ): Array<{ frameIndex: number; data?: TData }> {
73
- return hotspots.filter((hotspot) => hotspot.frameIndex === frameIndex);
74
- }
@@ -1,306 +0,0 @@
1
- import type { PointerEvent as ReactPointerEvent, RefObject, WheelEvent as ReactWheelEvent } from 'react';
2
- import { useEffect, useMemo, useRef, useState } from 'react';
3
-
4
- import {
5
- applyWheelZoom,
6
- getViewerCursorClass,
7
- isResetDisabled,
8
- resolveViewer360Config,
9
- stepZoomIn,
10
- stepZoomOut,
11
- } from '../helpers/adjustViewerZoom';
12
- import { computeDragFrameIndex } from '../helpers/computeDragFrameIndex';
13
- import {
14
- computeHotspotPositionFromClick,
15
- computeHotspotScreenPosition,
16
- computeViewerImageLayout,
17
- type ViewerImageLayout,
18
- } from '../helpers/computeViewerImageLayout';
19
- import { computeViewerPanOffset } from '../helpers/computeViewerPanOffset';
20
- import {
21
- drawFrameOnCanvas,
22
- filterHotspotsByFrame,
23
- getFramesSignature,
24
- hasLoadedViewerFrame,
25
- preloadViewerFrames,
26
- } from '../helpers/viewerHelpers';
27
- import type {
28
- Viewer360Config,
29
- Viewer360Frame,
30
- Viewer360Hotspot,
31
- Viewer360HotspotPosition,
32
- Viewer360PanOffset,
33
- } from '../types';
34
-
35
- type UseViewer360Params<TData> = {
36
- frames: Viewer360Frame[];
37
- currentFrameIndex: number;
38
- onFrameChange: (index: number) => void;
39
- hotspots?: Viewer360Hotspot<TData>[];
40
- config?: Viewer360Config;
41
- hotspotMode?: boolean;
42
- onHotspotAdd?: (position: Viewer360HotspotPosition) => void;
43
- };
44
-
45
- type UseViewer360Return<TData> = {
46
- canvasRef: RefObject<HTMLCanvasElement | null>;
47
- containerRef: RefObject<HTMLDivElement | null>;
48
- currentFrame: Viewer360Frame | undefined;
49
- currentFrameHotspots: Viewer360Hotspot<TData>[];
50
- imagesLoaded: boolean;
51
- isHotspotMode: boolean;
52
- isResetDisabled: boolean;
53
- maxZoom: number;
54
- minZoom: number;
55
- viewerCursorClass: string;
56
- zoom: number;
57
- getCurrentImageLayout: () => ViewerImageLayout | null;
58
- getHotspotScreenPosition: (hotspot: Viewer360Hotspot<TData>) => { leftPercent: number; topPercent: number };
59
- handleCanvasClick: (event: React.MouseEvent<HTMLDivElement>) => void;
60
- handlePointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;
61
- handlePointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void;
62
- handlePointerUp: (event: ReactPointerEvent<HTMLDivElement>) => void;
63
- handleResetView: () => void;
64
- handleWheel: (event: ReactWheelEvent<HTMLDivElement>) => void;
65
- handleZoomIn: () => void;
66
- handleZoomOut: () => void;
67
- };
68
-
69
- export function useViewer360<TData = unknown>({
70
- frames,
71
- hotspots = [],
72
- currentFrameIndex,
73
- onFrameChange,
74
- config,
75
- hotspotMode: hotspotModeProp = false,
76
- onHotspotAdd,
77
- }: UseViewer360Params<TData>): UseViewer360Return<TData> {
78
- const resolvedConfig = useMemo(() => resolveViewer360Config(config), [config]);
79
- const { minZoom, maxZoom } = resolvedConfig;
80
-
81
- const canvasRef = useRef<HTMLCanvasElement>(null);
82
- const containerRef = useRef<HTMLDivElement>(null);
83
- const imagesRef = useRef<HTMLImageElement[]>([]);
84
- const dragStartRef = useRef<{ pointerX: number; frameIndex: number } | null>(null);
85
- const panStartRef = useRef<{ pointerX: number; pointerY: number; panX: number; panY: number } | null>(null);
86
-
87
- const framesSignature = getFramesSignature(frames);
88
- const [loadedSignature, setLoadedSignature] = useState<string | null>(null);
89
- const [zoom, setZoom] = useState<number>(minZoom);
90
- const [pan, setPan] = useState<Viewer360PanOffset>({ panX: 0, panY: 0 });
91
- const [isDragging, setIsDragging] = useState(false);
92
-
93
- const isHotspotMode = hotspotModeProp;
94
- const imagesLoaded = loadedSignature === framesSignature;
95
- const currentFrameHotspots = filterHotspotsByFrame(hotspots, currentFrameIndex) as Viewer360Hotspot<TData>[];
96
- const currentFrame = frames[currentFrameIndex];
97
- const viewerCursorClass = getViewerCursorClass(isHotspotMode, zoom, isDragging, minZoom);
98
- const resetDisabled = isResetDisabled(zoom, pan, resolvedConfig);
99
-
100
- useEffect(() => {
101
- let cancelled = false;
102
- imagesRef.current = [];
103
-
104
- async function loadFrames(): Promise<void> {
105
- const loadedImages = await preloadViewerFrames(frames);
106
-
107
- if (!cancelled && hasLoadedViewerFrame(loadedImages)) {
108
- imagesRef.current = loadedImages;
109
- setLoadedSignature(framesSignature);
110
- }
111
- }
112
-
113
- void loadFrames();
114
-
115
- return (): void => {
116
- cancelled = true;
117
- };
118
- }, [frames, framesSignature]);
119
-
120
- useEffect(() => {
121
- if (!imagesLoaded) return;
122
-
123
- function renderFrame(): void {
124
- const canvas = canvasRef.current;
125
- const container = containerRef.current;
126
- const img = imagesRef.current[currentFrameIndex];
127
-
128
- if (!canvas || !container) return;
129
-
130
- drawFrameOnCanvas({ canvas, container, image: img, zoom, pan });
131
- }
132
-
133
- renderFrame();
134
- window.addEventListener('resize', renderFrame);
135
-
136
- return (): void => window.removeEventListener('resize', renderFrame);
137
- }, [imagesLoaded, currentFrameIndex, zoom, pan]);
138
-
139
- useEffect(() => {
140
- if (!resolvedConfig.autoRotate || frames.length <= 1 || isDragging || isHotspotMode || zoom > minZoom) {
141
- return;
142
- }
143
-
144
- const direction = resolvedConfig.autoRotateDirection === 'backward' ? -1 : 1;
145
- const interval = window.setInterval(() => {
146
- onFrameChange((currentFrameIndex + direction + frames.length) % frames.length);
147
- }, resolvedConfig.autoRotateIntervalMs);
148
-
149
- return (): void => window.clearInterval(interval);
150
- }, [
151
- resolvedConfig.autoRotate,
152
- resolvedConfig.autoRotateDirection,
153
- resolvedConfig.autoRotateIntervalMs,
154
- frames.length,
155
- currentFrameIndex,
156
- isDragging,
157
- isHotspotMode,
158
- zoom,
159
- minZoom,
160
- onFrameChange,
161
- ]);
162
-
163
- function getCurrentImageLayout(): ViewerImageLayout | null {
164
- const container = containerRef.current;
165
- const image = imagesRef.current[currentFrameIndex];
166
-
167
- if (!container || !image || !image.complete || !image.naturalWidth) return null;
168
-
169
- const rect = container.getBoundingClientRect();
170
-
171
- return computeViewerImageLayout({
172
- containerWidth: rect.width,
173
- containerHeight: rect.height,
174
- imageWidth: image.naturalWidth,
175
- imageHeight: image.naturalHeight,
176
- pan,
177
- });
178
- }
179
-
180
- function getHotspotScreenPosition(hotspot: Viewer360Hotspot<TData>): { leftPercent: number; topPercent: number } {
181
- const layout = getCurrentImageLayout();
182
-
183
- if (!layout) {
184
- return { leftPercent: hotspot.positionX, topPercent: hotspot.positionY };
185
- }
186
-
187
- return computeHotspotScreenPosition(hotspot.positionX, hotspot.positionY, layout, zoom);
188
- }
189
-
190
- function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>): void {
191
- if (isHotspotMode) return;
192
-
193
- event.currentTarget.setPointerCapture(event.pointerId);
194
-
195
- if (zoom > minZoom) {
196
- panStartRef.current = { pointerX: event.clientX, pointerY: event.clientY, panX: pan.panX, panY: pan.panY };
197
- } else {
198
- dragStartRef.current = { pointerX: event.clientX, frameIndex: currentFrameIndex };
199
- }
200
-
201
- setIsDragging(true);
202
- }
203
-
204
- function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>): void {
205
- if (!isDragging) return;
206
-
207
- if (panStartRef.current && zoom > minZoom) {
208
- setPan(computeViewerPanOffset(panStartRef.current, event.clientX, event.clientY));
209
- return;
210
- }
211
-
212
- if (dragStartRef.current && zoom <= minZoom) {
213
- const nextFrameIndex = computeDragFrameIndex(
214
- dragStartRef.current,
215
- event.clientX,
216
- frames.length,
217
- resolvedConfig.dragSensitivity
218
- );
219
-
220
- if (nextFrameIndex !== null) {
221
- onFrameChange(nextFrameIndex);
222
- }
223
- }
224
- }
225
-
226
- function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>): void {
227
- if (event.currentTarget.hasPointerCapture(event.pointerId)) {
228
- event.currentTarget.releasePointerCapture(event.pointerId);
229
- }
230
-
231
- dragStartRef.current = null;
232
- panStartRef.current = null;
233
- setIsDragging(false);
234
- }
235
-
236
- function handleWheel(event: ReactWheelEvent<HTMLDivElement>): void {
237
- event.preventDefault();
238
- const { zoom: nextZoom, pan: nextPan } = applyWheelZoom(zoom, event.deltaY, pan, resolvedConfig);
239
- setZoom(nextZoom);
240
- setPan(nextPan);
241
- }
242
-
243
- function handleCanvasClick(event: React.MouseEvent<HTMLDivElement>): void {
244
- if (!isHotspotMode || isDragging || !onHotspotAdd) return;
245
-
246
- const frame = frames[currentFrameIndex];
247
- if (!frame) return;
248
-
249
- const layout = getCurrentImageLayout();
250
- if (!layout) return;
251
-
252
- const { positionX, positionY } = computeHotspotPositionFromClick(
253
- event.clientX,
254
- event.clientY,
255
- event.currentTarget.getBoundingClientRect(),
256
- layout,
257
- zoom
258
- );
259
-
260
- onHotspotAdd({
261
- frameIndex: currentFrameIndex,
262
- frameId: frame.id,
263
- positionX,
264
- positionY,
265
- });
266
- }
267
-
268
- function handleResetView(): void {
269
- setZoom(minZoom);
270
- setPan({ panX: 0, panY: 0 });
271
- }
272
-
273
- function handleZoomIn(): void {
274
- setZoom(stepZoomIn(zoom, resolvedConfig));
275
- }
276
-
277
- function handleZoomOut(): void {
278
- const { zoom: nextZoom, pan: nextPan } = stepZoomOut(zoom, pan, resolvedConfig);
279
- setZoom(nextZoom);
280
- setPan(nextPan);
281
- }
282
-
283
- return {
284
- canvasRef,
285
- containerRef,
286
- currentFrame,
287
- currentFrameHotspots,
288
- imagesLoaded,
289
- isHotspotMode,
290
- isResetDisabled: resetDisabled,
291
- maxZoom,
292
- minZoom,
293
- viewerCursorClass,
294
- zoom,
295
- getCurrentImageLayout,
296
- getHotspotScreenPosition,
297
- handleCanvasClick,
298
- handlePointerDown,
299
- handlePointerMove,
300
- handlePointerUp,
301
- handleResetView,
302
- handleWheel,
303
- handleZoomIn,
304
- handleZoomOut,
305
- };
306
- }
package/src/index.ts DELETED
@@ -1,68 +0,0 @@
1
- export { Viewer360 } from './feature/Viewer360';
2
- export { Viewer360AddModeBanner } from './feature/Viewer360AddModeBanner';
3
- export { Viewer360FrameIndicator } from './feature/Viewer360FrameIndicator';
4
- export { Viewer360LoadingOverlay } from './feature/Viewer360LoadingOverlay';
5
- export { Viewer360MarkerPin } from './feature/Viewer360MarkerPin';
6
- export { Viewer360Toolbar } from './feature/Viewer360Toolbar';
7
- export { useViewer360 } from './hooks/useViewer360';
8
-
9
- export { defaultViewer360Config } from './constants/viewer360Config';
10
- export { defaultViewer360Labels } from './constants/viewer360Labels';
11
- export { defaultViewer360MarkerPinLabels } from './constants/viewer360MarkerLabels';
12
- export {
13
- defaultViewer360ClassNames,
14
- defaultViewer360MarkerPinClassNames,
15
- viewer360ClassNames,
16
- viewer360MarkerPinClassNames,
17
- } from './constants/viewer360ClassNames';
18
-
19
- export {
20
- applyWheelZoom,
21
- clampZoom,
22
- getViewerCursorClass,
23
- isResetDisabled,
24
- resolveViewer360Config,
25
- stepZoomIn,
26
- stepZoomOut,
27
- } from './helpers/adjustViewerZoom';
28
- export { clampFrameIndex, computeDragFrameIndex } from './helpers/computeDragFrameIndex';
29
- export {
30
- computeHotspotPositionFromClick,
31
- computeHotspotScreenPosition,
32
- computeViewerImageLayout,
33
- type ViewerImageLayout,
34
- } from './helpers/computeViewerImageLayout';
35
- export { computeViewerPanOffset } from './helpers/computeViewerPanOffset';
36
- export { hotspotToViewer360Marker, toViewer360Hotspots } from './helpers/markerHelpers';
37
- export {
38
- drawFrameOnCanvas,
39
- filterHotspotsByFrame,
40
- getFramesSignature,
41
- hasLoadedViewerFrame,
42
- preloadFrameImage,
43
- preloadViewerFrames,
44
- } from './helpers/viewerHelpers';
45
-
46
- export type {
47
- Viewer360ClassNames,
48
- Viewer360Config,
49
- Viewer360Frame,
50
- Viewer360Hotspot,
51
- Viewer360HotspotPinOptions,
52
- Viewer360HotspotPosition,
53
- Viewer360HotspotRenderProps,
54
- Viewer360Labels,
55
- Viewer360Marker,
56
- Viewer360MarkerPinClassNames,
57
- Viewer360MarkerPinLabels,
58
- Viewer360MarkerPinProps,
59
- Viewer360MarkerPinRenderProps,
60
- Viewer360OverlayRenderProps,
61
- Viewer360PanOffset,
62
- Viewer360Props,
63
- Viewer360Theme,
64
- Viewer360ToolbarRenderProps,
65
- } from './types';
66
-
67
- export { cn } from './components/utils';
68
- export { Button, buttonVariants } from './components/ui/Button';
package/src/styles.css DELETED
@@ -1,80 +0,0 @@
1
- @import 'tailwindcss/theme' layer(theme);
2
- @import 'tailwindcss/utilities' layer(utilities);
3
-
4
- @source './**/*.{ts,tsx}';
5
-
6
- @custom-variant dark (&:is(.dark *));
7
-
8
- @theme inline {
9
- --color-background: var(--background);
10
- --color-foreground: var(--foreground);
11
- --color-card: var(--card);
12
- --color-card-foreground: var(--card-foreground);
13
- --color-popover: var(--popover);
14
- --color-popover-foreground: var(--popover-foreground);
15
- --color-primary: var(--primary);
16
- --color-primary-foreground: var(--primary-foreground);
17
- --color-secondary: var(--secondary);
18
- --color-secondary-foreground: var(--secondary-foreground);
19
- --color-muted: var(--muted);
20
- --color-muted-foreground: var(--muted-foreground);
21
- --color-accent: var(--accent);
22
- --color-accent-foreground: var(--accent-foreground);
23
- --color-destructive: var(--destructive);
24
- --color-border: var(--border);
25
- --color-input: var(--input);
26
- --color-ring: var(--ring);
27
- --radius-sm: calc(var(--radius) - 4px);
28
- --radius-md: calc(var(--radius) - 2px);
29
- --radius-lg: var(--radius);
30
- --radius-xl: calc(var(--radius) + 4px);
31
- --radius-4xl: 2rem;
32
- }
33
-
34
- /*
35
- * Scoped to the viewer only — never set :root (that would override the host app's entire theme).
36
- * Host app shadcn variables inherit into the viewer. Fallbacks apply only inside [data-viewer-360].
37
- */
38
- [data-viewer-360] {
39
- --radius: 0.625rem;
40
- --radius-4xl: 2rem;
41
- --background: oklch(1 0 0);
42
- --foreground: oklch(0.145 0 0);
43
- --card: oklch(1 0 0);
44
- --card-foreground: oklch(0.145 0 0);
45
- --popover: oklch(1 0 0);
46
- --popover-foreground: oklch(0.145 0 0);
47
- --primary: oklch(0.205 0 0);
48
- --primary-foreground: oklch(0.985 0 0);
49
- --secondary: oklch(0.97 0 0);
50
- --secondary-foreground: oklch(0.205 0 0);
51
- --muted: oklch(0.97 0 0);
52
- --muted-foreground: oklch(0.556 0 0);
53
- --accent: oklch(0.97 0 0);
54
- --accent-foreground: oklch(0.205 0 0);
55
- --destructive: oklch(0.577 0.245 27.325);
56
- --border: oklch(0.922 0 0);
57
- --input: oklch(0.922 0 0);
58
- --ring: oklch(0.708 0 0);
59
- }
60
-
61
- .dark [data-viewer-360] {
62
- --background: oklch(0.145 0 0);
63
- --foreground: oklch(0.985 0 0);
64
- --card: oklch(0.205 0 0);
65
- --card-foreground: oklch(0.985 0 0);
66
- --popover: oklch(0.205 0 0);
67
- --popover-foreground: oklch(0.985 0 0);
68
- --primary: oklch(0.922 0 0);
69
- --primary-foreground: oklch(0.205 0 0);
70
- --secondary: oklch(0.269 0 0);
71
- --secondary-foreground: oklch(0.985 0 0);
72
- --muted: oklch(0.269 0 0);
73
- --muted-foreground: oklch(0.708 0 0);
74
- --accent: oklch(0.269 0 0);
75
- --accent-foreground: oklch(0.985 0 0);
76
- --destructive: oklch(0.704 0.191 22.216);
77
- --border: oklch(1 0 0 / 10%);
78
- --input: oklch(1 0 0 / 15%);
79
- --ring: oklch(0.556 0 0);
80
- }
@@ -1,67 +0,0 @@
1
- export type Viewer360Frame = {
2
- id: string;
3
- src: string;
4
- label?: string;
5
- };
6
-
7
- export type Viewer360PanOffset = {
8
- panX: number;
9
- panY: number;
10
- };
11
-
12
- export type Viewer360Config = {
13
- minZoom?: number;
14
- maxZoom?: number;
15
- zoomStep?: number;
16
- dragSensitivity?: number;
17
- autoRotate?: boolean;
18
- autoRotateIntervalMs?: number;
19
- autoRotateDirection?: 'forward' | 'backward';
20
- };
21
-
22
- export type Viewer360Hotspot<TData = unknown> = {
23
- id: string;
24
- frameIndex: number;
25
- positionX: number;
26
- positionY: number;
27
- data?: TData;
28
- };
29
-
30
- export type Viewer360HotspotPosition = {
31
- frameIndex: number;
32
- frameId: string;
33
- positionX: number;
34
- positionY: number;
35
- };
36
-
37
- export type Viewer360HotspotRenderProps<TData = unknown> = {
38
- hotspot: Viewer360Hotspot<TData>;
39
- leftPercent: number;
40
- topPercent: number;
41
- };
42
-
43
- export type Viewer360OverlayRenderProps = {
44
- currentFrameIndex: number;
45
- frameCount: number;
46
- frameLabel?: string;
47
- isHotspotMode: boolean;
48
- labels: Required<import('./Viewer360Props').Viewer360Labels>;
49
- frameIndicatorClassName: string;
50
- };
51
-
52
- export type Viewer360ToolbarRenderProps = {
53
- zoom: number;
54
- minZoom: number;
55
- maxZoom: number;
56
- isResetDisabled: boolean;
57
- isHotspotMode: boolean;
58
- showHotspotModeControl: boolean;
59
- showZoomControls: boolean;
60
- showResetControl: boolean;
61
- showDragHint: boolean;
62
- labels: Required<import('./Viewer360Props').Viewer360Labels>;
63
- onZoomIn: () => void;
64
- onZoomOut: () => void;
65
- onResetView: () => void;
66
- onHotspotModeChange: (active: boolean) => void;
67
- };
@@ -1,52 +0,0 @@
1
- import type { MouseEvent, ReactNode } from 'react';
2
-
3
- import type { Viewer360Hotspot } from './Viewer360Hotspot';
4
-
5
- export type Viewer360Marker = {
6
- id: string;
7
- title: string;
8
- description?: string;
9
- };
10
-
11
- export type Viewer360MarkerPinClassNames = {
12
- root?: string;
13
- ping?: string;
14
- dot?: string;
15
- tooltip?: string;
16
- tooltipHeader?: string;
17
- tooltipBody?: string;
18
- tooltipTitle?: string;
19
- tooltipDescription?: string;
20
- deleteButton?: string;
21
- };
22
-
23
- export type Viewer360MarkerPinLabels = {
24
- delete?: string;
25
- };
26
-
27
- export type Viewer360MarkerPinRenderProps<TData = unknown> = {
28
- marker: Viewer360Marker;
29
- hotspot?: Viewer360Hotspot<TData>;
30
- };
31
-
32
- export type Viewer360MarkerPinProps<TData = unknown> = {
33
- marker: Viewer360Marker;
34
- hotspot?: Viewer360Hotspot<TData>;
35
- leftPercent: number;
36
- topPercent: number;
37
- onDelete?: (id: string) => void;
38
- isDeletePending?: boolean;
39
- onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
40
- renderTag?: (props: Viewer360MarkerPinRenderProps<TData>) => ReactNode;
41
- classNames?: Viewer360MarkerPinClassNames;
42
- labels?: Viewer360MarkerPinLabels;
43
- };
44
-
45
- export type Viewer360HotspotPinOptions<TData = unknown> = {
46
- onDelete?: (id: string) => void;
47
- deletingMarkerId?: string | null;
48
- getMarker?: (hotspot: Viewer360Hotspot<TData>) => Viewer360Marker;
49
- renderTag?: (props: Viewer360MarkerPinRenderProps<TData>) => ReactNode;
50
- classNames?: Viewer360MarkerPinClassNames;
51
- labels?: Viewer360MarkerPinLabels;
52
- };