@zoompinch/react 0.0.4

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/README.md ADDED
@@ -0,0 +1,578 @@
1
+ # @zoompinch/react
2
+
3
+ React bindings for [@zoompinch/core](https://github.com/ElyaConrad/zoompinch) - Apply a pinch-and-zoom experience that feels native and communicates the transform reactively and lets you project any layer on top of the transformed canvas.
4
+
5
+ **Play with the demo:** [https://zoompinch.pages.dev](https://zoompinch.pages.dev)
6
+
7
+ ![Mobile demo](https://zoompinch.pages.dev/zoompinch_demo.gif)
8
+
9
+ ### Mathematical correct pinch on touch
10
+
11
+ Unlike other libraries, _Zoompinch_ does not just use the center point between two fingers as projection center. The fingers get correctly projected on the virtual canvas. This makes pinching on touch devices feel native-like.
12
+
13
+ ### Touch, Wheel, Mouse and Trackpad Gestures!
14
+
15
+ Aside from touch, mouse and wheel events, **gesture events** (Safari Desktop) are supported as well! Try it out on the [demo](https://zoompinch.pages.dev)
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @zoompinch/react
21
+ ```
22
+
23
+ ## Complete Example
24
+
25
+ ```tsx
26
+ import React, { useRef, useState } from 'react';
27
+ import { Zoompinch, ZoompinchRef } from '@zoompinch/react';
28
+
29
+ function App() {
30
+ const zoompinchRef = useRef<ZoompinchRef>(null);
31
+ const [transform, setTransform] = useState({
32
+ translateX: 0,
33
+ translateY: 0,
34
+ scale: 1,
35
+ rotate: 0
36
+ });
37
+
38
+ function handleInit() {
39
+ // Center canvas on initialization
40
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5], 0);
41
+ }
42
+
43
+ function handleTransformChange(newTransform) {
44
+ console.log('Transform updated:', newTransform);
45
+ setTransform(newTransform);
46
+ }
47
+
48
+ function handleClick(event: React.MouseEvent) {
49
+ if (!zoompinchRef.current) return;
50
+ const [x, y] = zoompinchRef.current.normalizeClientCoords(event.clientX, event.clientY);
51
+ console.log('Clicked at canvas position:', x, y);
52
+ }
53
+
54
+ return (
55
+ <Zoompinch
56
+ ref={zoompinchRef}
57
+ style={{ width: '800px', height: '600px', border: '1px solid #ccc' }}
58
+ transform={transform}
59
+ onTransformChange={handleTransformChange}
60
+ offset={{ top: 0, right: 0, bottom: 0, left: 0 }}
61
+ minScale={0.5}
62
+ maxScale={4}
63
+ clampBounds={false}
64
+ rotation={true}
65
+ mouse={true}
66
+ wheel={true}
67
+ touch={true}
68
+ gesture={true}
69
+ onInit={handleInit}
70
+ onClick={handleClick}
71
+ >
72
+ <img
73
+ width="1536"
74
+ height="2048"
75
+ src="https://imagedelivery.net/mudX-CmAqIANL8bxoNCToA/489df5b2-38ce-46e7-32e0-d50170e8d800/public"
76
+ draggable={false}
77
+ style={{ userSelect: 'none' }}
78
+ />
79
+ </Zoompinch>
80
+ );
81
+ }
82
+
83
+ export default App;
84
+ ```
85
+
86
+ ### With Matrix Overlay
87
+
88
+ ```tsx
89
+ <Zoompinch
90
+ ref={zoompinchRef}
91
+ style={{ width: '800px', height: '600px' }}
92
+ onInit={handleInit}
93
+ matrix={({ composePoint, normalizeClientCoords, canvasWidth, canvasHeight }) => (
94
+ <svg width="100%" height="100%">
95
+ {/* Center marker */}
96
+ <circle
97
+ cx={composePoint(canvasWidth / 2, canvasHeight / 2)[0]}
98
+ cy={composePoint(canvasWidth / 2, canvasHeight / 2)[1]}
99
+ r="8"
100
+ fill="red"
101
+ />
102
+ </svg>
103
+ )}
104
+ >
105
+ <img width="1536" height="2048" src="image.jpg" />
106
+ </Zoompinch>
107
+ ```
108
+
109
+ ---
110
+
111
+ ## API Reference
112
+
113
+ ### Props
114
+
115
+ | Prop | Type | Default | Description |
116
+ |------|------|---------|-------------|
117
+ | `transform` | `Transform` | `{ translateX: 0, translateY: 0, scale: 1, rotate: 0 }` | Current transform state |
118
+ | `onTransformChange` | `(transform: Transform) => void` | - | Callback when transform changes |
119
+ | `offset` | `Offset` | `{ top: 0, right: 0, bottom: 0, left: 0 }` | Inner padding/offset within container |
120
+ | `minScale` | `number` | `0.5` | Minimum scale (user gestures only) |
121
+ | `maxScale` | `number` | `10` | Maximum scale (user gestures only) |
122
+ | `clampBounds` | `boolean` | `false` | Clamp panning within bounds (user gestures only) |
123
+ | `rotation` | `boolean` | `true` | Enable rotation gestures |
124
+ | `mouse` | `boolean` | `true` | Enable mouse drag |
125
+ | `wheel` | `boolean` | `true` | Enable wheel/trackpad |
126
+ | `touch` | `boolean` | `true` | Enable touch gestures |
127
+ | `gesture` | `boolean` | `true` | Enable Safari gesture events |
128
+ | `style` | `React.CSSProperties` | - | Inline styles for container |
129
+ | `children` | `ReactNode` | - | Canvas content |
130
+ | `matrix` | `ReactNode \| Function` | - | Overlay content (see Matrix Prop) |
131
+
132
+ **Note:** `minScale`, `maxScale`, `rotation`, and `clampBounds` only apply during user interaction. Programmatic changes via ref methods are unrestricted.
133
+
134
+ ### Events
135
+
136
+ | Event | Payload | Description |
137
+ |-------|---------|-------------|
138
+ | `onInit` | `void` | Fired when canvas dimensions are available |
139
+ | `onTransformChange` | `Transform` | Fired when transform changes |
140
+ | `onClick` | `React.MouseEvent` | Standard click event |
141
+ | `onMouseDown` | `React.MouseEvent` | Standard mousedown event |
142
+ | `onTouchStart` | `React.TouchEvent` | Standard touchstart event |
143
+ | `onMouseUp` | `React.MouseEvent` | Standard mouseup event |
144
+ | `onTouchEnd` | `React.TouchEvent` | Standard touchend event |
145
+
146
+ ```tsx
147
+ <Zoompinch
148
+ onInit={handleInit}
149
+ onTransformChange={handleTransformChange}
150
+ onClick={handleClick}
151
+ >
152
+ {/* content */}
153
+ </Zoompinch>
154
+ ```
155
+
156
+ ### Ref Methods
157
+
158
+ Access methods via ref:
159
+
160
+ ```typescript
161
+ import { ZoompinchRef } from '@zoompinch/react';
162
+
163
+ const zoompinchRef = useRef<ZoompinchRef>(null);
164
+
165
+ // Call methods
166
+ zoompinchRef.current?.applyTransform(scale, wrapperCoords, canvasCoords, rotate?);
167
+ zoompinchRef.current?.normalizeClientCoords(clientX, clientY);
168
+ zoompinchRef.current?.composePoint(x, y);
169
+ zoompinchRef.current?.rotateCanvas(x, y, radians);
170
+
171
+ // Access properties
172
+ zoompinchRef.current?.canvasWidth;
173
+ zoompinchRef.current?.canvasHeight;
174
+ zoompinchRef.current?.zoompinchEngine; // Access core engine directly
175
+ ```
176
+
177
+ #### `applyTransform(scale, wrapperCoords, canvasCoords, rotate?)`
178
+
179
+ Apply transform by anchoring a canvas point to a wrapper point.
180
+
181
+ **Parameters:**
182
+ - `scale: number` - Target scale
183
+ - `wrapperCoords: [number, number]` - Wrapper position (0-1, 0.5 = center)
184
+ - `canvasCoords: [number, number]` - Canvas position (0-1, 0.5 = center)
185
+ - `rotate?: number` - Optional rotation in radians
186
+
187
+ **Examples:**
188
+
189
+ ```typescript
190
+ // Center canvas at scale 1
191
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5]);
192
+
193
+ // Zoom to 2x, keep centered
194
+ zoompinchRef.current?.applyTransform(2, [0.5, 0.5], [0.5, 0.5]);
195
+
196
+ // Anchor canvas top-left to wrapper center
197
+ zoompinchRef.current?.applyTransform(1.5, [0.5, 0.5], [0, 0]);
198
+
199
+ // Set rotation
200
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5], Math.PI / 4);
201
+ ```
202
+
203
+ #### `normalizeClientCoords(clientX, clientY)`
204
+
205
+ Convert global client coordinates to canvas coordinates.
206
+
207
+ **Parameters:**
208
+ - `clientX: number` - Global X from event
209
+ - `clientY: number` - Global Y from event
210
+
211
+ **Returns:** `[number, number]` - Canvas coordinates in pixels
212
+
213
+ **Example:**
214
+
215
+ ```typescript
216
+ function handleClick(event: React.MouseEvent) {
217
+ const [x, y] = zoompinchRef.current!.normalizeClientCoords(
218
+ event.clientX,
219
+ event.clientY
220
+ );
221
+ console.log('Canvas position:', x, y);
222
+ }
223
+ ```
224
+
225
+ #### `composePoint(x, y)`
226
+
227
+ Convert canvas coordinates to wrapper coordinates (accounts for transform).
228
+
229
+ **Parameters:**
230
+ - `x: number` - Canvas X in pixels
231
+ - `y: number` - Canvas Y in pixels
232
+
233
+ **Returns:** `[number, number]` - Wrapper coordinates in pixels
234
+
235
+ **Example:**
236
+
237
+ ```typescript
238
+ // Get wrapper position for canvas center
239
+ const [wrapperX, wrapperY] = zoompinchRef.current!.composePoint(
240
+ zoompinchRef.current!.canvasWidth / 2,
241
+ zoompinchRef.current!.canvasHeight / 2
242
+ );
243
+ ```
244
+
245
+ #### `rotateCanvas(x, y, radians)`
246
+
247
+ Rotate canvas around a specific canvas point.
248
+
249
+ **Parameters:**
250
+ - `x: number` - Canvas X (rotation center)
251
+ - `y: number` - Canvas Y (rotation center)
252
+ - `radians: number` - Rotation angle
253
+
254
+ **Example:**
255
+
256
+ ```typescript
257
+ // Rotate 90° around canvas center
258
+ const centerX = zoompinchRef.current!.canvasWidth / 2;
259
+ const centerY = zoompinchRef.current!.canvasHeight / 2;
260
+ zoompinchRef.current?.rotateCanvas(centerX, centerY, Math.PI / 2);
261
+ ```
262
+
263
+ ### Ref Properties
264
+
265
+ Access current canvas dimensions and engine:
266
+
267
+ ```typescript
268
+ const width = zoompinchRef.current?.canvasWidth; // number
269
+ const height = zoompinchRef.current?.canvasHeight; // number
270
+ const engine = zoompinchRef.current?.zoompinchEngine; // ZoompinchCore | null
271
+ ```
272
+
273
+ ### Matrix Prop
274
+
275
+ Render overlay elements that follow the canvas transform.
276
+
277
+ **Type:** `ReactNode | ((props: MatrixProps) => ReactNode)`
278
+
279
+ **MatrixProps:**
280
+
281
+ | Prop | Type | Description |
282
+ |------|------|-------------|
283
+ | `composePoint` | `(x: number, y: number) => [number, number]` | Canvas → Wrapper coords |
284
+ | `normalizeClientCoords` | `(clientX: number, clientY: number) => [number, number]` | Client → Canvas coords |
285
+ | `canvasWidth` | `number` | Current canvas width |
286
+ | `canvasHeight` | `number` | Current canvas height |
287
+
288
+ **Note:** `applyTransform` and `rotateCanvas` are NOT available in the matrix function. Use component ref instead.
289
+
290
+ **Example:**
291
+
292
+ ```tsx
293
+ <Zoompinch
294
+ matrix={({ composePoint, normalizeClientCoords, canvasWidth, canvasHeight }) => (
295
+ <svg width="100%" height="100%">
296
+ <circle
297
+ cx={composePoint(canvasWidth / 2, canvasHeight / 2)[0]}
298
+ cy={composePoint(canvasWidth / 2, canvasHeight / 2)[1]}
299
+ r="8"
300
+ fill="red"
301
+ />
302
+ </svg>
303
+ )}
304
+ >
305
+ <img width="1920" height="1080" src="image.jpg" />
306
+ </Zoompinch>
307
+ ```
308
+
309
+ ## Coordinate Systems
310
+
311
+ ### 1. Canvas Coordinates (Absolute)
312
+
313
+ Absolute pixels within canvas content.
314
+ - Origin: `(0, 0)` at top-left
315
+ - Range: `0` to `canvasWidth`, `0` to `canvasHeight`
316
+
317
+ ```typescript
318
+ const [canvasX, canvasY] = normalizeClientCoords(event.clientX, event.clientY);
319
+ ```
320
+
321
+ ### 2. Wrapper Coordinates (Absolute)
322
+
323
+ Absolute pixels within viewport/wrapper.
324
+ - Origin: `(0, 0)` at top-left (accounting for offset)
325
+ - Range: `0` to `wrapperWidth`, `0` to `wrapperHeight`
326
+
327
+ ```typescript
328
+ const [wrapperX, wrapperY] = composePoint(canvasX, canvasY);
329
+ ```
330
+
331
+ ### 3. Relative Coordinates (0-1)
332
+
333
+ Normalized coordinates for `applyTransform`.
334
+ - Range: `0.0` to `1.0`
335
+ - `0.5` = center, `1.0` = bottom-right
336
+
337
+ ```typescript
338
+ [0, 0] // top-left
339
+ [0.5, 0.5] // center
340
+ [1, 1] // bottom-right
341
+ ```
342
+
343
+ **Conversion Flow:**
344
+
345
+ ```
346
+ Client Coords → normalizeClientCoords() → Canvas Coords → composePoint() → Wrapper Coords
347
+ ```
348
+
349
+ ## Complete Playground Example
350
+
351
+ ```tsx
352
+ import React, { useRef, useState } from 'react';
353
+ import { Zoompinch, ZoompinchRef } from '@zoompinch/react';
354
+
355
+ function App() {
356
+ const zoompinchRef = useRef<ZoompinchRef>(null);
357
+ const [transform, setTransform] = useState({
358
+ translateX: 0,
359
+ translateY: 0,
360
+ scale: 1,
361
+ rotate: 0
362
+ });
363
+ const [clickPoint, setClickPoint] = useState<[number, number] | null>(null);
364
+
365
+ function handleInit() {
366
+ // Center canvas on initialization
367
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5], 0);
368
+ }
369
+
370
+ function handleClick(event: React.MouseEvent) {
371
+ if (!zoompinchRef.current) return;
372
+ const [x, y] = zoompinchRef.current.normalizeClientCoords(
373
+ event.clientX,
374
+ event.clientY
375
+ );
376
+ setClickPoint([x, y]);
377
+ console.log('Clicked at:', x, y);
378
+ }
379
+
380
+ function handleZoomIn() {
381
+ if (!zoompinchRef.current) return;
382
+ const newScale = Math.min(transform.scale * 1.5, 4);
383
+ zoompinchRef.current.applyTransform(newScale, [0.5, 0.5], [0.5, 0.5]);
384
+ }
385
+
386
+ function handleZoomOut() {
387
+ if (!zoompinchRef.current) return;
388
+ const newScale = Math.max(transform.scale / 1.5, 0.5);
389
+ zoompinchRef.current.applyTransform(newScale, [0.5, 0.5], [0.5, 0.5]);
390
+ }
391
+
392
+ function handleReset() {
393
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5], 0);
394
+ }
395
+
396
+ function handleRotate() {
397
+ if (!zoompinchRef.current) return;
398
+ const centerX = zoompinchRef.current.canvasWidth / 2;
399
+ const centerY = zoompinchRef.current.canvasHeight / 2;
400
+ zoompinchRef.current.rotateCanvas(centerX, centerY, Math.PI / 4);
401
+ }
402
+
403
+ return (
404
+ <div style={{ padding: '20px' }}>
405
+ <div style={{ marginBottom: '10px' }}>
406
+ <button onClick={handleZoomIn}>Zoom In</button>
407
+ <button onClick={handleZoomOut}>Zoom Out</button>
408
+ <button onClick={handleReset}>Reset</button>
409
+ <button onClick={handleRotate}>Rotate 45°</button>
410
+ </div>
411
+
412
+ <div style={{ marginBottom: '10px' }}>
413
+ <strong>Transform:</strong> Scale: {transform.scale.toFixed(2)},
414
+ Rotate: {(transform.rotate * 180 / Math.PI).toFixed(0)}°
415
+ </div>
416
+
417
+ {clickPoint && (
418
+ <div style={{ marginBottom: '10px' }}>
419
+ <strong>Last click:</strong> ({clickPoint[0].toFixed(0)}, {clickPoint[1].toFixed(0)})
420
+ </div>
421
+ )}
422
+
423
+ <Zoompinch
424
+ ref={zoompinchRef}
425
+ style={{
426
+ width: '800px',
427
+ height: '600px',
428
+ border: '2px solid #333',
429
+ borderRadius: '8px'
430
+ }}
431
+ transform={transform}
432
+ onTransformChange={setTransform}
433
+ offset={{ top: 0, right: 0, bottom: 0, left: 0 }}
434
+ minScale={0.5}
435
+ maxScale={4}
436
+ clampBounds={false}
437
+ rotation={true}
438
+ mouse={true}
439
+ wheel={true}
440
+ touch={true}
441
+ gesture={true}
442
+ onInit={handleInit}
443
+ onClick={handleClick}
444
+ matrix={({ composePoint, canvasWidth, canvasHeight }) => (
445
+ <svg width="100%" height="100%">
446
+ {/* Center marker */}
447
+ <circle
448
+ cx={composePoint(canvasWidth / 2, canvasHeight / 2)[0]}
449
+ cy={composePoint(canvasWidth / 2, canvasHeight / 2)[1]}
450
+ r="8"
451
+ fill="red"
452
+ />
453
+
454
+ {/* Click point marker */}
455
+ {clickPoint && (
456
+ <circle
457
+ cx={composePoint(clickPoint[0], clickPoint[1])[0]}
458
+ cy={composePoint(clickPoint[0], clickPoint[1])[1]}
459
+ r="5"
460
+ fill="blue"
461
+ />
462
+ )}
463
+ </svg>
464
+ )}
465
+ >
466
+ <img
467
+ width="1536"
468
+ height="2048"
469
+ src="https://imagedelivery.net/mudX-CmAqIANL8bxoNCToA/489df5b2-38ce-46e7-32e0-d50170e8d800/public"
470
+ draggable={false}
471
+ style={{ userSelect: 'none' }}
472
+ />
473
+ </Zoompinch>
474
+ </div>
475
+ );
476
+ }
477
+
478
+ export default App;
479
+ ```
480
+
481
+ ## Best Practices
482
+
483
+ 1. **Always specify image dimensions** to avoid layout shifts:
484
+ ```tsx
485
+ <img width="1920" height="1080" src="image.jpg" />
486
+ ```
487
+
488
+ 2. **Center content on init:**
489
+ ```typescript
490
+ function handleInit() {
491
+ zoompinchRef.current?.applyTransform(1, [0.5, 0.5], [0.5, 0.5]);
492
+ }
493
+ ```
494
+
495
+ 3. **Prevent image drag:**
496
+ ```tsx
497
+ <img
498
+ src="image.jpg"
499
+ draggable={false}
500
+ style={{ userSelect: 'none' }}
501
+ />
502
+ ```
503
+
504
+ 4. **Use controlled transform state:**
505
+ ```tsx
506
+ const [transform, setTransform] = useState({
507
+ translateX: 0, translateY: 0, scale: 1, rotate: 0
508
+ });
509
+
510
+ <Zoompinch
511
+ transform={transform}
512
+ onTransformChange={setTransform}
513
+ />
514
+ ```
515
+
516
+ 5. **Enable clamp bounds for better UX:**
517
+ ```tsx
518
+ <Zoompinch clampBounds={true} minScale={0.5} maxScale={4} />
519
+ ```
520
+
521
+ ## Styling
522
+
523
+ Minimal base styles are applied. Customize via style prop:
524
+
525
+ ```tsx
526
+ <Zoompinch
527
+ style={{
528
+ width: '100%',
529
+ height: '600px',
530
+ border: '1px solid #ccc',
531
+ borderRadius: '8px'
532
+ }}
533
+ >
534
+ {/* content */}
535
+ </Zoompinch>
536
+ ```
537
+
538
+ **Internal CSS classes:**
539
+
540
+ ```css
541
+ .zoompinch /* Container */
542
+ .zoompinch > .canvas /* Canvas wrapper */
543
+ .zoompinch > .matrix /* Matrix overlay */
544
+ ```
545
+
546
+ ## TypeScript Support
547
+
548
+ Full TypeScript support with exported types:
549
+
550
+ ```typescript
551
+ import {
552
+ Zoompinch,
553
+ ZoompinchRef,
554
+ ZoompinchProps
555
+ } from '@zoompinch/react';
556
+
557
+ import type { Transform } from '@zoompinch/core';
558
+ ```
559
+
560
+ ## Browser Support
561
+
562
+ - ✅ Chrome/Edge (latest)
563
+ - ✅ Firefox (latest)
564
+ - ✅ Safari (latest, including iOS)
565
+ - ✅ Mobile browsers (iOS Safari, Chrome Mobile)
566
+
567
+ ## License
568
+
569
+ MIT
570
+
571
+
572
+ ## Related
573
+
574
+ - [@zoompinch/core](https://www.npmjs.com/package/@zoompinch/core) - Core engine
575
+ - [@zoompinch/vue](https://www.npmjs.com/package/@zoompinch/vue) - Vue 3
576
+ - [@zoompinch/elements](https://www.npmjs.com/package/@zoompinch/elements) - Web Components
577
+
578
+ Built with ❤️ by Elya Maurice Conrad
package/dist/react.css ADDED
@@ -0,0 +1 @@
1
+ .zoompinch{touch-action:none;overflow:hidden;position:relative;border:2px solid #ccc}.zoompinch>.canvas{position:absolute}.zoompinch>.matrix{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0}
@@ -0,0 +1,408 @@
1
+ import te, { forwardRef as ne, useRef as F, useState as ae, useImperativeHandle as oe, useEffect as E } from "react";
2
+ import { Zoompinch as ue } from "@zoompinch/core";
3
+ var I = { exports: {} }, M = {};
4
+ /**
5
+ * @license React
6
+ * react-jsx-runtime.production.js
7
+ *
8
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
9
+ *
10
+ * This source code is licensed under the MIT license found in the
11
+ * LICENSE file in the root directory of this source tree.
12
+ */
13
+ var Q;
14
+ function se() {
15
+ if (Q) return M;
16
+ Q = 1;
17
+ var a = Symbol.for("react.transitional.element"), m = Symbol.for("react.fragment");
18
+ function l(d, s, c) {
19
+ var i = null;
20
+ if (c !== void 0 && (i = "" + c), s.key !== void 0 && (i = "" + s.key), "key" in s) {
21
+ c = {};
22
+ for (var p in s)
23
+ p !== "key" && (c[p] = s[p]);
24
+ } else c = s;
25
+ return s = c.ref, {
26
+ $$typeof: a,
27
+ type: d,
28
+ key: i,
29
+ ref: s !== void 0 ? s : null,
30
+ props: c
31
+ };
32
+ }
33
+ return M.Fragment = m, M.jsx = l, M.jsxs = l, M;
34
+ }
35
+ var W = {};
36
+ /**
37
+ * @license React
38
+ * react-jsx-runtime.development.js
39
+ *
40
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
41
+ *
42
+ * This source code is licensed under the MIT license found in the
43
+ * LICENSE file in the root directory of this source tree.
44
+ */
45
+ var K;
46
+ function ce() {
47
+ return K || (K = 1, process.env.NODE_ENV !== "production" && (function() {
48
+ function a(e) {
49
+ if (e == null) return null;
50
+ if (typeof e == "function")
51
+ return e.$$typeof === X ? null : e.displayName || e.name || null;
52
+ if (typeof e == "string") return e;
53
+ switch (e) {
54
+ case O:
55
+ return "Fragment";
56
+ case H:
57
+ return "Profiler";
58
+ case U:
59
+ return "StrictMode";
60
+ case t:
61
+ return "Suspense";
62
+ case f:
63
+ return "SuspenseList";
64
+ case x:
65
+ return "Activity";
66
+ }
67
+ if (typeof e == "object")
68
+ switch (typeof e.tag == "number" && console.error(
69
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
70
+ ), e.$$typeof) {
71
+ case G:
72
+ return "Portal";
73
+ case J:
74
+ return e.displayName || "Context";
75
+ case q:
76
+ return (e._context.displayName || "Context") + ".Consumer";
77
+ case _:
78
+ var r = e.render;
79
+ return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
80
+ case v:
81
+ return r = e.displayName || null, r !== null ? r : a(e.type) || "Memo";
82
+ case A:
83
+ r = e._payload, e = e._init;
84
+ try {
85
+ return a(e(r));
86
+ } catch {
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ function m(e) {
92
+ return "" + e;
93
+ }
94
+ function l(e) {
95
+ try {
96
+ m(e);
97
+ var r = !1;
98
+ } catch {
99
+ r = !0;
100
+ }
101
+ if (r) {
102
+ r = console;
103
+ var n = r.error, o = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
104
+ return n.call(
105
+ r,
106
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
107
+ o
108
+ ), m(e);
109
+ }
110
+ }
111
+ function d(e) {
112
+ if (e === O) return "<>";
113
+ if (typeof e == "object" && e !== null && e.$$typeof === A)
114
+ return "<...>";
115
+ try {
116
+ var r = a(e);
117
+ return r ? "<" + r + ">" : "<...>";
118
+ } catch {
119
+ return "<...>";
120
+ }
121
+ }
122
+ function s() {
123
+ var e = g.A;
124
+ return e === null ? null : e.getOwner();
125
+ }
126
+ function c() {
127
+ return Error("react-stack-top-frame");
128
+ }
129
+ function i(e) {
130
+ if (S.call(e, "key")) {
131
+ var r = Object.getOwnPropertyDescriptor(e, "key").get;
132
+ if (r && r.isReactWarning) return !1;
133
+ }
134
+ return e.key !== void 0;
135
+ }
136
+ function p(e, r) {
137
+ function n() {
138
+ j || (j = !0, console.error(
139
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
140
+ r
141
+ ));
142
+ }
143
+ n.isReactWarning = !0, Object.defineProperty(e, "key", {
144
+ get: n,
145
+ configurable: !0
146
+ });
147
+ }
148
+ function w() {
149
+ var e = a(this.type);
150
+ return L[e] || (L[e] = !0, console.error(
151
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
152
+ )), e = this.props.ref, e !== void 0 ? e : null;
153
+ }
154
+ function T(e, r, n, o, R, V) {
155
+ var u = n.ref;
156
+ return e = {
157
+ $$typeof: y,
158
+ type: e,
159
+ key: r,
160
+ props: n,
161
+ _owner: o
162
+ }, (u !== void 0 ? u : null) !== null ? Object.defineProperty(e, "ref", {
163
+ enumerable: !1,
164
+ get: w
165
+ }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
166
+ configurable: !1,
167
+ enumerable: !1,
168
+ writable: !0,
169
+ value: 0
170
+ }), Object.defineProperty(e, "_debugInfo", {
171
+ configurable: !1,
172
+ enumerable: !1,
173
+ writable: !0,
174
+ value: null
175
+ }), Object.defineProperty(e, "_debugStack", {
176
+ configurable: !1,
177
+ enumerable: !1,
178
+ writable: !0,
179
+ value: R
180
+ }), Object.defineProperty(e, "_debugTask", {
181
+ configurable: !1,
182
+ enumerable: !1,
183
+ writable: !0,
184
+ value: V
185
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
186
+ }
187
+ function $(e, r, n, o, R, V) {
188
+ var u = r.children;
189
+ if (u !== void 0)
190
+ if (o)
191
+ if (z(u)) {
192
+ for (o = 0; o < u.length; o++)
193
+ b(u[o]);
194
+ Object.freeze && Object.freeze(u);
195
+ } else
196
+ console.error(
197
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
198
+ );
199
+ else b(u);
200
+ if (S.call(r, "key")) {
201
+ u = a(e);
202
+ var k = Object.keys(r).filter(function(re) {
203
+ return re !== "key";
204
+ });
205
+ o = 0 < k.length ? "{key: someKey, " + k.join(": ..., ") + ": ...}" : "{key: someKey}", Y[u + o] || (k = 0 < k.length ? "{" + k.join(": ..., ") + ": ...}" : "{}", console.error(
206
+ `A props object containing a "key" prop is being spread into JSX:
207
+ let props = %s;
208
+ <%s {...props} />
209
+ React keys must be passed directly to JSX without using spread:
210
+ let props = %s;
211
+ <%s key={someKey} {...props} />`,
212
+ o,
213
+ u,
214
+ k,
215
+ u
216
+ ), Y[u + o] = !0);
217
+ }
218
+ if (u = null, n !== void 0 && (l(n), u = "" + n), i(r) && (l(r.key), u = "" + r.key), "key" in r) {
219
+ n = {};
220
+ for (var Z in r)
221
+ Z !== "key" && (n[Z] = r[Z]);
222
+ } else n = r;
223
+ return u && p(
224
+ n,
225
+ typeof e == "function" ? e.displayName || e.name || "Unknown" : e
226
+ ), T(
227
+ e,
228
+ u,
229
+ n,
230
+ s(),
231
+ R,
232
+ V
233
+ );
234
+ }
235
+ function b(e) {
236
+ D(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === A && (e._payload.status === "fulfilled" ? D(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
237
+ }
238
+ function D(e) {
239
+ return typeof e == "object" && e !== null && e.$$typeof === y;
240
+ }
241
+ var h = te, y = Symbol.for("react.transitional.element"), G = Symbol.for("react.portal"), O = Symbol.for("react.fragment"), U = Symbol.for("react.strict_mode"), H = Symbol.for("react.profiler"), q = Symbol.for("react.consumer"), J = Symbol.for("react.context"), _ = Symbol.for("react.forward_ref"), t = Symbol.for("react.suspense"), f = Symbol.for("react.suspense_list"), v = Symbol.for("react.memo"), A = Symbol.for("react.lazy"), x = Symbol.for("react.activity"), X = Symbol.for("react.client.reference"), g = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, S = Object.prototype.hasOwnProperty, z = Array.isArray, P = console.createTask ? console.createTask : function() {
242
+ return null;
243
+ };
244
+ h = {
245
+ react_stack_bottom_frame: function(e) {
246
+ return e();
247
+ }
248
+ };
249
+ var j, L = {}, N = h.react_stack_bottom_frame.bind(
250
+ h,
251
+ c
252
+ )(), C = P(d(c)), Y = {};
253
+ W.Fragment = O, W.jsx = function(e, r, n) {
254
+ var o = 1e4 > g.recentlyCreatedOwnerStacks++;
255
+ return $(
256
+ e,
257
+ r,
258
+ n,
259
+ !1,
260
+ o ? Error("react-stack-top-frame") : N,
261
+ o ? P(d(e)) : C
262
+ );
263
+ }, W.jsxs = function(e, r, n) {
264
+ var o = 1e4 > g.recentlyCreatedOwnerStacks++;
265
+ return $(
266
+ e,
267
+ r,
268
+ n,
269
+ !0,
270
+ o ? Error("react-stack-top-frame") : N,
271
+ o ? P(d(e)) : C
272
+ );
273
+ };
274
+ })()), W;
275
+ }
276
+ var ee;
277
+ function ie() {
278
+ return ee || (ee = 1, process.env.NODE_ENV === "production" ? I.exports = se() : I.exports = ce()), I.exports;
279
+ }
280
+ var B = ie();
281
+ const le = ne(({
282
+ transform: a = { translateX: 0, translateY: 0, scale: 1, rotate: 0 },
283
+ offset: m = { left: 0, top: 0, right: 0, bottom: 0 },
284
+ minScale: l = 0.5,
285
+ maxScale: d = 10,
286
+ clampBounds: s = !1,
287
+ rotation: c = !0,
288
+ mouse: i = !0,
289
+ wheel: p = !0,
290
+ touch: w = !0,
291
+ gesture: T = !0,
292
+ children: $,
293
+ matrix: b,
294
+ style: D,
295
+ onTransformChange: h,
296
+ onInit: y,
297
+ onClick: G,
298
+ onMouseDown: O,
299
+ onTouchStart: U,
300
+ onMouseup: H,
301
+ onTouchend: q
302
+ }, J) => {
303
+ const _ = F(null), t = F(null), f = F(!1), [v, A] = ae({
304
+ composePoint: (r, n) => [0, 0],
305
+ canvasWidth: 0,
306
+ canvasHeight: 0
307
+ }), x = F((r, n) => t.current ? t.current.normalizeClientCoords(r, n) : [0, 0]);
308
+ oe(J, () => ({
309
+ applyTransform: (r, n, o, R) => {
310
+ t.current && (R !== void 0 && (t.current.rotate = R), t.current.applyTransform(r, n, o));
311
+ },
312
+ composePoint: (r, n) => v.composePoint ? v.composePoint(r, n) : [0, 0],
313
+ normalizeClientCoords: (r, n) => x.current ? x.current(r, n) : [0, 0],
314
+ rotateCanvas: (r, n, o) => {
315
+ t.current && t.current.rotateCanvas(r, n, o);
316
+ },
317
+ zoompinchEngine: t.current,
318
+ canvasWidth: v.canvasWidth,
319
+ canvasHeight: v.canvasHeight
320
+ }));
321
+ function X() {
322
+ var r, n;
323
+ t.current && A({
324
+ composePoint: t.current.composePoint.bind(t.current),
325
+ canvasWidth: ((r = t.current.canvasBounds) == null ? void 0 : r.width) ?? 0,
326
+ canvasHeight: ((n = t.current.canvasBounds) == null ? void 0 : n.height) ?? 0
327
+ });
328
+ }
329
+ E(() => {
330
+ !_.current || t.current || (t.current = new ue(_.current, m, a.translateX, a.translateY, a.scale, a.rotate, l, d, s, c), console.log("Zoompinch initialisiert mit Props!"), t.current.addEventListener("update", () => {
331
+ if (!t.current) return;
332
+ const r = {
333
+ translateX: t.current.translateX,
334
+ translateY: t.current.translateY,
335
+ scale: t.current.scale,
336
+ rotate: t.current.rotate
337
+ };
338
+ h && (r.translateX !== a.translateX || r.translateY !== a.translateY || r.scale !== a.scale || r.rotate !== a.rotate) && h(r), X();
339
+ }), t.current.addEventListener("load", () => {
340
+ t.current && (f.current = !0, y && y(), X());
341
+ }));
342
+ }, []), E(() => {
343
+ !t.current || !f.current || (t.current.translateX !== a.translateX || t.current.translateY !== a.translateY || t.current.scale !== a.scale || t.current.rotate !== a.rotate) && (t.current.translateX = a.translateX, t.current.translateY = a.translateY, t.current.scale = a.scale, t.current.rotate = a.rotate, t.current.update());
344
+ }, [a]), E(() => {
345
+ !t.current || !f.current || (t.current.offset = m, t.current.update());
346
+ }, [m]), E(() => {
347
+ !t.current || !f.current || (t.current.minScale = l, t.current.update());
348
+ }, [l]), E(() => {
349
+ !t.current || !f.current || (t.current.maxScale = d, t.current.update());
350
+ }, [d]), E(() => {
351
+ !t.current || !f.current || (t.current.clampBounds = s, t.current.setTranslateFromUserGesture(t.current.translateX, t.current.translateY), t.current.update());
352
+ }, [s]), E(() => {
353
+ !t.current || !f.current || (t.current.rotation = c, t.current.update());
354
+ }, [c]);
355
+ const g = (r) => {
356
+ !t.current || !p || (r.preventDefault(), t.current.handleWheel(r));
357
+ }, S = (r) => {
358
+ !t.current || !T || t.current.handleGesturestart(r);
359
+ }, z = (r) => {
360
+ !t.current || !T || t.current.handleGesturechange(r);
361
+ }, P = (r) => {
362
+ !t.current || !T || t.current.handleGestureend(r);
363
+ }, j = (r) => {
364
+ !t.current || !i || t.current.handleMousedown(r);
365
+ }, L = (r) => {
366
+ !t.current || !i || t.current.handleMousemove(r);
367
+ }, N = (r) => {
368
+ !t.current || !i || t.current.handleMouseup(r);
369
+ }, C = (r) => {
370
+ !t.current || !w || t.current.handleTouchstart(r);
371
+ }, Y = (r) => {
372
+ !t.current || !w || t.current.handleTouchmove(r);
373
+ }, e = (r) => {
374
+ !t.current || !w || t.current.handleTouchend(r);
375
+ };
376
+ return E(() => {
377
+ if (!_.current) return;
378
+ const r = _.current;
379
+ return window.addEventListener("gesturechange", z), window.addEventListener("gestureend", P), window.addEventListener("mousemove", L), window.addEventListener("mouseup", N), window.addEventListener("touchmove", Y), window.addEventListener("touchend", e), r.addEventListener("wheel", g, { passive: !1 }), r.addEventListener("gesturestart", S, { passive: !1 }), r.addEventListener("mousedown", j, { passive: !1 }), r.addEventListener("touchstart", C, { passive: !1 }), () => {
380
+ window.removeEventListener("gesturechange", z), window.removeEventListener("gestureend", P), window.removeEventListener("mousemove", L), window.removeEventListener("mouseup", N), window.removeEventListener("touchmove", Y), window.removeEventListener("touchend", e), r.removeEventListener("wheel", g), r.removeEventListener("gesturestart", S), r.removeEventListener("mousedown", j), r.removeEventListener("touchstart", C);
381
+ };
382
+ }, [i, w, T, p]), /* @__PURE__ */ B.jsxs(
383
+ "div",
384
+ {
385
+ ref: _,
386
+ className: "zoompinch",
387
+ style: D,
388
+ onClick: G,
389
+ onMouseDown: O,
390
+ onTouchStart: U,
391
+ onMouseUp: H,
392
+ onTouchEnd: q,
393
+ children: [
394
+ /* @__PURE__ */ B.jsx("div", { className: "canvas", children: $ }),
395
+ /* @__PURE__ */ B.jsx("div", { className: "matrix", children: typeof b == "function" ? b({
396
+ composePoint: v.composePoint,
397
+ normalizeClientCoords: x.current,
398
+ canvasWidth: v.canvasWidth,
399
+ canvasHeight: v.canvasHeight
400
+ }) : b })
401
+ ]
402
+ }
403
+ );
404
+ });
405
+ le.displayName = "Zoompinch";
406
+ export {
407
+ le as Zoompinch
408
+ };
@@ -0,0 +1,22 @@
1
+ (function(p,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("@zoompinch/core")):typeof define=="function"&&define.amd?define(["exports","react","@zoompinch/core"],u):(p=typeof globalThis<"u"?globalThis:p||self,u(p.ZoompinchReact={},p.React,p.ZoompinchCore))})(this,(function(p,u,te){"use strict";var D={exports:{}},O={};/**
2
+ * @license React
3
+ * react-jsx-runtime.production.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */var q;function ne(){if(q)return O;q=1;var a=Symbol.for("react.transitional.element"),E=Symbol.for("react.fragment");function f(d,c,i){var l=null;if(i!==void 0&&(l=""+i),c.key!==void 0&&(l=""+c.key),"key"in c){i={};for(var h in c)h!=="key"&&(i[h]=c[h])}else i=c;return c=i.ref,{$$typeof:a,type:d,key:l,ref:c!==void 0?c:null,props:i}}return O.Fragment=E,O.jsx=f,O.jsxs=f,O}var x={};/**
10
+ * @license React
11
+ * react-jsx-runtime.development.js
12
+ *
13
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ */var $;function ae(){return $||($=1,process.env.NODE_ENV!=="production"&&(function(){function a(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===I?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case S:return"Fragment";case J:return"Profiler";case Z:return"StrictMode";case t:return"Suspense";case v:return"SuspenseList";case C:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case H:return"Portal";case B:return e.displayName||"Context";case V:return(e._context.displayName||"Context")+".Consumer";case _:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case m:return r=e.displayName||null,r!==null?r:a(e.type)||"Memo";case j:r=e._payload,e=e._init;try{return a(e(r))}catch{}}return null}function E(e){return""+e}function f(e){try{E(e);var r=!1}catch{r=!0}if(r){r=console;var n=r.error,o=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return n.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",o),E(e)}}function d(e){if(e===S)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===j)return"<...>";try{var r=a(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function c(){var e=P.A;return e===null?null:e.getOwner()}function i(){return Error("react-stack-top-frame")}function l(e){if(L.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function h(e,r){function n(){N||(N=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}n.isReactWarning=!0,Object.defineProperty(e,"key",{get:n,configurable:!0})}function w(){var e=a(this.type);return Y[e]||(Y[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function b(e,r,n,o,T,Q){var s=n.ref;return e={$$typeof:A,type:e,key:r,props:n,_owner:o},(s!==void 0?s:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:w}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:T}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Q}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function X(e,r,n,o,T,Q){var s=r.children;if(s!==void 0)if(o)if(G(s)){for(o=0;o<s.length;o++)g(s[o]);Object.freeze&&Object.freeze(s)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else g(s);if(L.call(r,"key")){s=a(e);var k=Object.keys(r).filter(function(ue){return ue!=="key"});o=0<k.length?"{key: someKey, "+k.join(": ..., ")+": ...}":"{key: someKey}",z[s+o]||(k=0<k.length?"{"+k.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
18
+ let props = %s;
19
+ <%s {...props} />
20
+ React keys must be passed directly to JSX without using spread:
21
+ let props = %s;
22
+ <%s key={someKey} {...props} />`,o,s,k,s),z[s+o]=!0)}if(s=null,n!==void 0&&(f(n),s=""+n),l(r)&&(f(r.key),s=""+r.key),"key"in r){n={};for(var K in r)K!=="key"&&(n[K]=r[K])}else n=r;return s&&h(n,typeof e=="function"?e.displayName||e.name||"Unknown":e),b(e,s,n,c(),T,Q)}function g(e){F(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===j&&(e._payload.status==="fulfilled"?F(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function F(e){return typeof e=="object"&&e!==null&&e.$$typeof===A}var R=u,A=Symbol.for("react.transitional.element"),H=Symbol.for("react.portal"),S=Symbol.for("react.fragment"),Z=Symbol.for("react.strict_mode"),J=Symbol.for("react.profiler"),V=Symbol.for("react.consumer"),B=Symbol.for("react.context"),_=Symbol.for("react.forward_ref"),t=Symbol.for("react.suspense"),v=Symbol.for("react.suspense_list"),m=Symbol.for("react.memo"),j=Symbol.for("react.lazy"),C=Symbol.for("react.activity"),I=Symbol.for("react.client.reference"),P=R.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,L=Object.prototype.hasOwnProperty,G=Array.isArray,y=console.createTask?console.createTask:function(){return null};R={react_stack_bottom_frame:function(e){return e()}};var N,Y={},M=R.react_stack_bottom_frame.bind(R,i)(),W=y(d(i)),z={};x.Fragment=S,x.jsx=function(e,r,n){var o=1e4>P.recentlyCreatedOwnerStacks++;return X(e,r,n,!1,o?Error("react-stack-top-frame"):M,o?y(d(e)):W)},x.jsxs=function(e,r,n){var o=1e4>P.recentlyCreatedOwnerStacks++;return X(e,r,n,!0,o?Error("react-stack-top-frame"):M,o?y(d(e)):W)}})()),x}var ee;function oe(){return ee||(ee=1,process.env.NODE_ENV==="production"?D.exports=ne():D.exports=ae()),D.exports}var U=oe();const re=u.forwardRef(({transform:a={translateX:0,translateY:0,scale:1,rotate:0},offset:E={left:0,top:0,right:0,bottom:0},minScale:f=.5,maxScale:d=10,clampBounds:c=!1,rotation:i=!0,mouse:l=!0,wheel:h=!0,touch:w=!0,gesture:b=!0,children:X,matrix:g,style:F,onTransformChange:R,onInit:A,onClick:H,onMouseDown:S,onTouchStart:Z,onMouseup:J,onTouchend:V},B)=>{const _=u.useRef(null),t=u.useRef(null),v=u.useRef(!1),[m,j]=u.useState({composePoint:(r,n)=>[0,0],canvasWidth:0,canvasHeight:0}),C=u.useRef((r,n)=>t.current?t.current.normalizeClientCoords(r,n):[0,0]);u.useImperativeHandle(B,()=>({applyTransform:(r,n,o,T)=>{t.current&&(T!==void 0&&(t.current.rotate=T),t.current.applyTransform(r,n,o))},composePoint:(r,n)=>m.composePoint?m.composePoint(r,n):[0,0],normalizeClientCoords:(r,n)=>C.current?C.current(r,n):[0,0],rotateCanvas:(r,n,o)=>{t.current&&t.current.rotateCanvas(r,n,o)},zoompinchEngine:t.current,canvasWidth:m.canvasWidth,canvasHeight:m.canvasHeight}));function I(){var r,n;t.current&&j({composePoint:t.current.composePoint.bind(t.current),canvasWidth:((r=t.current.canvasBounds)==null?void 0:r.width)??0,canvasHeight:((n=t.current.canvasBounds)==null?void 0:n.height)??0})}u.useEffect(()=>{!_.current||t.current||(t.current=new te.Zoompinch(_.current,E,a.translateX,a.translateY,a.scale,a.rotate,f,d,c,i),console.log("Zoompinch initialisiert mit Props!"),t.current.addEventListener("update",()=>{if(!t.current)return;const r={translateX:t.current.translateX,translateY:t.current.translateY,scale:t.current.scale,rotate:t.current.rotate};R&&(r.translateX!==a.translateX||r.translateY!==a.translateY||r.scale!==a.scale||r.rotate!==a.rotate)&&R(r),I()}),t.current.addEventListener("load",()=>{t.current&&(v.current=!0,A&&A(),I())}))},[]),u.useEffect(()=>{!t.current||!v.current||(t.current.translateX!==a.translateX||t.current.translateY!==a.translateY||t.current.scale!==a.scale||t.current.rotate!==a.rotate)&&(t.current.translateX=a.translateX,t.current.translateY=a.translateY,t.current.scale=a.scale,t.current.rotate=a.rotate,t.current.update())},[a]),u.useEffect(()=>{!t.current||!v.current||(t.current.offset=E,t.current.update())},[E]),u.useEffect(()=>{!t.current||!v.current||(t.current.minScale=f,t.current.update())},[f]),u.useEffect(()=>{!t.current||!v.current||(t.current.maxScale=d,t.current.update())},[d]),u.useEffect(()=>{!t.current||!v.current||(t.current.clampBounds=c,t.current.setTranslateFromUserGesture(t.current.translateX,t.current.translateY),t.current.update())},[c]),u.useEffect(()=>{!t.current||!v.current||(t.current.rotation=i,t.current.update())},[i]);const P=r=>{!t.current||!h||(r.preventDefault(),t.current.handleWheel(r))},L=r=>{!t.current||!b||t.current.handleGesturestart(r)},G=r=>{!t.current||!b||t.current.handleGesturechange(r)},y=r=>{!t.current||!b||t.current.handleGestureend(r)},N=r=>{!t.current||!l||t.current.handleMousedown(r)},Y=r=>{!t.current||!l||t.current.handleMousemove(r)},M=r=>{!t.current||!l||t.current.handleMouseup(r)},W=r=>{!t.current||!w||t.current.handleTouchstart(r)},z=r=>{!t.current||!w||t.current.handleTouchmove(r)},e=r=>{!t.current||!w||t.current.handleTouchend(r)};return u.useEffect(()=>{if(!_.current)return;const r=_.current;return window.addEventListener("gesturechange",G),window.addEventListener("gestureend",y),window.addEventListener("mousemove",Y),window.addEventListener("mouseup",M),window.addEventListener("touchmove",z),window.addEventListener("touchend",e),r.addEventListener("wheel",P,{passive:!1}),r.addEventListener("gesturestart",L,{passive:!1}),r.addEventListener("mousedown",N,{passive:!1}),r.addEventListener("touchstart",W,{passive:!1}),()=>{window.removeEventListener("gesturechange",G),window.removeEventListener("gestureend",y),window.removeEventListener("mousemove",Y),window.removeEventListener("mouseup",M),window.removeEventListener("touchmove",z),window.removeEventListener("touchend",e),r.removeEventListener("wheel",P),r.removeEventListener("gesturestart",L),r.removeEventListener("mousedown",N),r.removeEventListener("touchstart",W)}},[l,w,b,h]),U.jsxs("div",{ref:_,className:"zoompinch",style:F,onClick:H,onMouseDown:S,onTouchStart:Z,onMouseUp:J,onTouchEnd:V,children:[U.jsx("div",{className:"canvas",children:X}),U.jsx("div",{className:"matrix",children:typeof g=="function"?g({composePoint:m.composePoint,normalizeClientCoords:C.current,canvasWidth:m.canvasWidth,canvasHeight:m.canvasHeight}):g})]})});re.displayName="Zoompinch",p.Zoompinch=re,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@zoompinch/react",
3
+ "version": "0.0.4",
4
+ "description": "React components for Zoompinch",
5
+ "main": "./dist/zoompinch-react.umd.js",
6
+ "module": "./dist/zoompinch-react.es.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/zoompinch-react.es.js",
11
+ "require": "./dist/zoompinch-react.umd.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "dev": "vite",
20
+ "build": "tsc && vite build",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "react",
25
+ "zoompinch",
26
+ "zoom images",
27
+ "pinch to zoom",
28
+ "image zoom",
29
+ "pan gesture",
30
+ "pan and zoom",
31
+ "panzoom",
32
+ "gesture library",
33
+ "touch gestures"
34
+ ],
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "homepage": "https://zoompinch.pages.dev/",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/ElyaConrad/zoompinch"
42
+ },
43
+ "author": "Elya Maurice Conrad",
44
+ "license": "ISC",
45
+ "type": "module",
46
+ "peerDependencies": {
47
+ "react": "^18.0.0 || ^19.0.0",
48
+ "react-dom": "^18.0.0 || ^19.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/react": "^19.2.7",
52
+ "@types/react-dom": "^19.2.3",
53
+ "@vitejs/plugin-react": "^4.7.0",
54
+ "react": "^19.2.3",
55
+ "react-dom": "^19.2.3",
56
+ "typescript": "^5.9.3",
57
+ "vite": "^6.4.1"
58
+ },
59
+ "dependencies": {
60
+ "@zoompinch/core": "^0.0.27"
61
+ }
62
+ }