@pixerate/editor-svelte 0.116.0 → 0.117.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.
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
handlePaintShortcut,
|
|
17
17
|
pointerPressure,
|
|
18
18
|
FreeTransformTool,
|
|
19
|
+
boxFrameHit,
|
|
20
|
+
quadFrameOverlay,
|
|
19
21
|
getViewportProjection,
|
|
20
22
|
measureCanvasViewport,
|
|
21
23
|
watchCanvasViewport,
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
type SelectionToolOptions,
|
|
27
29
|
type ShapeToolOptions,
|
|
28
30
|
type TextEditSession,
|
|
31
|
+
type TransformOverlay,
|
|
29
32
|
type TypeToolOptions,
|
|
30
33
|
} from '@pixerate/editor/image-editor';
|
|
31
34
|
import { untrack } from 'svelte';
|
|
@@ -343,6 +346,64 @@
|
|
|
343
346
|
return () => window.removeEventListener('keydown', onKey);
|
|
344
347
|
});
|
|
345
348
|
|
|
349
|
+
/** How far outside a frame (in hit tolerances) a drag rotates instead of picking a layer. */
|
|
350
|
+
const ROTATE_BAND = 4;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Transform mode, with no transform open: the active layer's frame, drawn as a transform's.
|
|
354
|
+
* A layer locked in place gets the outline without handles.
|
|
355
|
+
*/
|
|
356
|
+
function layerFrame(): TransformOverlay | null {
|
|
357
|
+
if (mode !== 'transform' || transformTool.active) return null;
|
|
358
|
+
const c = editor.controller;
|
|
359
|
+
const id = c.getState().activeLayerId;
|
|
360
|
+
const layer = id ? c.getLayer(id) : undefined;
|
|
361
|
+
if (!layer || layer.visible === false) return null;
|
|
362
|
+
const corners = c.getLayerFrame(layer.id);
|
|
363
|
+
if (!corners) return null;
|
|
364
|
+
return quadFrameOverlay(corners, !(layer.locks?.all || layer.locks?.position));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Transform mode: a drag on the active layer's frame transforms it, and a press elsewhere picks
|
|
369
|
+
* the layer there (or none) and drags that. Each drag opens a Free Transform and closes it on
|
|
370
|
+
* release, one undo step when it changed something, so other edits never meet an open one.
|
|
371
|
+
*/
|
|
372
|
+
let frameDrag = false;
|
|
373
|
+
function handleFramePointerDown(e: PointerEvent): boolean {
|
|
374
|
+
if (mode !== 'transform' || transformTool.active || !canvasEl) return false;
|
|
375
|
+
// Middle-button and Space drags pan (see handleMouseDown).
|
|
376
|
+
if (e.button !== 0 || (viewportGestures && isSpacePressed)) return false;
|
|
377
|
+
const c = editor.controller;
|
|
378
|
+
const { pt, tolerance } = transformPoint(e);
|
|
379
|
+
const frame = layerFrame();
|
|
380
|
+
let target = frame && boxFrameHit(frame, pt, tolerance, tolerance * ROTATE_BAND) ? c.getState().activeLayerId : null;
|
|
381
|
+
if (!target) {
|
|
382
|
+
target = c.layerAt(pt);
|
|
383
|
+
c.setActiveLayer(target);
|
|
384
|
+
}
|
|
385
|
+
const layer = target ? c.getLayer(target) : undefined;
|
|
386
|
+
if (!layer || layer.locks?.all || layer.locks?.position) return true;
|
|
387
|
+
e.preventDefault();
|
|
388
|
+
if (transformTool.begin({ layerId: layer.id })) return true;
|
|
389
|
+
try {
|
|
390
|
+
canvasEl.setPointerCapture?.(e.pointerId);
|
|
391
|
+
} catch {
|
|
392
|
+
// Synthetic events have no active pointer to capture.
|
|
393
|
+
}
|
|
394
|
+
// A press anywhere inside moves the layer, the centre included.
|
|
395
|
+
transformTool.down(pt, tolerance, { reference: false });
|
|
396
|
+
frameDrag = true;
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
function endFrameDrag(cancelled = false) {
|
|
400
|
+
if (!frameDrag) return;
|
|
401
|
+
frameDrag = false;
|
|
402
|
+
if (!transformTool.active) return;
|
|
403
|
+
if (!cancelled && transformTool.modified) transformTool.commit();
|
|
404
|
+
else transformTool.cancel();
|
|
405
|
+
}
|
|
406
|
+
|
|
346
407
|
/** The document point of a pointer event and the hit tolerance (6 screen px). */
|
|
347
408
|
function transformPoint(e: PointerEvent) {
|
|
348
409
|
const rect = canvasEl!.getBoundingClientRect();
|
|
@@ -448,7 +509,7 @@
|
|
|
448
509
|
mode === 'paint' && brushCursor && editor.controller.getState().activeTool !== 'move' && !transformTool.active
|
|
449
510
|
? { ...brushCursor, diameter: editor.controller.getState().paint.brush.size }
|
|
450
511
|
: null,
|
|
451
|
-
freeTransform: transformTool.overlay(),
|
|
512
|
+
freeTransform: transformTool.overlay() ?? layerFrame(),
|
|
452
513
|
textEdit: typeTool.session?.alive ? typeTool.session.overlay() : null,
|
|
453
514
|
});
|
|
454
515
|
}
|
|
@@ -468,6 +529,7 @@
|
|
|
468
529
|
}
|
|
469
530
|
function handlePaintPointerDown(e: PointerEvent) {
|
|
470
531
|
if (handleTransformPointerDown(e)) return;
|
|
532
|
+
if (handleFramePointerDown(e)) return;
|
|
471
533
|
if (mode !== 'paint' || e.button !== 0 || !canvasEl) return;
|
|
472
534
|
e.preventDefault();
|
|
473
535
|
try {
|
|
@@ -479,6 +541,12 @@
|
|
|
479
541
|
}
|
|
480
542
|
function handlePaintPointerMove(e: PointerEvent) {
|
|
481
543
|
if (handleTransformPointerMove(e)) return;
|
|
544
|
+
if (mode === 'transform' && canvasEl) {
|
|
545
|
+
const { pt, tolerance } = transformPoint(e);
|
|
546
|
+
const frame = layerFrame();
|
|
547
|
+
transformCursor = frame ? transformTool.cursor(boxFrameHit(frame, pt, tolerance, tolerance * ROTATE_BAND)) : 'default';
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
482
550
|
if (mode !== 'paint' || !canvasEl) return;
|
|
483
551
|
const samples = paintSamples(e);
|
|
484
552
|
brushCursor = samples[samples.length - 1] ?? null;
|
|
@@ -486,7 +554,10 @@
|
|
|
486
554
|
else void renderCanvas();
|
|
487
555
|
}
|
|
488
556
|
function handlePaintPointerUp() {
|
|
489
|
-
if (handleTransformPointerUp())
|
|
557
|
+
if (handleTransformPointerUp()) {
|
|
558
|
+
endFrameDrag();
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
490
561
|
if (mode !== 'paint' || !paintGesture.active) return;
|
|
491
562
|
paintGesture.up();
|
|
492
563
|
if (paintGesture.error) report('paint', paintGesture.error);
|
|
@@ -552,23 +623,8 @@
|
|
|
552
623
|
return;
|
|
553
624
|
}
|
|
554
625
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const imgPt = canvasToImagePoint(canvasPt, editor.state, view.width, view.height, false);
|
|
558
|
-
const hitLayerId = editor.controller.layerAt(imgPt);
|
|
559
|
-
if (hitLayerId) {
|
|
560
|
-
editor.controller.setActiveLayer(hitLayerId);
|
|
561
|
-
if (!transformTool.active) {
|
|
562
|
-
transformTool.begin();
|
|
563
|
-
}
|
|
564
|
-
} else {
|
|
565
|
-
editor.controller.setActiveLayer(null);
|
|
566
|
-
if (transformTool.active) {
|
|
567
|
-
transformTool.cancel();
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
626
|
+
// Transform mode picks and drags layers on pointerdown (handleFramePointerDown).
|
|
627
|
+
if (mode === 'transform') return;
|
|
572
628
|
|
|
573
629
|
if (transformTool.active) return;
|
|
574
630
|
const canvasPt = getCanvasEventPoint(e);
|
|
@@ -952,10 +1008,13 @@
|
|
|
952
1008
|
onpointerdown={handlePaintPointerDown}
|
|
953
1009
|
onpointermove={handlePaintPointerMove}
|
|
954
1010
|
onpointerup={handlePaintPointerUp}
|
|
955
|
-
onpointercancel={() =>
|
|
1011
|
+
onpointercancel={() => {
|
|
1012
|
+
paintGesture.cancel();
|
|
1013
|
+
endFrameDrag(true);
|
|
1014
|
+
}}
|
|
956
1015
|
data-testid="image-editor-canvas"
|
|
957
|
-
style="width: 100%; height: 100%;{transformActive ? ` cursor: ${transformCursor};` : ''}"
|
|
958
|
-
class="absolute inset-0 w-full h-full block {transformActive ? 'touch-none' : mode === 'paint' ? 'touch-none cursor-crosshair' : mode === 'annotate' && editor.state.activeTool === 'type' ? 'cursor-text' : mode === 'annotate' && editor.state.activeTool === 'shape' ? 'cursor-crosshair' : ''}"
|
|
1016
|
+
style="width: 100%; height: 100%;{transformActive || mode === 'transform' ? ` cursor: ${transformCursor};` : ''}"
|
|
1017
|
+
class="absolute inset-0 w-full h-full block {transformActive || mode === 'transform' ? 'touch-none' : mode === 'paint' ? 'touch-none cursor-crosshair' : mode === 'annotate' && editor.state.activeTool === 'type' ? 'cursor-text' : mode === 'annotate' && editor.state.activeTool === 'shape' ? 'cursor-crosshair' : ''}"
|
|
959
1018
|
></canvas>
|
|
960
1019
|
{#if typeSession}
|
|
961
1020
|
<textarea
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.117.1",
|
|
4
4
|
"description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"@tiptap/extension-bubble-menu": "^2.27.3",
|
|
161
161
|
"@tiptap/extension-placeholder": "^2.27.3",
|
|
162
162
|
"@tiptap/starter-kit": "^2.27.3",
|
|
163
|
-
"@pixerate/editor": "0.
|
|
163
|
+
"@pixerate/editor": "0.160.0"
|
|
164
164
|
},
|
|
165
165
|
"peerDependencies": {
|
|
166
166
|
"@dagrejs/dagre": "^1.1.4",
|