@reekon-tools/boldr-utils 1.6.31 → 1.6.33

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 (71) hide show
  1. package/dist/annotation/canvas/tools/measurementTool.d.ts +6 -1
  2. package/dist/annotation/canvas/tools/measurementTool.js +34 -1
  3. package/dist/annotation/canvas/useAnnotationCanvasState.d.ts +1 -0
  4. package/dist/annotation/canvas/useAnnotationCanvasState.js +35 -28
  5. package/dist/canvas/AnnotationCanvas.d.ts +11 -0
  6. package/dist/canvas/AnnotationCanvas.js +10 -0
  7. package/dist/canvas/AnnotationCanvas.native.d.ts +8 -0
  8. package/dist/canvas/AnnotationCanvas.native.js +6 -0
  9. package/dist/canvas/AnnotationCanvasInner.d.ts +39 -0
  10. package/dist/canvas/AnnotationCanvasInner.js +219 -0
  11. package/dist/canvas/AnnotationCanvasInner.native.d.ts +35 -0
  12. package/dist/canvas/AnnotationCanvasInner.native.js +138 -0
  13. package/dist/canvas/AnnotationCanvasSkia.d.ts +27 -0
  14. package/dist/canvas/AnnotationCanvasSkia.js +20 -0
  15. package/dist/canvas/Tool.d.ts +38 -0
  16. package/dist/canvas/Tool.js +1 -0
  17. package/dist/canvas/elements/BackgroundImageElement.d.ts +9 -0
  18. package/dist/canvas/elements/BackgroundImageElement.js +37 -0
  19. package/dist/canvas/elements/MeasurementStampElement.d.ts +13 -0
  20. package/dist/canvas/elements/MeasurementStampElement.js +30 -0
  21. package/dist/canvas/elements/ShapeElement.d.ts +7 -0
  22. package/dist/canvas/elements/ShapeElement.js +62 -0
  23. package/dist/canvas/elements/StrokeElement.d.ts +7 -0
  24. package/dist/canvas/elements/StrokeElement.js +18 -0
  25. package/dist/canvas/measurementPicker.d.ts +10 -0
  26. package/dist/canvas/measurementPicker.js +1 -0
  27. package/dist/canvas/measurementStampOverlay.d.ts +11 -0
  28. package/dist/canvas/measurementStampOverlay.js +1 -0
  29. package/dist/canvas/pointerAdapter.d.ts +3 -0
  30. package/dist/canvas/pointerAdapter.js +19 -0
  31. package/dist/canvas/stampLayout.d.ts +5 -0
  32. package/dist/canvas/stampLayout.js +14 -0
  33. package/dist/canvas/tools/measurementStampTool.d.ts +9 -0
  34. package/dist/canvas/tools/measurementStampTool.js +37 -0
  35. package/dist/canvas/tools/panTool.d.ts +5 -0
  36. package/dist/canvas/tools/panTool.js +25 -0
  37. package/dist/canvas/tools/penTool.d.ts +13 -0
  38. package/dist/canvas/tools/penTool.js +68 -0
  39. package/dist/canvas/tools/selectTool.d.ts +2 -0
  40. package/dist/canvas/tools/selectTool.js +182 -0
  41. package/dist/canvas/useAnnotationCanvasState.d.ts +54 -0
  42. package/dist/canvas/useAnnotationCanvasState.js +210 -0
  43. package/dist/canvas/viewport.d.ts +16 -0
  44. package/dist/canvas/viewport.js +54 -0
  45. package/dist/data/AnnotationDataContext.d.ts +8 -0
  46. package/dist/data/AnnotationDataContext.js +11 -0
  47. package/dist/data/AnnotationDataProvider.d.ts +65 -0
  48. package/dist/data/AnnotationDataProvider.js +4 -0
  49. package/dist/data/InMemoryAnnotationProvider.d.ts +30 -0
  50. package/dist/data/InMemoryAnnotationProvider.js +197 -0
  51. package/dist/data/canvasPersistence.d.ts +3 -0
  52. package/dist/data/canvasPersistence.js +26 -0
  53. package/dist/data/hooks/useAnnotationCanvasDoc.d.ts +33 -0
  54. package/dist/data/hooks/useAnnotationCanvasDoc.js +314 -0
  55. package/dist/data/hooks/useAnnotationDoc.d.ts +7 -0
  56. package/dist/data/hooks/useAnnotationDoc.js +33 -0
  57. package/dist/data/hooks/useAnnotationList.d.ts +7 -0
  58. package/dist/data/hooks/useAnnotationList.js +26 -0
  59. package/dist/data/hooks/useAnnotationMutations.d.ts +9 -0
  60. package/dist/data/hooks/useAnnotationMutations.js +11 -0
  61. package/dist/exports.d.ts +1 -0
  62. package/dist/exports.js +1 -0
  63. package/dist/hooks/useParseMeasurement.d.ts +4 -0
  64. package/dist/hooks/useParseMeasurement.js +14 -0
  65. package/dist/utils/evaluateFormula.d.ts +20 -0
  66. package/dist/utils/evaluateFormula.js +31 -0
  67. package/dist/utils/selectValues.d.ts +3 -0
  68. package/dist/utils/selectValues.js +17 -0
  69. package/package.json +1 -1
  70. package/dist/annotation/canvas/tools/measurementLineTool.d.ts +0 -12
  71. package/dist/annotation/canvas/tools/measurementLineTool.js +0 -95
package/dist/exports.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from './types/annotation.js';
9
9
  export { getToleranceColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, type ToleranceThreshold, type ToleranceConfig, } from './utils/tolerance.js';
10
10
  export { DEFAULT_GROUP_INDEX, isDefaultGroup, findDefaultGroup, } from './utils/groups.js';
11
11
  export { numberToLetterIndex, formGroupInputLabel, listGroupMeasurementLabel, } from './utils/indexLabels.js';
12
+ export { toSelectedValues, formatSelectedValues, toStoredValue, } from './utils/selectValues.js';
12
13
  export { annotationScopeKey, isFieldOp, isTemplateScope, type AnnotationDataProvider, type AnnotationFile, type AnnotationFilePatch, type AnnotationFileSummary, type AnnotationScope, type FieldOp, type ImageBlob, type JobGroupScope, type JobScope, type Patch, type TemplateScope, type Unsubscribe, type UploadedImageRef, } from './annotation/data/AnnotationDataProvider.js';
13
14
  export { AnnotationDataProviderContext, useAnnotationData, type AnnotationDataProviderProps, } from './annotation/data/AnnotationDataContext.js';
14
15
  export { useAnnotationDoc, type UseAnnotationDocResult, } from './annotation/data/hooks/useAnnotationDoc.js';
package/dist/exports.js CHANGED
@@ -13,6 +13,7 @@ export * from './types/annotation.js';
13
13
  export { getToleranceColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, } from './utils/tolerance.js';
14
14
  export { DEFAULT_GROUP_INDEX, isDefaultGroup, findDefaultGroup, } from './utils/groups.js';
15
15
  export { numberToLetterIndex, formGroupInputLabel, listGroupMeasurementLabel, } from './utils/indexLabels.js';
16
+ export { toSelectedValues, formatSelectedValues, toStoredValue, } from './utils/selectValues.js';
16
17
  // Annotation data layer (SDK-neutral; apps provide their own provider).
17
18
  export { annotationScopeKey, isFieldOp, isTemplateScope, } from './annotation/data/AnnotationDataProvider.js';
18
19
  export { AnnotationDataProviderContext, useAnnotationData, } from './annotation/data/AnnotationDataContext.js';
@@ -0,0 +1,4 @@
1
+ export declare const useParseMeasurement: () => {
2
+ parseMeasurementInput: (input: string, defaultUnit?: string) => number | null;
3
+ error: string | null;
4
+ };
@@ -0,0 +1,14 @@
1
+ import { useState } from 'react';
2
+ import { parseMeasurement } from '../utils/parseMeasurement.js';
3
+ export const useParseMeasurement = () => {
4
+ const [error, setError] = useState(null);
5
+ const parseMeasurementInput = (input, defaultUnit = 'mm') => {
6
+ setError(null);
7
+ const result = parseMeasurement(input, defaultUnit);
8
+ if (result === null) {
9
+ setError('Invalid measurement. Please provide a valid number and unit.');
10
+ }
11
+ return result;
12
+ };
13
+ return { parseMeasurementInput, error };
14
+ };
@@ -0,0 +1,20 @@
1
+ type MeasurementMap = Map<string, {
2
+ id: string;
3
+ value: number;
4
+ }[]>;
5
+ interface FormulaEvaluationOptions {
6
+ expression: string;
7
+ mappings: Record<string, string>;
8
+ group: {
9
+ id: string;
10
+ columns: Map<string, any>;
11
+ };
12
+ columns: {
13
+ id: string;
14
+ type: string;
15
+ }[];
16
+ measurementMap: MeasurementMap;
17
+ defaultUnit?: string;
18
+ }
19
+ export declare function evaluateFormula({ expression, mappings, group, columns, measurementMap, defaultUnit, }: FormulaEvaluationOptions): number | string;
20
+ export {};
@@ -0,0 +1,31 @@
1
+ import { create, all } from 'mathjs';
2
+ const math = create(all);
3
+ export function evaluateFormula({ expression, mappings, group, columns, measurementMap, defaultUnit = 'um', }) {
4
+ const scope = {};
5
+ for (const [variable, columnId] of Object.entries(mappings)) {
6
+ const rawValue = group.columns.get(columnId);
7
+ const columnDef = columns.find((c) => c.id === columnId);
8
+ if (columnDef?.type === 'Measurement') {
9
+ const groupMeasurements = measurementMap.get(group.id) || [];
10
+ const measurement = groupMeasurements.find((m) => m.id === rawValue);
11
+ if (measurement?.value !== undefined) {
12
+ scope[variable] = math.unit(measurement.value, defaultUnit);
13
+ continue;
14
+ }
15
+ }
16
+ const parsedValue = typeof rawValue === 'number' ? rawValue : parseFloat(rawValue || '');
17
+ scope[variable] = isNaN(parsedValue) ? 0 : parsedValue;
18
+ }
19
+ try {
20
+ const compiled = math.compile(expression);
21
+ const result = compiled.evaluate(scope);
22
+ if (math.typeOf(result) === 'Unit') {
23
+ return result.toNumber(defaultUnit);
24
+ }
25
+ return result;
26
+ }
27
+ catch (err) {
28
+ console.error(`Formula evaluation failed:`, err);
29
+ return 'Error';
30
+ }
31
+ }
@@ -0,0 +1,3 @@
1
+ export declare const toSelectedValues: (value: unknown) => string[];
2
+ export declare const formatSelectedValues: (value: unknown) => string;
3
+ export declare const toStoredValue: (values: string[]) => string[] | "";
@@ -0,0 +1,17 @@
1
+ // Multi-select cell value helpers, shared by rock-desktop and rock-pro-app.
2
+ //
3
+ // Multi-select column cells (group.columns[columnId] / fileData.columns[...])
4
+ // hold string[] when filled, but legacy cells — and the backend's section
5
+ // initialization — hold plain strings or ''. An EMPTY selection is stored as
6
+ // '' — never [] — because completion checks compare against '' (most
7
+ // critically the backend's updateProgress, which counts `columns[id] !== ""`
8
+ // toward job progress; an empty array would falsely count as filled).
9
+ // Normalize a stored cell value to the list of selected options. A legacy
10
+ // plain string (e.g. after a singleSelect → multiSelect type switch) becomes
11
+ // a one-element selection.
12
+ export const toSelectedValues = (value) => Array.isArray(value) ? value.map(String) : value ? [String(value)] : [];
13
+ // Human-readable form of a selection: "A, B". Identity for non-empty plain
14
+ // strings, '' for empty values — safe to use on any non-measurement cell.
15
+ export const formatSelectedValues = (value) => toSelectedValues(value).join(', ');
16
+ // Encode a selection for storage: the array when non-empty, '' when empty.
17
+ export const toStoredValue = (values) => values.length > 0 ? values : '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reekon-tools/boldr-utils",
3
- "version": "1.6.31",
3
+ "version": "1.6.33",
4
4
  "description": "Shared utilities for formulas and measurement conversion used in Reekon apps",
5
5
  "author": "REEKON Tools",
6
6
  "license": "MIT",
@@ -1,12 +0,0 @@
1
- import type { PlacedMeasurementRef } from '../../../types/annotation.js';
2
- import type { Tool } from '../Tool.js';
3
- export interface MeasurementLineToolOptions {
4
- id?: string;
5
- label?: string;
6
- minDragPx?: number;
7
- autoSwitchToSelect?: boolean;
8
- selectToolId?: string;
9
- onAutoSwitch?: (toToolId: string) => void;
10
- onPlaced?: (measurement: PlacedMeasurementRef) => void;
11
- }
12
- export declare const createMeasurementLineTool: (options?: MeasurementLineToolOptions) => Tool;
@@ -1,95 +0,0 @@
1
- import { DEFAULT_LAYER_ID } from '../../../types/annotation.js';
2
- import { DEFAULT_LINE_POS, recomputeAnchor } from '../measurementGeometry.js';
3
- let counter = 0;
4
- const makeId = () => `annotation-${Date.now().toString(36)}-${(counter++).toString(36)}`;
5
- const firstLayerId = (doc) => doc.layers[0]?.id ?? DEFAULT_LAYER_ID;
6
- // Build the blank line-measurement annotation for a drag from `a` to `b`: a
7
- // 2-point line with a value tile magnetized to its center (linePos 0.5). The
8
- // payload mirrors useAnnotationCanvasState's placeAnnotationAtCenter so a drawn
9
- // line and a (legacy) center-placed one are byte-identical once committed.
10
- const buildLineMeasurement = (opts) => {
11
- const line = { a: opts.a, b: opts.b };
12
- return {
13
- id: opts.id,
14
- layerId: opts.layerId,
15
- placement: 'line',
16
- line,
17
- linePos: DEFAULT_LINE_POS,
18
- // Center of the line; recomputeAnchor keeps this in sync on edits.
19
- anchor: recomputeAnchor(line, 'line', DEFAULT_LINE_POS, {
20
- x: (opts.a.x + opts.b.x) / 2,
21
- y: (opts.a.y + opts.b.y) / 2,
22
- }),
23
- showLabel: true,
24
- showValue: true,
25
- createdAt: Date.now(),
26
- };
27
- };
28
- // Drag-to-draw measurement-line tool. Press-drag rubber-bands a measurement
29
- // annotation (a line with a blank value tile at its center); release commits
30
- // it. Mirrors createShapeTool's interaction so "input lines" are placed the
31
- // same way as shapes — draw to add, not tap-the-icon-to-add — replacing the
32
- // old center-place affordance. The annotation stays blank (no measurement
33
- // associated) until the user fills it via the tile / picker. Skia-free, like
34
- // every tool factory; it renders its live preview through ctx.preview, so it
35
- // works on web and (via the generic tool-pan dispatch) on native.
36
- export const createMeasurementLineTool = (options = {}) => {
37
- const minDragPx = options.minDragPx ?? 4;
38
- const autoSwitchToSelect = options.autoSwitchToSelect ?? true;
39
- const selectToolId = options.selectToolId ?? 'select';
40
- return {
41
- id: options.id ?? 'measure-line',
42
- label: options.label ?? 'Measurement line',
43
- cursor: 'crosshair',
44
- onPointerDown(event) {
45
- return {
46
- kind: 'measurement-line-drawing',
47
- id: makeId(),
48
- startWorld: event.world,
49
- startScreen: event.screen,
50
- moved: false,
51
- };
52
- },
53
- onPointerMove(event, ctx, state) {
54
- const s = state;
55
- if (s?.kind !== 'measurement-line-drawing')
56
- return s;
57
- const measurement = buildLineMeasurement({
58
- id: s.id,
59
- layerId: firstLayerId(ctx.document),
60
- a: s.startWorld,
61
- b: event.world,
62
- });
63
- ctx.preview({ ops: [{ op: 'addMeasurement', measurement }] });
64
- return { ...s, moved: true };
65
- },
66
- onPointerUp(event, ctx, state) {
67
- const s = state;
68
- if (s?.kind !== 'measurement-line-drawing')
69
- return;
70
- const dx = event.screen.x - s.startScreen.x;
71
- const dy = event.screen.y - s.startScreen.y;
72
- if (!s.moved || dx * dx + dy * dy < minDragPx * minDragPx) {
73
- // Accidental tap — discard the rubber-band, commit nothing.
74
- ctx.preview({ ops: [] });
75
- return;
76
- }
77
- const measurement = buildLineMeasurement({
78
- id: s.id,
79
- layerId: firstLayerId(ctx.document),
80
- a: s.startWorld,
81
- b: event.world,
82
- });
83
- ctx.commit({ ops: [{ op: 'addMeasurement', measurement }] });
84
- // Leave it selected (and hand back to select) so the blank line can be
85
- // filled / moved straight away — the same flow as the text tool.
86
- ctx.setSelection({ ids: [measurement.id] });
87
- options.onPlaced?.(measurement);
88
- if (autoSwitchToSelect)
89
- options.onAutoSwitch?.(selectToolId);
90
- },
91
- onCancel(_state, ctx) {
92
- ctx.preview({ ops: [] });
93
- },
94
- };
95
- };