@reekon-tools/boldr-utils 1.6.32 → 1.6.34

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.
@@ -19,6 +19,14 @@ const computeContentFit = (canvas, width, height) => {
19
19
  : { x: 0, y: 0, width: viewport.width, height: viewport.height };
20
20
  return fitRectToScreen(rect, width, height);
21
21
  };
22
+ // Default leader length (doc units) for a placed measurement when no explicit
23
+ // length is given. A generous fraction of the document width, clamped, so the
24
+ // leader — and its draggable endcaps — stay clear of the fixed-size value tile
25
+ // at typical full-fit zoom (Asana 1216212322376723: leaders were collapsing
26
+ // under the tile). The tile is screen-constant while the line is doc-space, so
27
+ // this can't guarantee clearance on very large drawings (the clamp caps the
28
+ // length) or at extreme zoom-out — zoom in to grab the endcaps there.
29
+ const defaultLeaderLenDoc = (docWidth) => Math.min(800, Math.max(240, docWidth * 0.45));
22
30
  // Platform-agnostic state machine for the annotation canvas. Web and native
23
31
  // inners share this hook; each wraps it with platform-specific event
24
32
  // capture and JSX (div + DOM events vs. GestureDetector + RN Views).
@@ -205,7 +213,7 @@ export const useAnnotationCanvasState = (props) => {
205
213
  return;
206
214
  let line = m.line;
207
215
  if (!line) {
208
- const len = Math.min(400, Math.max(120, canvas.viewport.width * 0.25));
216
+ const len = defaultLeaderLenDoc(canvas.viewport.width);
209
217
  line = {
210
218
  a: { x: m.anchor.x - len / 2, y: m.anchor.y },
211
219
  b: { x: m.anchor.x + len / 2, y: m.anchor.y },
@@ -286,10 +294,9 @@ export const useAnnotationCanvasState = (props) => {
286
294
  x: width / 2,
287
295
  y: height / 2,
288
296
  });
289
- // Default line length: a quarter of the doc width, clamped to a sane
290
- // range so it's a grabbable size at any canvas scale.
291
- const len = opts?.defaultLengthDoc ??
292
- Math.min(400, Math.max(120, canvas.viewport.width * 0.25));
297
+ // Default line length: a generous fraction of the doc width, clamped,
298
+ // so the leader and its endcaps clear the fixed-size tile at full-fit.
299
+ const len = opts?.defaultLengthDoc ?? defaultLeaderLenDoc(canvas.viewport.width);
293
300
  const line = {
294
301
  a: { x: center.x - len / 2, y: center.y },
295
302
  b: { x: center.x + len / 2, y: center.y },
@@ -318,7 +325,7 @@ export const useAnnotationCanvasState = (props) => {
318
325
  // Reuse the existing rect if the annotation had one; otherwise
319
326
  // synthesize a square centered on the anchor (same size clamp as
320
327
  // the default line) so the tile doesn't jump.
321
- const side = Math.min(400, Math.max(120, canvas.viewport.width * 0.25));
328
+ const side = defaultLeaderLenDoc(canvas.viewport.width);
322
329
  const rect = m.rect ?? {
323
330
  a: { x: m.anchor.x - side / 2, y: m.anchor.y - side / 2 },
324
331
  b: { x: m.anchor.x + side / 2, y: m.anchor.y + side / 2 },
@@ -341,7 +348,7 @@ export const useAnnotationCanvasState = (props) => {
341
348
  if (type === 'line') {
342
349
  let line = m.line;
343
350
  if (!line) {
344
- const len = Math.min(400, Math.max(120, canvas.viewport.width * 0.25));
351
+ const len = defaultLeaderLenDoc(canvas.viewport.width);
345
352
  line = {
346
353
  a: { x: m.anchor.x - len / 2, y: m.anchor.y },
347
354
  b: { x: m.anchor.x + len / 2, y: m.anchor.y },
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,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.32",
3
+ "version": "1.6.34",
4
4
  "description": "Shared utilities for formulas and measurement conversion used in Reekon apps",
5
5
  "author": "REEKON Tools",
6
6
  "license": "MIT",