js-cloudimage-360-view 4.0.0 → 4.1.1

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/package.json CHANGED
@@ -1,15 +1,29 @@
1
1
  {
2
2
  "name": "js-cloudimage-360-view",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "main": "dist/js-cloudimage-360-view.min.js",
5
+ "types": "src/types/ci360.d.ts",
6
+ "files": [
7
+ "dist/js-cloudimage-360-view.min.js",
8
+ "dist/react",
9
+ "src/types",
10
+ "src/react/types.d.ts"
11
+ ],
5
12
  "exports": {
6
13
  ".": {
14
+ "types": "./src/types/ci360.d.ts",
7
15
  "import": "./dist/js-cloudimage-360-view.min.js",
8
16
  "require": "./dist/js-cloudimage-360-view.min.js"
17
+ },
18
+ "./css": "./dist/react/style.css",
19
+ "./react": {
20
+ "types": "./dist/react/index.d.ts",
21
+ "import": "./dist/react/index.js",
22
+ "require": "./dist/react/index.cjs"
9
23
  }
10
24
  },
11
- "style": "dist/js-cloudimage-360-view.min.css",
12
- "module": "dist/js-cloudimage-360-view.es.js",
25
+ "style": "dist/react/style.css",
26
+ "module": "dist/js-cloudimage-360-view.min.js",
13
27
  "description": "",
14
28
  "author": "scaleflex",
15
29
  "license": "MIT",
@@ -30,40 +44,64 @@
30
44
  "360 product view"
31
45
  ],
32
46
  "scripts": {
33
- "dev": "vite serve demo",
47
+ "dev": "vite serve demo --host",
48
+ "dev:react": "npm --prefix demo/react-demo run dev",
34
49
  "clean:build": "rm -rf dist",
35
50
  "build:bundle": "npm run clean:build && vite build",
51
+ "build:react": "vite build --config vite-react.config.js && cp src/react/types.d.ts dist/react/index.d.ts",
52
+ "build": "npm run build:bundle && npm run build:react",
36
53
  "deploy:bundle": "npm run build:bundle && node bin/deploy-bundle",
37
54
  "clean:dist": "rm -rf dist",
38
55
  "clean:demo": "rm -rf demo/dist",
39
56
  "build:npm": "npm run clean:demo && vite --config vite-npm.config.js build",
40
- "build:demo": "npm run clean:demo && vite --config vite-demo.config.js build",
57
+ "build:demo": "vite --config vite-demo.config.js build && npm --prefix demo/react-demo run build",
41
58
  "deploy:demo": "gh-pages -d dist",
42
- "publish": "npm run build:demo && npm run deploy:demo"
59
+ "publish": "npm run build:demo && npm run deploy:demo",
60
+ "test": "vitest",
61
+ "test:run": "vitest run",
62
+ "test:coverage": "vitest run --coverage"
43
63
  },
44
64
  "dependencies": {
45
65
  "@popperjs/core": "^2.11.2",
46
- "lodash.debounce": "^4.0.8",
47
66
  "lodash.throttle": "^4.1.1"
48
67
  },
68
+ "peerDependencies": {
69
+ "react": ">=17.0.0",
70
+ "react-dom": ">=17.0.0"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "react": {
74
+ "optional": true
75
+ },
76
+ "react-dom": {
77
+ "optional": true
78
+ }
79
+ },
49
80
  "devDependencies": {
50
81
  "@babel/cli": "^7.16.7",
82
+ "@types/react": "^18.2.0",
83
+ "@types/react-dom": "^18.2.0",
84
+ "@vitejs/plugin-react": "^4.2.0",
85
+ "react": "^18.2.0",
86
+ "react-dom": "^18.2.0",
87
+ "typescript": "^5.3.0",
51
88
  "@babel/core": "^7.16.7",
52
89
  "@babel/plugin-transform-runtime": "^7.16.5",
53
90
  "@babel/preset-env": "^7.16.5",
54
91
  "@eslint/js": "^9.12.0",
92
+ "@vitest/coverage-v8": "^4.0.17",
93
+ "autoprefixer": "^10.4.23",
55
94
  "babel-loader": "^8.2.3",
56
95
  "babel-plugin-array-includes": "^2.0.3",
57
- "babel-preset-env": "^1.7.0",
58
- "babel-preset-es2015": "^6.24.1",
59
96
  "babel-preset-minify": "^0.5.0",
60
- "babel-preset-stage-0": "^6.24.1",
61
97
  "css-loader": "^2.1.1",
62
98
  "dotenv": "^16.0.3",
63
99
  "eslint": "^9.12.0",
64
100
  "form-data": "^4.0.0",
65
101
  "gh-pages": "^2.0.1",
66
102
  "highlight.js": "^10.4.1",
103
+ "isomorphic-fetch": "^3.0.0",
104
+ "jsdom": "^27.4.0",
67
105
  "mini-css-extract-plugin": "^0.9.0",
68
106
  "mobile-detect": "^1.4.3",
69
107
  "prettier": "3.3.3",
@@ -72,6 +110,7 @@
72
110
  "vite-plugin-dts": "^4.3.0",
73
111
  "vite-plugin-html": "^3.2.2",
74
112
  "vite-plugin-lib-inject-css": "^2.1.1",
113
+ "vitest": "^4.0.17",
75
114
  "webpack": "^5.95.0",
76
115
  "webpack-cli": "^5.0.1",
77
116
  "webpack-dev-server": "^4.13.3"
@@ -0,0 +1,228 @@
1
+ import { CSSProperties, RefObject, ForwardRefExoticComponent, RefAttributes } from 'react';
2
+
3
+ /**
4
+ * Autoplay behavior options
5
+ */
6
+ export type AutoplayBehavior = 'spin-x' | 'spin-y' | 'spin-xy' | 'spin-yx';
7
+
8
+ /**
9
+ * Theme options for the viewer
10
+ */
11
+ export type Theme = 'light' | 'dark';
12
+
13
+ /**
14
+ * Hotspot orientation
15
+ */
16
+ export type HotspotOrientation = 'x' | 'y';
17
+
18
+ /**
19
+ * Hotspot position
20
+ */
21
+ export interface HotspotPosition {
22
+ x: number;
23
+ y: number;
24
+ }
25
+
26
+ /**
27
+ * Hotspot configuration
28
+ */
29
+ export interface Hotspot {
30
+ id: string;
31
+ label?: string;
32
+ orientation?: HotspotOrientation;
33
+ containerSize?: [number, number];
34
+ positions: Record<number, HotspotPosition>;
35
+ content?: string;
36
+ className?: string;
37
+ }
38
+
39
+ /**
40
+ * Hint configuration
41
+ */
42
+ export interface Hint {
43
+ text: string;
44
+ icon?: 'drag' | 'scroll' | 'pinch' | 'keys';
45
+ }
46
+
47
+ /**
48
+ * Spin event data
49
+ */
50
+ export interface SpinEventData {
51
+ viewerId: string;
52
+ direction: 'left' | 'right' | 'up' | 'down';
53
+ activeImageX: number;
54
+ activeImageY: number;
55
+ amountX: number;
56
+ amountY: number;
57
+ }
58
+
59
+ /**
60
+ * Load event data
61
+ */
62
+ export interface LoadEventData {
63
+ viewerId: string;
64
+ imagesX: number;
65
+ imagesY: number;
66
+ }
67
+
68
+ /**
69
+ * Zoom event data
70
+ */
71
+ export interface ZoomEventData {
72
+ viewerId: string;
73
+ zoomLevel: number;
74
+ }
75
+
76
+ /**
77
+ * Error event data
78
+ */
79
+ export interface ErrorEventData {
80
+ viewerId: string;
81
+ error: { message: string; url?: string };
82
+ errorCount: number;
83
+ totalImages: number;
84
+ errors: Array<{ message: string; url?: string }>;
85
+ }
86
+
87
+ /**
88
+ * Base event data (common to all events)
89
+ */
90
+ export interface BaseEventData {
91
+ viewerId: string;
92
+ }
93
+
94
+ /**
95
+ * CI360 Configuration options
96
+ */
97
+ export interface CI360Config {
98
+ folder?: string;
99
+ apiVersion?: string;
100
+ filenameX?: string;
101
+ filenameY?: string | null;
102
+ imageListX?: string | string[] | null;
103
+ imageListY?: string | string[] | null;
104
+ indexZeroBase?: number;
105
+ amountX?: number;
106
+ amountY?: number;
107
+ draggable?: boolean;
108
+ swipeable?: boolean;
109
+ keys?: boolean;
110
+ keysReverse?: boolean;
111
+ autoplay?: boolean;
112
+ autoplayBehavior?: AutoplayBehavior;
113
+ playOnce?: boolean;
114
+ speed?: number;
115
+ autoplayReverse?: boolean;
116
+ dragSpeed?: number;
117
+ dragReverse?: boolean;
118
+ stopAtEdges?: boolean;
119
+ inertia?: boolean;
120
+ fullscreen?: boolean;
121
+ magnifier?: number | null;
122
+ pointerZoom?: number;
123
+ pinchZoom?: boolean;
124
+ bottomCircle?: boolean;
125
+ bottomCircleOffset?: number;
126
+ initialIconShown?: boolean;
127
+ hide360Logo?: boolean;
128
+ logoSrc?: string;
129
+ imageInfo?: boolean;
130
+ hints?: boolean | Hint[];
131
+ theme?: Theme;
132
+ ciToken?: string | null;
133
+ ciFilters?: string | null;
134
+ ciTransformation?: string | null;
135
+ lazyload?: boolean;
136
+ hotspots?: Hotspot[] | null;
137
+ hotspotTimelineOnClick?: boolean;
138
+ onReady?: (data: BaseEventData) => void;
139
+ onLoad?: (data: LoadEventData) => void;
140
+ onSpin?: (data: SpinEventData) => void;
141
+ onAutoplayStart?: (data: BaseEventData) => void;
142
+ onAutoplayStop?: (data: BaseEventData) => void;
143
+ onFullscreenOpen?: (data: BaseEventData) => void;
144
+ onFullscreenClose?: (data: BaseEventData) => void;
145
+ onZoomIn?: (data: ZoomEventData) => void;
146
+ onZoomOut?: (data: BaseEventData) => void;
147
+ onDragStart?: (data: BaseEventData) => void;
148
+ onDragEnd?: (data: BaseEventData) => void;
149
+ onError?: (data: ErrorEventData) => void;
150
+ }
151
+
152
+ /**
153
+ * CI360 Viewer Instance methods available from the native viewer
154
+ */
155
+ export interface CI360ViewerInstance {
156
+ moveLeft: (stopAtEdges?: boolean, steps?: number) => void;
157
+ moveRight: (stopAtEdges?: boolean, steps?: number) => void;
158
+ moveTop: (stopAtEdges?: boolean, steps?: number) => void;
159
+ moveBottom: (stopAtEdges?: boolean, steps?: number) => void;
160
+ play: () => void;
161
+ stopAutoplay: () => void;
162
+ toggleZoom: (event?: MouseEvent) => void;
163
+ removeZoom: () => void;
164
+ animateToFrame: (frame: number, hotspotId?: string) => void;
165
+ destroy: () => void;
166
+ update: (config: Partial<CI360Config>) => void;
167
+ isReady: boolean;
168
+ activeImageX: number;
169
+ activeImageY: number;
170
+ amountX: number;
171
+ amountY: number;
172
+ isZoomed: boolean;
173
+ viewerConfig: CI360Config;
174
+ }
175
+
176
+ /**
177
+ * Props for the CI360Viewer React component
178
+ */
179
+ export interface CI360ViewerProps extends CI360Config {
180
+ id?: string;
181
+ className?: string;
182
+ style?: CSSProperties;
183
+ }
184
+
185
+ /**
186
+ * Ref methods exposed by CI360Viewer component
187
+ */
188
+ export interface CI360ViewerRef {
189
+ moveLeft: (steps?: number) => void;
190
+ moveRight: (steps?: number) => void;
191
+ moveTop: (steps?: number) => void;
192
+ moveBottom: (steps?: number) => void;
193
+ play: () => void;
194
+ stop: () => void;
195
+ zoomIn: () => void;
196
+ zoomOut: () => void;
197
+ goToFrame: (frame: number, hotspotId?: string) => void;
198
+ getViewer: () => CI360ViewerInstance | null;
199
+ }
200
+
201
+ /**
202
+ * Return type for useCI360 hook
203
+ */
204
+ export interface UseCI360Return {
205
+ viewer: CI360ViewerInstance | null;
206
+ isReady: boolean;
207
+ }
208
+
209
+ /**
210
+ * Options for useCI360 hook
211
+ */
212
+ export interface UseCI360Options extends CI360Config {
213
+ autoInit?: boolean;
214
+ }
215
+
216
+ /**
217
+ * CI360Viewer React Component
218
+ */
219
+ export declare const CI360Viewer: ForwardRefExoticComponent<CI360ViewerProps & RefAttributes<CI360ViewerRef>>;
220
+ export default CI360Viewer;
221
+
222
+ /**
223
+ * useCI360 Hook for advanced control
224
+ */
225
+ export declare function useCI360(
226
+ containerRef: RefObject<HTMLDivElement | null>,
227
+ config: UseCI360Options
228
+ ): UseCI360Return;
@@ -0,0 +1,66 @@
1
+ declare module CI360 {
2
+ export interface CI360ViewerConfig {
3
+ folder?: string; // Default: '/'
4
+ apiVersion?: string; // Default: 'v7'
5
+ filenameX?: string; // Default: 'image-{index}.jpg'
6
+ filenameY?: string | null; // Default: null
7
+ imageListX?: string | null; // Default: null
8
+ imageListY?: string | null; // Default: null
9
+ indexZeroBase?: number; // Default: 0
10
+ amountX?: number; // Default: 0
11
+ amountY?: number; // Default: 0
12
+ draggable?: boolean; // Default: true
13
+ swipeable?: boolean; // Default: true
14
+ keys?: boolean; // Default: false
15
+ keysReverse?: boolean; // Default: false
16
+ bottomCircleOffset?: number; // Default: 5
17
+ autoplay?: boolean; // Default: false
18
+ autoplayBehavior?: string; // Default: AUTOPLAY_BEHAVIOR.SPIN_X
19
+ playOnce?: boolean; // Default: false
20
+ speed?: number; // Default: 80
21
+ autoplayReverse?: boolean; // Default: false
22
+ fullscreen?: boolean; // Default: false
23
+ magnifier?: number | null; // Default: null
24
+ ciToken?: string | null; // Default: null
25
+ ciFilters?: string | null; // Default: null
26
+ ciTransformation?: string | null; // Default: null
27
+ lazyload?: boolean; // Default: true
28
+ dragSpeed?: number; // Default: 150
29
+ stopAtEdges?: boolean; // Default: false
30
+ pointerZoom?: number; // Default: 0
31
+ imageInfo?: boolean; // Changed from string to boolean; Default: false
32
+ initialIconShown?: boolean; // Default: true
33
+ bottomCircle?: boolean; // Default: true
34
+ hotspots?: any; // Default: null (type adjusted as needed)
35
+ dragReverse?: boolean; // Default: false
36
+ hide360Logo?: boolean; // Default: false (not documented)
37
+ logoSrc?: string; // Default: Scaleflex 360 logo URL
38
+ }
39
+
40
+ // Define the CI360Viewer class with the config type and constructor
41
+ export default class CI360Viewer {
42
+ constructor(container: HTMLElement | string, config?: CI360ViewerConfig, fullscreen?: boolean);
43
+ destroy(): void;
44
+ update(config: CI360ViewerConfig): void;
45
+ viewerConfig: CI360ViewerConfig;
46
+ }
47
+
48
+ // Define the CI360 class
49
+ export class CI360 {
50
+ views: Map<string, CI360Viewer>;
51
+ instances: CI360Viewer[];
52
+ initAll: (className?: string) => void;
53
+ getInstances: () => CI360Viewer[];
54
+ init: (
55
+ container: HTMLElement | string,
56
+ config?: CI360ViewerConfig,
57
+ fullscreen?: boolean
58
+ ) => CI360Viewer | undefined;
59
+ getViewById: (id: string) => CI360Viewer | undefined;
60
+ getViews: () => CI360Viewer[];
61
+ updateView: (id: string, config: CI360ViewerConfig) => CI360Viewer | undefined;
62
+ destroy: (id: string) => void;
63
+ destroyAll: () => void;
64
+ constructor();
65
+ }
66
+ }
package/.prettierrc DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "semi": true,
3
- "singleQuote": true,
4
- "trailingComma": "es5",
5
- "tabWidth": 2,
6
- "useTabs": false,
7
- "printWidth": 110,
8
- "arrowParens": "always"
9
- }
@@ -1 +0,0 @@
1
- @keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.cloudimage-360{width:100%;position:relative}.cloudimage-360-inner-box{width:100%;height:100%;position:relative}.cloudimage-360-icons-container{position:absolute;display:flex;top:15px;right:10px;height:100%;flex-direction:column;align-items:center;z-index:100;gap:8px}.cloudimage-360-transition-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff;opacity:0;transition:all 1s ease-out;z-index:10}.cloudimage-360-button{width:30px;height:30px;cursor:pointer;transition:transform .15s ease-out,background-color .15s ease-out;display:flex;align-items:center;justify-content:center;border-radius:50%;background-color:#f0f0f0;color:#4a4a4a;box-shadow:0 2px 4px #0000001a;padding:6px}.cloudimage-360-button:hover{transform:scale(1.05);background-color:#e7e6e6}.cloudimage-360-button svg{width:18px;height:18px;fill:#4a4a4a;transition:fill .15s ease-out}.cloudimage-360-button:hover svg{fill:#2c2c2c}.cloudimage-initial-icon{position:absolute;top:0;bottom:0;left:0;right:0;width:100px;height:100px;margin:auto;background:linear-gradient(135deg,#ffffff80,#c8c8c880);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:50%;border:1px solid rgba(255,255,255,.5);box-shadow:0 8px 12px #0003,0 4px 6px #0000001a;transition:.2s all,transform .2s;color:#4b4b4b;text-align:center;z-index:2;line-height:100px;-webkit-user-select:none;user-select:none}.cloudimage-initial-icon:hover{background-color:#c8c8c833}.cloudimage-loading-spinner{width:30px;height:30px;transform:translate(-50%,-50%);border:3px solid #fff;position:absolute;top:15px;left:15px;border-bottom-color:#a3a3a3;border-radius:50%;display:inline-block;box-sizing:border-box;opacity:0;animation:rotation .7s linear infinite}.cloudimage-360-view-360-circle{position:absolute;left:0;bottom:0;width:100%;height:auto;margin:auto;pointer-events:none;-webkit-user-select:none;user-select:none;transition:.2s all;z-index:2}.cloudimage-360-fullscreen-modal{position:fixed;top:0;bottom:0;left:0;right:0;width:100%;height:100%;z-index:999;background-color:#fff}.cloudimage-360-img-magnifier-glass{background-color:#fff;background-image:radial-gradient(circle at center,#fffc,#f0f0f0e6);background-repeat:no-repeat;position:absolute;border:2px solid rgba(0,0,0,.3);border-radius:50%;line-height:200px;text-align:center;z-index:1000;width:250px;height:250px;top:-75px;right:-85px;box-shadow:0 8px 16px #0006,0 4px 8px #0003;transition:box-shadow .2s ease;overflow:hidden;pointer-events:none}.cloudimage-360-hotspot-container{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:20}.cloudimage-360-popper{opacity:1;transition:opacity .2s ease-in-out}.cloudimage-360-hotspot{display:inline-block;position:absolute;top:0;right:0;bottom:0;left:0;transform:translate(-50%,-50%);background:#0af;border:1px solid #fff;border-radius:50%;height:18px;width:18px;box-shadow:0 0 #0af9,0 2px 6px #0003;opacity:0;animation:pulse 2s infinite;transition:transform .2s ease,box-shadow .2s ease}.cloudimage-360-hotspot.visible{opacity:1}@keyframes pulse{0%{transform:scale(1);box-shadow:0 0 #0af9,0 0 0 10px #0af6,0 0 0 20px #0af3}50%{transform:scale(1.1);box-shadow:0 0 0 10px #0af0,0 0 0 20px #00aaff1a,0 0 0 30px #0af0}to{transform:scale(1);box-shadow:0 0 #0af0,0 0 0 10px #0af0,0 0 0 20px #0af0}}.cloudimage-360-hotspot:hover{transform:scale(1.2);box-shadow:0 0 0 5px #00aaff80,0 4px 12px #0000004d}.cloudimage-360-popper{background-color:#ffffffe6;color:#333;padding:10px 15px;border-radius:6px;box-shadow:0 4px 16px #0003;font-size:14px;max-width:220px;z-index:9999;text-align:center;transition:opacity .2s ease,translate .2s ease;opacity:0;translate:0 -10px}.cloudimage-360-popper[data-show]{opacity:1;translate:0}