@reekon-tools/boldr-utils 1.19.1 → 1.19.3
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.
|
@@ -492,17 +492,6 @@ export const AnnotationCanvasInner = (props) => {
|
|
|
492
492
|
'worklet';
|
|
493
493
|
return HANDLE_RING_PX / zoom.value;
|
|
494
494
|
});
|
|
495
|
-
// Loupe variants: divided by the loupe's extra magnification too, so handles
|
|
496
|
-
// stay screen-constant INSIDE the lens as well — chrome shouldn't magnify
|
|
497
|
-
// with the content, and at 2× it covers the very point being placed.
|
|
498
|
-
const loupeHandleRadius = useDerivedValue(() => {
|
|
499
|
-
'worklet';
|
|
500
|
-
return HANDLE_RADIUS_PX / zoom.value / LOUPE_MAGNIFICATION;
|
|
501
|
-
});
|
|
502
|
-
const loupeHandleRingWidth = useDerivedValue(() => {
|
|
503
|
-
'worklet';
|
|
504
|
-
return HANDLE_RING_PX / zoom.value / LOUPE_MAGNIFICATION;
|
|
505
|
-
});
|
|
506
495
|
// ---- Plane-calibration handle drag (UI thread; Tool.planeEdit) ----------
|
|
507
496
|
// The plane tool's JS preview path re-rendered the whole canvas (and
|
|
508
497
|
// recomputed the photo-spanning grid) per pointer-move, dropping JS frames
|
|
@@ -538,29 +527,9 @@ export const AnnotationCanvasInner = (props) => {
|
|
|
538
527
|
y: planeDragStartY.value + planeDragTY.value / zoom.value,
|
|
539
528
|
};
|
|
540
529
|
});
|
|
541
|
-
//
|
|
542
|
-
//
|
|
543
|
-
//
|
|
544
|
-
// its size is fixed pixels: project the handle through the same math as
|
|
545
|
-
// loupeTransform — lensCenter + MAG · (screen(handle) − finger). That
|
|
546
|
-
// offset from center is the grab offset the drag preserves, which is why a
|
|
547
|
-
// fixed center mark sat visibly OFF the point and was removed.
|
|
548
|
-
const loupeCrossPath = useDerivedValue(() => {
|
|
549
|
-
'worklet';
|
|
550
|
-
const path = Skia.Path.Make();
|
|
551
|
-
if (planeDragMode.value !== 1)
|
|
552
|
-
return path;
|
|
553
|
-
const p = planeDragHandle.value;
|
|
554
|
-
const sx = (p.x - panX.value) * zoom.value;
|
|
555
|
-
const sy = (p.y - panY.value) * zoom.value;
|
|
556
|
-
const x = loupeCx + LOUPE_MAGNIFICATION * (sx - magTouchX.value);
|
|
557
|
-
const y = loupeCy + LOUPE_MAGNIFICATION * (sy - magTouchY.value);
|
|
558
|
-
path.moveTo(x - LOUPE_CROSS_ARM_PX, y);
|
|
559
|
-
path.lineTo(x + LOUPE_CROSS_ARM_PX, y);
|
|
560
|
-
path.moveTo(x, y - LOUPE_CROSS_ARM_PX);
|
|
561
|
-
path.lineTo(x, y + LOUPE_CROSS_ARM_PX);
|
|
562
|
-
return path;
|
|
563
|
-
}, [loupeCx, loupeCy]);
|
|
530
|
+
// (The lens crosshair marking the dragged point — loupeCrossPath — is
|
|
531
|
+
// declared after the resize sections below: it mirrors every precision
|
|
532
|
+
// drag's live-point math, not just this plane handle's.)
|
|
564
533
|
// WORKLET TWIN of PlaneElement's outline path (quad ring / reference line;
|
|
565
534
|
// the scale ticks are skipped live and reappear on commit). The committed
|
|
566
535
|
// plane + dragged index are captured from React state — setPlaneDrag
|
|
@@ -833,6 +802,91 @@ export const AnnotationCanvasInner = (props) => {
|
|
|
833
802
|
const nmy = c.fy + (c.my - c.fy) * shapeResizeScale.value.sy;
|
|
834
803
|
return Math.abs(nmy - c.fy) + SELECTION_PAD * 2;
|
|
835
804
|
});
|
|
805
|
+
// Black crosshair marking the DRAGGED POINT inside the lens — every
|
|
806
|
+
// precision drag the loupe shows, not a fixed center mark: the lens center
|
|
807
|
+
// is the FINGER, which sits off the dragged point by the grab offset the
|
|
808
|
+
// drags deliberately preserve, so a center mark pointed at the wrong pixel
|
|
809
|
+
// (doubly wrong at 2×). Built in SCREEN space and drawn as lens chrome
|
|
810
|
+
// inside the clip (see loupeWrap), so its size is fixed pixels: the point
|
|
811
|
+
// projects through the same math as loupeTransform —
|
|
812
|
+
// lensCenter + MAG · (screen(point) − finger). Each branch is a one-line
|
|
813
|
+
// mirror of that drag's worklet twin above; 'center' covers the pointer-path
|
|
814
|
+
// drag-to-draw tools, whose tip IS the finger (no grab offset). The mode is
|
|
815
|
+
// React state captured at drag start — set before the loupe mounts.
|
|
816
|
+
const loupeCrossMode = planeDrag
|
|
817
|
+
? 'plane'
|
|
818
|
+
: epDragId || shapeEpDragId
|
|
819
|
+
? 'endpoint'
|
|
820
|
+
: rectDragId
|
|
821
|
+
? 'rect-corner'
|
|
822
|
+
: shapeResizeId
|
|
823
|
+
? 'shape-corner'
|
|
824
|
+
: resizingId
|
|
825
|
+
? 'text-resize'
|
|
826
|
+
: 'center';
|
|
827
|
+
const loupeCrossPath = useDerivedValue(() => {
|
|
828
|
+
'worklet';
|
|
829
|
+
const path = Skia.Path.Make();
|
|
830
|
+
let x = loupeCx;
|
|
831
|
+
let y = loupeCy;
|
|
832
|
+
if (loupeCrossMode !== 'center') {
|
|
833
|
+
let wx = 0;
|
|
834
|
+
let wy = 0;
|
|
835
|
+
if (loupeCrossMode === 'plane') {
|
|
836
|
+
if (planeDragMode.value !== 1)
|
|
837
|
+
return path;
|
|
838
|
+
const p = planeDragHandle.value;
|
|
839
|
+
wx = p.x;
|
|
840
|
+
wy = p.y;
|
|
841
|
+
}
|
|
842
|
+
else if (loupeCrossMode === 'endpoint') {
|
|
843
|
+
// Measurement-line and shape line/arrow endpoint drags both stage
|
|
844
|
+
// their line in epCtx; the grabbed end follows the finger.
|
|
845
|
+
const c = epCtx.value;
|
|
846
|
+
wx = (c.handle === 0 ? c.ax : c.bx) + dragX.value;
|
|
847
|
+
wy = (c.handle === 0 ? c.ay : c.by) + dragY.value;
|
|
848
|
+
}
|
|
849
|
+
else if (loupeCrossMode === 'rect-corner') {
|
|
850
|
+
const c = rectCtx.value;
|
|
851
|
+
wx = c.mx + dragX.value;
|
|
852
|
+
wy = c.my + dragY.value;
|
|
853
|
+
}
|
|
854
|
+
else if (loupeCrossMode === 'shape-corner') {
|
|
855
|
+
// The grabbed corner under the live (clamped, possibly uniform)
|
|
856
|
+
// scale — matches shapeResizeScale, so ellipses mark the true corner.
|
|
857
|
+
const c = shapeResizeCtx.value;
|
|
858
|
+
const s = shapeResizeScale.value;
|
|
859
|
+
wx = c.fx + (c.mx - c.fx) * s.sx;
|
|
860
|
+
wy = c.fy + (c.my - c.fy) * s.sy;
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
// WORKLET TWIN of resizeTransform's clamped scale above: the corner
|
|
864
|
+
// handle under scale-about-pivot.
|
|
865
|
+
const c = resizeCtx.value;
|
|
866
|
+
const bx = c.hx - c.px;
|
|
867
|
+
const by = c.hy - c.py;
|
|
868
|
+
const baseLen = Math.sqrt(bx * bx + by * by);
|
|
869
|
+
let s = 1;
|
|
870
|
+
if (baseLen > 0) {
|
|
871
|
+
const nx = bx + dragX.value;
|
|
872
|
+
const ny = by + dragY.value;
|
|
873
|
+
s = Math.sqrt(nx * nx + ny * ny) / baseLen;
|
|
874
|
+
}
|
|
875
|
+
s = Math.min(c.maxS, Math.max(c.minS, s));
|
|
876
|
+
wx = c.px + bx * s;
|
|
877
|
+
wy = c.py + by * s;
|
|
878
|
+
}
|
|
879
|
+
const sx = (wx - panX.value) * zoom.value;
|
|
880
|
+
const sy = (wy - panY.value) * zoom.value;
|
|
881
|
+
x = loupeCx + LOUPE_MAGNIFICATION * (sx - magTouchX.value);
|
|
882
|
+
y = loupeCy + LOUPE_MAGNIFICATION * (sy - magTouchY.value);
|
|
883
|
+
}
|
|
884
|
+
path.moveTo(x - LOUPE_CROSS_ARM_PX, y);
|
|
885
|
+
path.lineTo(x + LOUPE_CROSS_ARM_PX, y);
|
|
886
|
+
path.moveTo(x, y - LOUPE_CROSS_ARM_PX);
|
|
887
|
+
path.lineTo(x, y + LOUPE_CROSS_ARM_PX);
|
|
888
|
+
return path;
|
|
889
|
+
}, [loupeCx, loupeCy, loupeCrossMode]);
|
|
836
890
|
// Per-gesture refs so we always emit a matching down/move/up sequence.
|
|
837
891
|
const pointerIdRef = useRef(1);
|
|
838
892
|
const inFlightRef = useRef(null);
|
|
@@ -2007,16 +2061,17 @@ export const AnnotationCanvasInner = (props) => {
|
|
|
2007
2061
|
...skiaProps,
|
|
2008
2062
|
worldTransform: loupeTransform,
|
|
2009
2063
|
wrapContent: loupeWrap,
|
|
2010
|
-
//
|
|
2011
|
-
//
|
|
2012
|
-
//
|
|
2013
|
-
//
|
|
2014
|
-
|
|
2015
|
-
|
|
2064
|
+
// Inside the lens only the CONTENT magnifies; chrome doesn't.
|
|
2065
|
+
// Handle discs don't render at all (handleRadius undefined gates
|
|
2066
|
+
// every Handle/plane-disc draw) — the black crosshair drawn in
|
|
2067
|
+
// the lens chrome (loupeCrossPath) marks the dragged point, and
|
|
2068
|
+
// at 2× a disc just covered the pixel being placed. Plane
|
|
2069
|
+
// outlines and measurement lines drop to their normal apparent
|
|
2070
|
+
// thickness instead of doubling.
|
|
2071
|
+
handleRadius: undefined,
|
|
2072
|
+
handleRingWidth: undefined,
|
|
2016
2073
|
planeOutlineScale: 1 / LOUPE_MAGNIFICATION,
|
|
2017
|
-
|
|
2018
|
-
// lens chrome (loupeCrossPath) instead of its disc.
|
|
2019
|
-
planeDragHandleHidden: true,
|
|
2074
|
+
measurementLineScale: 1 / LOUPE_MAGNIFICATION,
|
|
2020
2075
|
}) }))] }));
|
|
2021
2076
|
};
|
|
2022
2077
|
const MeasurementStampOverlayItem = ({ placed, measurement, selected, dragging, sliding, endpointDragging, rectResizing, zoomSnapshot, zoom, panX, panY, dragX, dragY, slideCtx, epCtx, rectCtx, planeEdgeDragging, planeTileCtx, planeDragTX, planeDragTY, renderMeasurementStamp, tileScaleFactor, headerTileScaleFactor, fileTileScaleFactor, tileViewportScale, onStampPress, onStampLongPress, onRemove, }) => {
|
|
@@ -100,10 +100,10 @@ export interface AnnotationCanvasSkiaProps {
|
|
|
100
100
|
};
|
|
101
101
|
planeDragHandle?: AnimatedPoint;
|
|
102
102
|
planeOutlineScale?: number;
|
|
103
|
-
|
|
103
|
+
measurementLineScale?: number;
|
|
104
104
|
customPreview?: ReactNode;
|
|
105
105
|
wrapContent?: (content: ReactNode) => ReactNode;
|
|
106
106
|
canvasRef?: RefObject<CanvasRef | null>;
|
|
107
107
|
}
|
|
108
|
-
export declare const AnnotationCanvasSkia: ({ width, height, effectiveCanvas, worldTransform, viewport, resolveImageUrl, backgroundSkImages, backgroundContent, valueFont, textFontMgr, penDrawingStroke, livePreview, shapePreview, draggingId, dragTransform, resizingId, resizeTransform, selectedId, endpointDragId, shapeEndpointDragId, liveLineP1, liveLineP2, rectDragId, liveRect, shapeResizeId, shapeResizePath, shapeResizeBox, handleRadius, handleRingWidth, showPlaneHandles, planeDragId, planeDragIndex, planeDragPath, planeDragGridPath, planeDragHandle, planeOutlineScale,
|
|
108
|
+
export declare const AnnotationCanvasSkia: ({ width, height, effectiveCanvas, worldTransform, viewport, resolveImageUrl, backgroundSkImages, backgroundContent, valueFont, textFontMgr, penDrawingStroke, livePreview, shapePreview, draggingId, dragTransform, resizingId, resizeTransform, selectedId, endpointDragId, shapeEndpointDragId, liveLineP1, liveLineP2, rectDragId, liveRect, shapeResizeId, shapeResizePath, shapeResizeBox, handleRadius, handleRingWidth, showPlaneHandles, planeDragId, planeDragIndex, planeDragPath, planeDragGridPath, planeDragHandle, planeOutlineScale, measurementLineScale, customPreview, wrapContent, canvasRef, }: AnnotationCanvasSkiaProps) => import("react/jsx-runtime").JSX.Element;
|
|
109
109
|
export {};
|
|
@@ -80,7 +80,7 @@ const SelectionBox = ({ bounds, isDragging, transform, }) => (_jsx(DraggableElem
|
|
|
80
80
|
// since the function-call pattern works identically on native we use it
|
|
81
81
|
// in both Inners for consistency. Don't add hooks here; this is a plain
|
|
82
82
|
// JSX-returning helper, not a component.
|
|
83
|
-
export const AnnotationCanvasSkia = ({ width, height, effectiveCanvas, worldTransform, viewport, resolveImageUrl, backgroundSkImages, backgroundContent, valueFont, textFontMgr, penDrawingStroke, livePreview, shapePreview, draggingId, dragTransform, resizingId, resizeTransform, selectedId, endpointDragId, shapeEndpointDragId, liveLineP1, liveLineP2, rectDragId, liveRect, shapeResizeId, shapeResizePath, shapeResizeBox, handleRadius, handleRingWidth, showPlaneHandles, planeDragId, planeDragIndex, planeDragPath, planeDragGridPath, planeDragHandle, planeOutlineScale = 1,
|
|
83
|
+
export const AnnotationCanvasSkia = ({ width, height, effectiveCanvas, worldTransform, viewport, resolveImageUrl, backgroundSkImages, backgroundContent, valueFont, textFontMgr, penDrawingStroke, livePreview, shapePreview, draggingId, dragTransform, resizingId, resizeTransform, selectedId, endpointDragId, shapeEndpointDragId, liveLineP1, liveLineP2, rectDragId, liveRect, shapeResizeId, shapeResizePath, shapeResizeBox, handleRadius, handleRingWidth, showPlaneHandles, planeDragId, planeDragIndex, planeDragPath, planeDragGridPath, planeDragHandle, planeOutlineScale = 1, measurementLineScale = 1, customPreview, wrapContent, canvasRef, }) => {
|
|
84
84
|
// Doc rect a SCALE-mode plane grid covers: the first background layer (the
|
|
85
85
|
// photo being calibrated), else the document rect. Pinned to layer 0 like
|
|
86
86
|
// the tile-sizing reference — adding a second image must not re-span the
|
|
@@ -100,9 +100,7 @@ export const AnnotationCanvasSkia = ({ width, height, effectiveCanvas, worldTran
|
|
|
100
100
|
? plane.corners
|
|
101
101
|
: [plane.refLine.a, plane.refLine.b];
|
|
102
102
|
return (_jsxs(Group, { children: [planeDragGridPath && (_jsx(Path, { path: planeDragGridPath, color: PLANE_GRID_COLOR, style: "stroke", strokeWidth: PLANE_GRID_WIDTH, opacity: PLANE_GRID_OPACITY })), _jsx(Path, { path: planeDragPath, color: PLANE_CHROME_COLOR, style: "stroke", strokeWidth: PLANE_OUTLINE_WIDTH * planeOutlineScale, strokeJoin: "round" }), handleRadius != null &&
|
|
103
|
-
statics.map((p, i) => i === planeDragIndex ? null : (_jsxs(Group, { children: [_jsx(Circle, { c: p, r: handleRadius, color: PLANE_CHROME_COLOR }), _jsx(Circle, { c: p, r: handleRadius, color: "#FFFFFF", style: "stroke", strokeWidth: handleRingWidth })] }, i))), handleRadius != null &&
|
|
104
|
-
planeDragHandle &&
|
|
105
|
-
!planeDragHandleHidden && (_jsxs(_Fragment, { children: [_jsx(Circle, { c: planeDragHandle, r: handleRadius, color: PLANE_CHROME_COLOR }), _jsx(Circle, { c: planeDragHandle, r: handleRadius, color: "#FFFFFF", style: "stroke", strokeWidth: handleRingWidth })] }))] }, plane.id));
|
|
103
|
+
statics.map((p, i) => i === planeDragIndex ? null : (_jsxs(Group, { children: [_jsx(Circle, { c: p, r: handleRadius, color: PLANE_CHROME_COLOR }), _jsx(Circle, { c: p, r: handleRadius, color: "#FFFFFF", style: "stroke", strokeWidth: handleRingWidth })] }, i))), handleRadius != null && planeDragHandle && (_jsxs(_Fragment, { children: [_jsx(Circle, { c: planeDragHandle, r: handleRadius, color: PLANE_CHROME_COLOR }), _jsx(Circle, { c: planeDragHandle, r: handleRadius, color: "#FFFFFF", style: "stroke", strokeWidth: handleRingWidth })] }))] }, plane.id));
|
|
106
104
|
}
|
|
107
105
|
return (_jsx(PlaneElement, { plane: plane, scaleBounds: planeScaleBounds, showHandles: showPlaneHandles === true, handleRadius: showPlaneHandles ? handleRadius : undefined, handleRingWidth: showPlaneHandles ? handleRingWidth : undefined, outlineScale: planeOutlineScale }, plane.id));
|
|
108
106
|
}), effectiveCanvas.strokes.map((stroke) => (_jsx(DraggableElement, { isDragging: stroke.id === draggingId, transform: dragTransform, children: _jsx(StrokeElement, { stroke: stroke }) }, stroke.id))), effectiveCanvas.shapes.map((shape) => {
|
|
@@ -183,7 +181,7 @@ export const AnnotationCanvasSkia = ({ width, height, effectiveCanvas, worldTran
|
|
|
183
181
|
const p1 = isEndpointDrag && liveLineP1 ? liveLineP1 : placed.line.a;
|
|
184
182
|
const p2 = isEndpointDrag && liveLineP2 ? liveLineP2 : placed.line.b;
|
|
185
183
|
const lineColor = placed.lineColor ?? MEASUREMENT_LINE_COLOR;
|
|
186
|
-
const lineWidth = placed.lineWidth ?? MEASUREMENT_LINE_WIDTH;
|
|
184
|
+
const lineWidth = (placed.lineWidth ?? MEASUREMENT_LINE_WIDTH) * measurementLineScale;
|
|
187
185
|
// Solid filled-triangle arrowheads at endpoint b (the "end", lineCap)
|
|
188
186
|
// and/or endpoint a (the "start", lineStartCap). Built from the static
|
|
189
187
|
// endpoints, so they're skipped during a live endpoint drag (they
|
|
@@ -451,6 +451,7 @@ export interface Label extends FirestoreDoc, Timestamps {
|
|
|
451
451
|
* the matching print-settings selector (measurement/QR/image) instead of
|
|
452
452
|
* the public label library. Absent/null = ordinary library label. */
|
|
453
453
|
templateType?: 'measurement' | 'qr' | 'image' | null;
|
|
454
|
+
starred?: boolean;
|
|
454
455
|
}
|
|
455
456
|
export interface LabelRow {
|
|
456
457
|
id: string;
|
|
@@ -603,6 +604,11 @@ export interface UserDocument extends FirestoreDoc, Timestamps {
|
|
|
603
604
|
* shared across orgs, so the star can't live on the template doc (that's
|
|
604
605
|
* `Template.starred`, for the org's own templates). */
|
|
605
606
|
starredPublicTemplateIds?: string[];
|
|
607
|
+
/** Public labels this user starred in the label library. Same reasoning as
|
|
608
|
+
* `starredPublicTemplateIds`: public labels are shared across orgs, so the
|
|
609
|
+
* star can't live on the label doc (that's `Label.starred`, for the org's
|
|
610
|
+
* own labels). */
|
|
611
|
+
starredPublicLabelIds?: string[];
|
|
606
612
|
}
|
|
607
613
|
export interface UserComment extends FirestoreDoc, Timestamps {
|
|
608
614
|
comment: string;
|