@reekon-tools/boldr-utils 1.6.12 → 1.6.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 (41) hide show
  1. package/dist/annotation/canvas/AnnotationCanvas.native.d.ts +2 -2
  2. package/dist/annotation/canvas/AnnotationCanvasInner.d.ts +5 -2
  3. package/dist/annotation/canvas/AnnotationCanvasInner.js +58 -6
  4. package/dist/annotation/canvas/AnnotationCanvasInner.native.d.ts +5 -2
  5. package/dist/annotation/canvas/AnnotationCanvasInner.native.js +514 -59
  6. package/dist/annotation/canvas/AnnotationCanvasSkia.d.ts +31 -1
  7. package/dist/annotation/canvas/AnnotationCanvasSkia.js +38 -9
  8. package/dist/annotation/canvas/Tool.d.ts +27 -0
  9. package/dist/annotation/canvas/elements/BackgroundImageElement.js +4 -1
  10. package/dist/annotation/canvas/elements/ShapeElement.js +68 -9
  11. package/dist/annotation/canvas/elements/StrokeElement.js +8 -3
  12. package/dist/annotation/canvas/measurementGeometry.d.ts +21 -0
  13. package/dist/annotation/canvas/measurementGeometry.js +98 -3
  14. package/dist/annotation/canvas/shapeGeometry.d.ts +5 -0
  15. package/dist/annotation/canvas/shapeGeometry.js +116 -0
  16. package/dist/annotation/canvas/strokeGeometry.d.ts +1 -0
  17. package/dist/annotation/canvas/strokeGeometry.js +8 -0
  18. package/dist/annotation/canvas/textGeometry.d.ts +24 -0
  19. package/dist/annotation/canvas/textGeometry.js +110 -0
  20. package/dist/annotation/canvas/tools/panTool.d.ts +1 -0
  21. package/dist/annotation/canvas/tools/panTool.js +38 -5
  22. package/dist/annotation/canvas/tools/penTool.d.ts +1 -0
  23. package/dist/annotation/canvas/tools/penTool.js +8 -2
  24. package/dist/annotation/canvas/tools/polygonTool.d.ts +11 -0
  25. package/dist/annotation/canvas/tools/polygonTool.js +162 -0
  26. package/dist/annotation/canvas/tools/selectTool.js +148 -51
  27. package/dist/annotation/canvas/tools/shapeTool.d.ts +25 -0
  28. package/dist/annotation/canvas/tools/shapeTool.js +111 -0
  29. package/dist/annotation/canvas/tools/textTool.d.ts +12 -0
  30. package/dist/annotation/canvas/tools/textTool.js +78 -0
  31. package/dist/annotation/canvas/useAnnotationCanvasState.d.ts +2 -1
  32. package/dist/annotation/canvas/useAnnotationCanvasState.js +56 -6
  33. package/dist/annotation/data/coalescedRunner.d.ts +1 -0
  34. package/dist/annotation/data/coalescedRunner.js +48 -0
  35. package/dist/annotation/data/hooks/useAnnotationCanvasDoc.js +118 -38
  36. package/dist/exports.d.ts +9 -4
  37. package/dist/exports.js +8 -3
  38. package/dist/formulas/calculateFormula.js +1 -3
  39. package/dist/types/annotation.d.ts +9 -0
  40. package/dist/types/firestore.d.ts +4 -0
  41. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import type { AnnotationCanvasInnerProps } from './AnnotationCanvasInner.native.js';
2
- export type { AnnotationCanvasHandle, } from './useAnnotationCanvasState.js';
3
- export type { GestureConfig, PanTrigger, } from './AnnotationCanvasInner.js';
2
+ export type { AnnotationCanvasHandle } from './useAnnotationCanvasState.js';
3
+ export type { GestureConfig, PanTrigger } from './AnnotationCanvasInner.js';
4
4
  export type AnnotationCanvasProps = AnnotationCanvasInnerProps & {
5
5
  fallback?: unknown;
6
6
  canvasKitOpts?: unknown;
@@ -1,8 +1,8 @@
1
1
  import { type CSSProperties, type MutableRefObject } from 'react';
2
2
  import type { DecimalTolerance, FractionalTolerance, Measurement, Units } from '../../types/firestore.js';
3
- import type { AnnotationCanvasState, AnnotationDocumentPatch, Selection } from '../../types/annotation.js';
3
+ import type { AnnotationCanvasState, AnnotationDocumentPatch, PlacedMeasurementRef, Selection } from '../../types/annotation.js';
4
4
  import type { MeasurementRef } from './measurementPicker.js';
5
- import type { Tool } from './Tool.js';
5
+ import type { RequestTextInput, Tool } from './Tool.js';
6
6
  import { type AnnotationCanvasHandle } from './useAnnotationCanvasState.js';
7
7
  import { type ViewportState } from './viewport.js';
8
8
  import type { RenderMeasurementStamp } from './measurementStampOverlay.js';
@@ -20,7 +20,10 @@ export interface AnnotationCanvasInnerProps {
20
20
  decimalTolerance?: DecimalTolerance;
21
21
  resolveImageUrl?: (storagePath: string) => Promise<string>;
22
22
  pickMeasurement?: () => Promise<MeasurementRef | null>;
23
+ requestTextInput?: RequestTextInput;
23
24
  renderMeasurementStamp?: RenderMeasurementStamp;
25
+ onMeasurementStampPress?: (placed: PlacedMeasurementRef) => void;
26
+ onMeasurementStampLongPress?: (placed: PlacedMeasurementRef) => void;
24
27
  stampFontSource?: unknown;
25
28
  stampValueFontSize?: number;
26
29
  stampLabelFontSize?: number;
@@ -55,7 +55,10 @@ export const AnnotationCanvasInner = (props) => {
55
55
  y: event.clientY - (rect?.top ?? 0),
56
56
  };
57
57
  if (isPanTriggerDown(event)) {
58
- panGestureRef.current = { pointerId: event.pointerId, lastScreen: screen };
58
+ panGestureRef.current = {
59
+ pointerId: event.pointerId,
60
+ lastScreen: screen,
61
+ };
59
62
  event.currentTarget.setPointerCapture(event.pointerId);
60
63
  event.preventDefault();
61
64
  return;
@@ -75,7 +78,10 @@ export const AnnotationCanvasInner = (props) => {
75
78
  x: screen.x - pan.lastScreen.x,
76
79
  y: screen.y - pan.lastScreen.y,
77
80
  });
78
- panGestureRef.current = { pointerId: pan.pointerId, lastScreen: screen };
81
+ panGestureRef.current = {
82
+ pointerId: pan.pointerId,
83
+ lastScreen: screen,
84
+ };
79
85
  return;
80
86
  }
81
87
  state.dispatchPointerMove(toCanvasPointer(event));
@@ -165,7 +171,7 @@ export const AnnotationCanvasInner = (props) => {
165
171
  ...style,
166
172
  };
167
173
  const customPreview = activeTool?.renderPreview?.(state.customPreviewState, state.ctx);
168
- const { renderMeasurementStamp, selection } = props;
174
+ const { renderMeasurementStamp, onMeasurementStampPress, onMeasurementStampLongPress, selection, } = props;
169
175
  return (_jsxs("div", { ref: containerRef, style: containerStyle, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onPointerCancel: handlePointerCancel, onWheel: handleWheel, onContextMenu: handleContextMenu, children: [AnnotationCanvasSkia({
170
176
  width,
171
177
  height,
@@ -177,8 +183,13 @@ export const AnnotationCanvasInner = (props) => {
177
183
  // Endpoint handles on the selected line annotation. Web drives endpoint
178
184
  // drag through selectTool's pointer handlers (preview patches update the
179
185
  // line, so the handles follow via re-render); no live geometry needed.
186
+ // Handles are drag affordances — suppressed unless the active tool can
187
+ // act on them (view mode's pan tool selects measurements but must not
188
+ // advertise draggability).
180
189
  selectedId: selection?.ids[0] ?? null,
181
- handleRadius: HANDLE_PX / state.viewport.zoom,
190
+ handleRadius: activeTool?.dragSelection
191
+ ? HANDLE_PX / state.viewport.zoom
192
+ : undefined,
182
193
  customPreview,
183
194
  }), renderMeasurementStamp && (_jsx("div", { style: {
184
195
  position: 'absolute',
@@ -190,7 +201,7 @@ export const AnnotationCanvasInner = (props) => {
190
201
  const cy = (placed.anchor.y - state.viewport.pan.y) * state.viewport.zoom;
191
202
  const isSelected = selection?.ids.includes(placed.id) ?? false;
192
203
  const measurement = placed.measurementId
193
- ? state.measurementsById.get(placed.measurementId) ?? null
204
+ ? (state.measurementsById.get(placed.measurementId) ?? null)
194
205
  : null;
195
206
  return (_jsxs("div", { style: {
196
207
  position: 'absolute',
@@ -205,7 +216,9 @@ export const AnnotationCanvasInner = (props) => {
205
216
  selected: isSelected,
206
217
  size,
207
218
  zoom: state.viewport.zoom,
208
- }), isSelected && measurement && (_jsx("div", { role: "button", "aria-label": "Remove measurement", onPointerDown: (e) => {
219
+ }), onMeasurementStampPress && (_jsx(StampPressTarget, { onPress: () => onMeasurementStampPress(placed), onLongPress: onMeasurementStampLongPress
220
+ ? () => onMeasurementStampLongPress(placed)
221
+ : undefined })), isSelected && measurement && (_jsx("div", { role: "button", "aria-label": "Remove measurement", onPointerDown: (e) => {
209
222
  e.stopPropagation();
210
223
  const { ops, keepSelection } = buildRemoveMeasurementOps(placed);
211
224
  state.ctx.commit({ ops });
@@ -222,3 +235,42 @@ export const AnnotationCanvasInner = (props) => {
222
235
  } }))] }, placed.id));
223
236
  }) }))] }));
224
237
  };
238
+ // Whole-tile press target for the stamp overlay. The DOM has no native
239
+ // long-press, so it's derived: pointerdown arms a timer; if it fires before
240
+ // the pointer lifts (or leaves/cancels), the long-press callback runs and the
241
+ // trailing click is swallowed. Mirrors the native overlay's TouchableOpacity
242
+ // onPress/onLongPress semantics (500ms, RN's default delayLongPress).
243
+ const LONG_PRESS_MS = 500;
244
+ const StampPressTarget = ({ onPress, onLongPress, }) => {
245
+ const timerRef = useRef(null);
246
+ const longPressFiredRef = useRef(false);
247
+ const clearTimer = () => {
248
+ if (timerRef.current != null) {
249
+ clearTimeout(timerRef.current);
250
+ timerRef.current = null;
251
+ }
252
+ };
253
+ return (_jsx("button", { "aria-label": "Open measurement", onPointerDown: (e) => {
254
+ e.stopPropagation();
255
+ longPressFiredRef.current = false;
256
+ if (onLongPress) {
257
+ clearTimer();
258
+ timerRef.current = setTimeout(() => {
259
+ timerRef.current = null;
260
+ longPressFiredRef.current = true;
261
+ onLongPress();
262
+ }, LONG_PRESS_MS);
263
+ }
264
+ }, onPointerUp: clearTimer, onPointerLeave: clearTimer, onPointerCancel: clearTimer, onClick: () => {
265
+ if (!longPressFiredRef.current)
266
+ onPress();
267
+ }, style: {
268
+ position: 'absolute',
269
+ inset: 0,
270
+ pointerEvents: 'auto',
271
+ cursor: 'pointer',
272
+ background: 'transparent',
273
+ border: 'none',
274
+ padding: 0,
275
+ } }));
276
+ };
@@ -2,9 +2,9 @@ import { type MutableRefObject } from 'react';
2
2
  import { type ViewStyle } from 'react-native';
3
3
  import type { RenderMeasurementStamp } from './measurementStampOverlay.js';
4
4
  import type { DecimalTolerance, FractionalTolerance, Measurement, Units } from '../../types/firestore.js';
5
- import { type AnnotationCanvasState, type AnnotationDocumentPatch, type Selection } from '../../types/annotation.js';
5
+ import { type AnnotationCanvasState, type AnnotationDocumentPatch, type PlacedMeasurementRef, type Selection } from '../../types/annotation.js';
6
6
  import type { MeasurementRef } from './measurementPicker.js';
7
- import type { Tool } from './Tool.js';
7
+ import type { RequestTextInput, Tool } from './Tool.js';
8
8
  import { type AnnotationCanvasHandle } from './useAnnotationCanvasState.js';
9
9
  import type { ViewportState } from './viewport.js';
10
10
  export type { AnnotationCanvasHandle };
@@ -21,7 +21,10 @@ export interface AnnotationCanvasInnerProps {
21
21
  decimalTolerance?: DecimalTolerance;
22
22
  resolveImageUrl?: (storagePath: string) => Promise<string>;
23
23
  pickMeasurement?: () => Promise<MeasurementRef | null>;
24
+ requestTextInput?: RequestTextInput;
24
25
  renderMeasurementStamp?: RenderMeasurementStamp;
26
+ onMeasurementStampPress?: (placed: PlacedMeasurementRef) => void;
27
+ onMeasurementStampLongPress?: (placed: PlacedMeasurementRef) => void;
25
28
  stampFontSource?: unknown;
26
29
  stampValueFontSize?: number;
27
30
  stampLabelFontSize?: number;