@reekon-tools/boldr-utils 1.11.0 → 1.13.0
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.
- package/dist/annotation/canvas/AnnotationCanvasInner.native.js +48 -7
- package/dist/annotation/canvas/AnnotationCanvasSkia.d.ts +2 -2
- package/dist/annotation/canvas/AnnotationCanvasSkia.js +16 -3
- package/dist/annotation/canvas/Tool.d.ts +8 -1
- package/dist/annotation/canvas/backgroundLayers.d.ts +20 -0
- package/dist/annotation/canvas/backgroundLayers.js +98 -0
- package/dist/annotation/canvas/elements/BackgroundImageElement.d.ts +10 -7
- package/dist/annotation/canvas/elements/BackgroundImageElement.js +45 -11
- package/dist/annotation/canvas/elements/BackgroundSvg.d.ts +3 -4
- package/dist/annotation/canvas/elements/BackgroundSvg.js +23 -29
- package/dist/annotation/canvas/elements/backgroundUrl.js +2 -2
- package/dist/annotation/canvas/groupHeaderLayout.d.ts +72 -0
- package/dist/annotation/canvas/groupHeaderLayout.js +115 -0
- package/dist/annotation/canvas/stampLayout.d.ts +15 -2
- package/dist/annotation/canvas/stampLayout.js +46 -12
- package/dist/annotation/canvas/tools/selectTool.js +183 -19
- package/dist/annotation/canvas/useAnnotationCanvasState.d.ts +1 -0
- package/dist/annotation/canvas/useAnnotationCanvasState.js +40 -20
- package/dist/annotation/canvas/viewport.js +7 -6
- package/dist/annotation/data/AnnotationDataProvider.d.ts +1 -1
- package/dist/annotation/data/InMemoryAnnotationProvider.d.ts +1 -1
- package/dist/annotation/data/hooks/useAnnotationCanvasDoc.d.ts +7 -1
- package/dist/annotation/data/hooks/useAnnotationCanvasDoc.js +124 -22
- package/dist/annotation/data/hooks/useAnnotationMutations.d.ts +1 -1
- package/dist/canvas/AnnotationCanvas.d.ts +11 -0
- package/dist/canvas/AnnotationCanvas.js +10 -0
- package/dist/canvas/AnnotationCanvas.native.d.ts +8 -0
- package/dist/canvas/AnnotationCanvas.native.js +6 -0
- package/dist/canvas/AnnotationCanvasInner.d.ts +39 -0
- package/dist/canvas/AnnotationCanvasInner.js +219 -0
- package/dist/canvas/AnnotationCanvasInner.native.d.ts +35 -0
- package/dist/canvas/AnnotationCanvasInner.native.js +138 -0
- package/dist/canvas/AnnotationCanvasSkia.d.ts +27 -0
- package/dist/canvas/AnnotationCanvasSkia.js +20 -0
- package/dist/canvas/Tool.d.ts +38 -0
- package/dist/canvas/Tool.js +1 -0
- package/dist/canvas/elements/BackgroundImageElement.d.ts +9 -0
- package/dist/canvas/elements/BackgroundImageElement.js +37 -0
- package/dist/canvas/elements/MeasurementStampElement.d.ts +13 -0
- package/dist/canvas/elements/MeasurementStampElement.js +30 -0
- package/dist/canvas/elements/ShapeElement.d.ts +7 -0
- package/dist/canvas/elements/ShapeElement.js +62 -0
- package/dist/canvas/elements/StrokeElement.d.ts +7 -0
- package/dist/canvas/elements/StrokeElement.js +18 -0
- package/dist/canvas/measurementPicker.d.ts +10 -0
- package/dist/canvas/measurementPicker.js +1 -0
- package/dist/canvas/measurementStampOverlay.d.ts +11 -0
- package/dist/canvas/measurementStampOverlay.js +1 -0
- package/dist/canvas/pointerAdapter.d.ts +3 -0
- package/dist/canvas/pointerAdapter.js +19 -0
- package/dist/canvas/stampLayout.d.ts +5 -0
- package/dist/canvas/stampLayout.js +14 -0
- package/dist/canvas/tools/measurementStampTool.d.ts +9 -0
- package/dist/canvas/tools/measurementStampTool.js +37 -0
- package/dist/canvas/tools/panTool.d.ts +5 -0
- package/dist/canvas/tools/panTool.js +25 -0
- package/dist/canvas/tools/penTool.d.ts +13 -0
- package/dist/canvas/tools/penTool.js +68 -0
- package/dist/canvas/tools/selectTool.d.ts +2 -0
- package/dist/canvas/tools/selectTool.js +182 -0
- package/dist/canvas/useAnnotationCanvasState.d.ts +54 -0
- package/dist/canvas/useAnnotationCanvasState.js +210 -0
- package/dist/canvas/viewport.d.ts +16 -0
- package/dist/canvas/viewport.js +54 -0
- package/dist/data/AnnotationDataContext.d.ts +8 -0
- package/dist/data/AnnotationDataContext.js +11 -0
- package/dist/data/AnnotationDataProvider.d.ts +65 -0
- package/dist/data/AnnotationDataProvider.js +4 -0
- package/dist/data/InMemoryAnnotationProvider.d.ts +30 -0
- package/dist/data/InMemoryAnnotationProvider.js +197 -0
- package/dist/data/canvasPersistence.d.ts +3 -0
- package/dist/data/canvasPersistence.js +26 -0
- package/dist/data/hooks/useAnnotationCanvasDoc.d.ts +33 -0
- package/dist/data/hooks/useAnnotationCanvasDoc.js +314 -0
- package/dist/data/hooks/useAnnotationDoc.d.ts +7 -0
- package/dist/data/hooks/useAnnotationDoc.js +33 -0
- package/dist/data/hooks/useAnnotationList.d.ts +7 -0
- package/dist/data/hooks/useAnnotationList.js +26 -0
- package/dist/data/hooks/useAnnotationMutations.d.ts +9 -0
- package/dist/data/hooks/useAnnotationMutations.js +11 -0
- package/dist/exports.d.ts +3 -1
- package/dist/exports.js +3 -1
- package/dist/hooks/useParseMeasurement.d.ts +4 -0
- package/dist/hooks/useParseMeasurement.js +14 -0
- package/dist/types/annotation.d.ts +28 -0
- package/dist/types/annotation.js +68 -0
- package/dist/utils/evaluateFormula.d.ts +20 -0
- package/dist/utils/evaluateFormula.js +31 -0
- package/package.json +1 -1
- package/dist/theme/index.d.ts +0 -3
- package/dist/theme/index.js +0 -3
- package/dist/theme/preset.d.ts +0 -120
- package/dist/theme/preset.js +0 -25
- package/dist/theme/semantic.d.ts +0 -136
- package/dist/theme/semantic.js +0 -116
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AnnotationFile, ImageBlob, JobGroupScope, Patch, UploadedImageRef } from '../AnnotationDataProvider.js';
|
|
2
|
+
export interface AnnotationMutations {
|
|
3
|
+
create(seed: Partial<AnnotationFile>): Promise<string>;
|
|
4
|
+
update(fileId: string, patch: Patch<AnnotationFile>): Promise<void>;
|
|
5
|
+
remove(fileId: string): Promise<void>;
|
|
6
|
+
uploadImage(fileId: string, role: 'background' | 'thumbnail', blob: ImageBlob): Promise<UploadedImageRef>;
|
|
7
|
+
deleteImage(fileId: string, storagePath: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export declare const useAnnotationMutations: (scope: JobGroupScope) => AnnotationMutations;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
import { useAnnotationData } from '../AnnotationDataContext.js';
|
|
3
|
+
export const useAnnotationMutations = (scope) => {
|
|
4
|
+
const provider = useAnnotationData();
|
|
5
|
+
const create = useCallback((seed) => provider.create(scope, seed), [provider, scope.orgId, scope.projectId, scope.jobId, scope.groupId]);
|
|
6
|
+
const update = useCallback((fileId, patch) => provider.update(scope, fileId, patch), [provider, scope.orgId, scope.projectId, scope.jobId, scope.groupId]);
|
|
7
|
+
const remove = useCallback((fileId) => provider.delete(scope, fileId), [provider, scope.orgId, scope.projectId, scope.jobId, scope.groupId]);
|
|
8
|
+
const uploadImage = useCallback((fileId, role, blob) => provider.uploadImage(scope, fileId, role, blob), [provider, scope.orgId, scope.projectId, scope.jobId, scope.groupId]);
|
|
9
|
+
const deleteImage = useCallback((fileId, storagePath) => provider.deleteImage(scope, fileId, storagePath), [provider, scope.orgId, scope.projectId, scope.jobId, scope.groupId]);
|
|
10
|
+
return useMemo(() => ({ create, update, remove, uploadImage, deleteImage }), [create, update, remove, uploadImage, deleteImage]);
|
|
11
|
+
};
|
package/dist/exports.d.ts
CHANGED
|
@@ -29,8 +29,10 @@ export type { GestureConfig, PanTrigger, AnnotationCanvasInnerProps, } from './a
|
|
|
29
29
|
export type { CanvasPointerEvent, RequestTextInput, ShapeDrawConfig, Tool, ToolContext, ToolState, } from './annotation/canvas/Tool.js';
|
|
30
30
|
export type { MeasurementRef, PickMeasurement, } from './annotation/canvas/measurementPicker.js';
|
|
31
31
|
export type { MeasurementStampRenderArgs, RenderMeasurementStamp, } from './annotation/canvas/measurementStampOverlay.js';
|
|
32
|
-
export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, DEFAULT_TILE_SCALE, TILE_SCALE_MIN, TILE_SCALE_MAX, clampTileScale, resolveTileScaleFactor, tileDocSizeForFactor, tileScaleFromDocSize, stampTileSize, stampTileDims, isUnassociatedStamp, type StampTileDims, } from './annotation/canvas/stampLayout.js';
|
|
32
|
+
export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, GROUP_HEADER_COLLAPSED_WIDTH, GROUP_HEADER_COLLAPSED_HEIGHT, GROUP_HEADER_DESIGN, groupHeaderBaseDims, DEFAULT_TILE_SCALE, TILE_SCALE_MIN, TILE_SCALE_MAX, clampTileScale, resolveTileScaleFactor, tileDocSizeForFactor, tileScaleFromDocSize, stampTileSize, stampTileDims, isUnassociatedStamp, type StampTileDims, } from './annotation/canvas/stampLayout.js';
|
|
33
|
+
export { GROUP_HEADER_STYLE, describeGroupHeader, groupHeaderSignature, type GroupHeaderBadge, type GroupHeaderDescriptor, } from './annotation/canvas/groupHeaderLayout.js';
|
|
33
34
|
export { createViewportApi, fitToScreen, fitRectToScreen, imageDocRect, panBy, zoomAt, DEFAULT_VIEWPORT, type ViewportApi, type ViewportState, } from './annotation/canvas/viewport.js';
|
|
35
|
+
export { LEGACY_BACKGROUND_LAYER_ID, BACKGROUND_PLACEMENT_GAP_RATIO, backgroundLayersOf, backgroundLayerDocRect, backgroundLayersUnionRect, placeNewBackgroundLayer, } from './annotation/canvas/backgroundLayers.js';
|
|
34
36
|
export { createPenTool, type PenToolOptions, } from './annotation/canvas/tools/penTool.js';
|
|
35
37
|
export { createSelectTool, type SelectToolOptions, } from './annotation/canvas/tools/selectTool.js';
|
|
36
38
|
export { createMeasurementStampTool, type MeasurementStampToolOptions, } from './annotation/canvas/tools/measurementStampTool.js';
|
package/dist/exports.js
CHANGED
|
@@ -34,8 +34,10 @@ export { useAnnotationMutations, } from './annotation/data/hooks/useAnnotationMu
|
|
|
34
34
|
export { useAnnotationCanvasDoc, } from './annotation/data/hooks/useAnnotationCanvasDoc.js';
|
|
35
35
|
export { hydrateCanvasState } from './annotation/data/canvasPersistence.js';
|
|
36
36
|
export { InMemoryAnnotationProvider } from './annotation/data/InMemoryAnnotationProvider.js';
|
|
37
|
-
export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, DEFAULT_TILE_SCALE, TILE_SCALE_MIN, TILE_SCALE_MAX, clampTileScale, resolveTileScaleFactor, tileDocSizeForFactor, tileScaleFromDocSize, stampTileSize, stampTileDims, isUnassociatedStamp, } from './annotation/canvas/stampLayout.js';
|
|
37
|
+
export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, GROUP_HEADER_COLLAPSED_WIDTH, GROUP_HEADER_COLLAPSED_HEIGHT, GROUP_HEADER_DESIGN, groupHeaderBaseDims, DEFAULT_TILE_SCALE, TILE_SCALE_MIN, TILE_SCALE_MAX, clampTileScale, resolveTileScaleFactor, tileDocSizeForFactor, tileScaleFromDocSize, stampTileSize, stampTileDims, isUnassociatedStamp, } from './annotation/canvas/stampLayout.js';
|
|
38
|
+
export { GROUP_HEADER_STYLE, describeGroupHeader, groupHeaderSignature, } from './annotation/canvas/groupHeaderLayout.js';
|
|
38
39
|
export { createViewportApi, fitToScreen, fitRectToScreen, imageDocRect, panBy, zoomAt, DEFAULT_VIEWPORT, } from './annotation/canvas/viewport.js';
|
|
40
|
+
export { LEGACY_BACKGROUND_LAYER_ID, BACKGROUND_PLACEMENT_GAP_RATIO, backgroundLayersOf, backgroundLayerDocRect, backgroundLayersUnionRect, placeNewBackgroundLayer, } from './annotation/canvas/backgroundLayers.js';
|
|
39
41
|
export { createPenTool, } from './annotation/canvas/tools/penTool.js';
|
|
40
42
|
export { createSelectTool, } from './annotation/canvas/tools/selectTool.js';
|
|
41
43
|
export { createMeasurementStampTool, } from './annotation/canvas/tools/measurementStampTool.js';
|
|
@@ -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
|
+
};
|
|
@@ -54,6 +54,7 @@ export interface PlacedMeasurementRef {
|
|
|
54
54
|
groupId?: string;
|
|
55
55
|
columnId?: string;
|
|
56
56
|
isGroupHeader?: boolean;
|
|
57
|
+
collapsed?: boolean;
|
|
57
58
|
anchor: Vec2;
|
|
58
59
|
placement?: MeasurementPlacement;
|
|
59
60
|
line?: {
|
|
@@ -96,11 +97,27 @@ export interface AnnotationBackgroundImage {
|
|
|
96
97
|
heightPx: number;
|
|
97
98
|
format?: 'raster' | 'svg';
|
|
98
99
|
}
|
|
100
|
+
export interface BackgroundLayerTransform {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
scaleX: number;
|
|
104
|
+
scaleY: number;
|
|
105
|
+
}
|
|
106
|
+
export interface AnnotationBackgroundLayer {
|
|
107
|
+
id: AnnotationElementId;
|
|
108
|
+
storagePath: string;
|
|
109
|
+
downloadUrl: string;
|
|
110
|
+
widthPx: number;
|
|
111
|
+
heightPx: number;
|
|
112
|
+
format?: 'raster' | 'svg';
|
|
113
|
+
transform: BackgroundLayerTransform;
|
|
114
|
+
}
|
|
99
115
|
export interface AnnotationViewport {
|
|
100
116
|
width: number;
|
|
101
117
|
height: number;
|
|
102
118
|
backgroundImage?: AnnotationBackgroundImage;
|
|
103
119
|
backgroundFit?: BackgroundFit;
|
|
120
|
+
backgroundImages?: AnnotationBackgroundLayer[];
|
|
104
121
|
}
|
|
105
122
|
export type TileScalePlatform = 'web' | 'mobile';
|
|
106
123
|
export interface AnnotationCanvasState {
|
|
@@ -155,6 +172,17 @@ export type AnnotationPatchOp = {
|
|
|
155
172
|
} | {
|
|
156
173
|
op: 'removeMeasurement';
|
|
157
174
|
id: AnnotationElementId;
|
|
175
|
+
} | {
|
|
176
|
+
op: 'addBackgroundImage';
|
|
177
|
+
image: AnnotationBackgroundLayer;
|
|
178
|
+
index?: number;
|
|
179
|
+
} | {
|
|
180
|
+
op: 'updateBackgroundImage';
|
|
181
|
+
id: AnnotationElementId;
|
|
182
|
+
patch: Partial<Omit<AnnotationBackgroundLayer, 'id'>>;
|
|
183
|
+
} | {
|
|
184
|
+
op: 'removeBackgroundImage';
|
|
185
|
+
id: AnnotationElementId;
|
|
158
186
|
} | {
|
|
159
187
|
op: 'setViewport';
|
|
160
188
|
patch: Partial<AnnotationViewport>;
|
package/dist/types/annotation.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { backgroundLayersOf } from '../annotation/canvas/backgroundLayers.js';
|
|
1
2
|
export const DEFAULT_LAYER_ID = 'default';
|
|
2
3
|
export const createDefaultLayer = () => ({
|
|
3
4
|
id: DEFAULT_LAYER_ID,
|
|
@@ -20,11 +21,40 @@ export const createEmptyCanvasState = (viewport) => ({
|
|
|
20
21
|
...(viewport?.backgroundFit !== undefined
|
|
21
22
|
? { backgroundFit: viewport.backgroundFit }
|
|
22
23
|
: {}),
|
|
24
|
+
...(viewport?.backgroundImages !== undefined
|
|
25
|
+
? { backgroundImages: viewport.backgroundImages }
|
|
26
|
+
: {}),
|
|
23
27
|
},
|
|
24
28
|
strokes: [],
|
|
25
29
|
shapes: [],
|
|
26
30
|
placedMeasurements: [],
|
|
27
31
|
});
|
|
32
|
+
// Layer 0 projected into the legacy single-slot shape. The transform is
|
|
33
|
+
// dropped — old clients draw the legacy field fit-centered, an accepted
|
|
34
|
+
// degradation. `format` is included only when defined so the mirror survives
|
|
35
|
+
// the write path's JSON round-trip without changing shape.
|
|
36
|
+
const legacyBackgroundOf = (layer) => ({
|
|
37
|
+
storagePath: layer.storagePath,
|
|
38
|
+
downloadUrl: layer.downloadUrl,
|
|
39
|
+
widthPx: layer.widthPx,
|
|
40
|
+
heightPx: layer.heightPx,
|
|
41
|
+
...(layer.format ? { format: layer.format } : {}),
|
|
42
|
+
});
|
|
43
|
+
// Every background mutation lands here: it writes the (already-normalized)
|
|
44
|
+
// layer array and mirrors layer 0 into the legacy slot, so old clients —
|
|
45
|
+
// which read only `backgroundImage` and rewrite the whole canvas on save —
|
|
46
|
+
// keep rendering the first image instead of persisting its loss. An empty
|
|
47
|
+
// stack sets BOTH fields to explicit `undefined`: the write path's JSON
|
|
48
|
+
// round-trip strips those keys (Firestore rejects undefined values).
|
|
49
|
+
// `backgroundFit` is left alone — it belongs to the legacy render path.
|
|
50
|
+
const withBackgroundLayers = (state, layers) => ({
|
|
51
|
+
...state,
|
|
52
|
+
viewport: {
|
|
53
|
+
...state.viewport,
|
|
54
|
+
backgroundImages: layers.length > 0 ? layers : undefined,
|
|
55
|
+
backgroundImage: layers.length > 0 ? legacyBackgroundOf(layers[0]) : undefined,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
28
58
|
// Apply an in-memory patch to a canvas state. Pure — returns a new object.
|
|
29
59
|
// Used by the canvas reducer and by InMemoryAnnotationProvider; consumers
|
|
30
60
|
// can also call this when they receive a patch from the canvas to compute
|
|
@@ -71,6 +101,22 @@ const applyOp = (state, op) => {
|
|
|
71
101
|
...state,
|
|
72
102
|
placedMeasurements: state.placedMeasurements.filter((m) => m.id !== op.id),
|
|
73
103
|
};
|
|
104
|
+
case 'addBackgroundImage': {
|
|
105
|
+
const layers = backgroundLayersOf(state.viewport);
|
|
106
|
+
// Clamp so a stale index (e.g. an undo replayed after a concurrent
|
|
107
|
+
// removal) can never create a sparse array — a hole becomes `null`
|
|
108
|
+
// through the write path's JSON round-trip and corrupts the doc.
|
|
109
|
+
const index = Math.max(0, Math.min(op.index ?? layers.length, layers.length));
|
|
110
|
+
return withBackgroundLayers(state, [
|
|
111
|
+
...layers.slice(0, index),
|
|
112
|
+
op.image,
|
|
113
|
+
...layers.slice(index),
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
case 'updateBackgroundImage':
|
|
117
|
+
return withBackgroundLayers(state, backgroundLayersOf(state.viewport).map((l) => l.id === op.id ? { ...l, ...op.patch } : l));
|
|
118
|
+
case 'removeBackgroundImage':
|
|
119
|
+
return withBackgroundLayers(state, backgroundLayersOf(state.viewport).filter((l) => l.id !== op.id));
|
|
74
120
|
case 'setViewport':
|
|
75
121
|
return { ...state, viewport: { ...state.viewport, ...op.patch } };
|
|
76
122
|
case 'setTileScaleFactor':
|
|
@@ -148,6 +194,28 @@ const invertOp = (before, op) => {
|
|
|
148
194
|
}
|
|
149
195
|
return { op: 'updateMeasurement', id: op.id, patch: inversePatch };
|
|
150
196
|
}
|
|
197
|
+
case 'addBackgroundImage':
|
|
198
|
+
return { op: 'removeBackgroundImage', id: op.image.id };
|
|
199
|
+
case 'removeBackgroundImage': {
|
|
200
|
+
// Invert against the NORMALIZED stack: the before-state may hold only
|
|
201
|
+
// the legacy single field (the op being inverted is what materialized
|
|
202
|
+
// the array), and undo must still restore that layer — at its index.
|
|
203
|
+
const layers = backgroundLayersOf(before.viewport);
|
|
204
|
+
const index = layers.findIndex((l) => l.id === op.id);
|
|
205
|
+
return index >= 0
|
|
206
|
+
? { op: 'addBackgroundImage', image: layers[index], index }
|
|
207
|
+
: null;
|
|
208
|
+
}
|
|
209
|
+
case 'updateBackgroundImage': {
|
|
210
|
+
const prev = backgroundLayersOf(before.viewport).find((l) => l.id === op.id);
|
|
211
|
+
if (!prev)
|
|
212
|
+
return null;
|
|
213
|
+
const inversePatch = {};
|
|
214
|
+
for (const k of Object.keys(op.patch)) {
|
|
215
|
+
inversePatch[k] = prev[k];
|
|
216
|
+
}
|
|
217
|
+
return { op: 'updateBackgroundImage', id: op.id, patch: inversePatch };
|
|
218
|
+
}
|
|
151
219
|
case 'setViewport': {
|
|
152
220
|
const inversePatch = {};
|
|
153
221
|
for (const k of Object.keys(op.patch)) {
|
|
@@ -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
|
+
}
|
package/package.json
CHANGED
package/dist/theme/index.d.ts
DELETED
package/dist/theme/index.js
DELETED
package/dist/theme/preset.d.ts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared Tailwind preset. COLORS ONLY, by design.
|
|
3
|
-
*
|
|
4
|
-
* Must never define `content`, `plugins`, `presets`, or `darkMode`:
|
|
5
|
-
* NativeWind recurses `config.presets[].presets` hunting for its own marker
|
|
6
|
-
* preset, and a `content` key here would silently narrow the consuming app's
|
|
7
|
-
* globs.
|
|
8
|
-
*
|
|
9
|
-
* Consumed from CJS Tailwind configs, so this is a NAMED export with no
|
|
10
|
-
* default — that keeps ESM/CJS interop semantics irrelevant:
|
|
11
|
-
*
|
|
12
|
-
* const { boldrPreset } = require('@reekon-tools/boldr-utils/theme/preset');
|
|
13
|
-
* module.exports = { presets: [require('nativewind/preset'), boldrPreset] };
|
|
14
|
-
*
|
|
15
|
-
* Tailwind loads configs through jiti + sucrase, so requiring this ESM file
|
|
16
|
-
* from a CJS config works regardless of Node version.
|
|
17
|
-
*
|
|
18
|
-
* Note that Tailwind merges `theme.extend` per key with the *app* winning, and
|
|
19
|
-
* replaces a color key wholesale rather than deep-merging. An app that keeps
|
|
20
|
-
* its own `colors.background` will silently shadow this preset.
|
|
21
|
-
*/
|
|
22
|
-
export declare const boldrPreset: {
|
|
23
|
-
theme: {
|
|
24
|
-
extend: {
|
|
25
|
-
colors: {
|
|
26
|
-
background: "#1D1F21";
|
|
27
|
-
foreground: {
|
|
28
|
-
DEFAULT: "#FFFFFF";
|
|
29
|
-
disabled: "#626364";
|
|
30
|
-
};
|
|
31
|
-
card: {
|
|
32
|
-
DEFAULT: "#2B2C2E";
|
|
33
|
-
foreground: "#FFFFFF";
|
|
34
|
-
};
|
|
35
|
-
popover: {
|
|
36
|
-
DEFAULT: "#2B2C2E";
|
|
37
|
-
foreground: "#FFFFFF";
|
|
38
|
-
};
|
|
39
|
-
muted: {
|
|
40
|
-
DEFAULT: "#424345";
|
|
41
|
-
foreground: "#9FA0A2";
|
|
42
|
-
};
|
|
43
|
-
accent: {
|
|
44
|
-
DEFAULT: "#424345";
|
|
45
|
-
foreground: "#FFFFFF";
|
|
46
|
-
};
|
|
47
|
-
secondary: {
|
|
48
|
-
DEFAULT: "#424345";
|
|
49
|
-
foreground: "#FFFFFF";
|
|
50
|
-
};
|
|
51
|
-
border: {
|
|
52
|
-
DEFAULT: "#424345";
|
|
53
|
-
strong: "#626364";
|
|
54
|
-
};
|
|
55
|
-
input: "#424345";
|
|
56
|
-
ring: "#FFAD00";
|
|
57
|
-
primary: {
|
|
58
|
-
DEFAULT: "#FFAD00";
|
|
59
|
-
foreground: "#1D1F21";
|
|
60
|
-
};
|
|
61
|
-
destructive: {
|
|
62
|
-
DEFAULT: "#DF6358";
|
|
63
|
-
foreground: "#1D1F21";
|
|
64
|
-
};
|
|
65
|
-
elevated: {
|
|
66
|
-
DEFAULT: "#424345";
|
|
67
|
-
foreground: "#FFFFFF";
|
|
68
|
-
};
|
|
69
|
-
interactive: {
|
|
70
|
-
DEFAULT: "#0066FF";
|
|
71
|
-
foreground: "#FFFFFF";
|
|
72
|
-
};
|
|
73
|
-
nav: {
|
|
74
|
-
DEFAULT: "#2D3843";
|
|
75
|
-
foreground: "#FFFFFF";
|
|
76
|
-
};
|
|
77
|
-
paper: {
|
|
78
|
-
DEFAULT: "#E8EAED";
|
|
79
|
-
foreground: "#1D1F21";
|
|
80
|
-
field: "#FFFFFF";
|
|
81
|
-
line: "#BCBEC2";
|
|
82
|
-
muted: "#626364";
|
|
83
|
-
};
|
|
84
|
-
tile: {
|
|
85
|
-
foreground: "#FFFFFF";
|
|
86
|
-
measurement: {
|
|
87
|
-
DEFAULT: "#0066FF";
|
|
88
|
-
badge: "#50A6FF";
|
|
89
|
-
};
|
|
90
|
-
formula: {
|
|
91
|
-
DEFAULT: "#BD30A8";
|
|
92
|
-
badge: "#6C155F";
|
|
93
|
-
};
|
|
94
|
-
count: {
|
|
95
|
-
DEFAULT: "#02274B";
|
|
96
|
-
foreground: "#FFFFFF";
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
diagram: {
|
|
100
|
-
1: "#2E4C6A";
|
|
101
|
-
2: "#4B6074";
|
|
102
|
-
3: "#67819A";
|
|
103
|
-
};
|
|
104
|
-
tolerance: {
|
|
105
|
-
in: {
|
|
106
|
-
DEFAULT: "#58A942";
|
|
107
|
-
warning: "#00E920";
|
|
108
|
-
muted: "#8BB380";
|
|
109
|
-
};
|
|
110
|
-
out: {
|
|
111
|
-
DEFAULT: "#E83D2F";
|
|
112
|
-
warning: "#DA1100";
|
|
113
|
-
muted: "#DF6358";
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
};
|
|
119
|
-
};
|
|
120
|
-
export type BoldrPreset = typeof boldrPreset;
|
package/dist/theme/preset.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { boldrColors } from './semantic.js';
|
|
2
|
-
/**
|
|
3
|
-
* Shared Tailwind preset. COLORS ONLY, by design.
|
|
4
|
-
*
|
|
5
|
-
* Must never define `content`, `plugins`, `presets`, or `darkMode`:
|
|
6
|
-
* NativeWind recurses `config.presets[].presets` hunting for its own marker
|
|
7
|
-
* preset, and a `content` key here would silently narrow the consuming app's
|
|
8
|
-
* globs.
|
|
9
|
-
*
|
|
10
|
-
* Consumed from CJS Tailwind configs, so this is a NAMED export with no
|
|
11
|
-
* default — that keeps ESM/CJS interop semantics irrelevant:
|
|
12
|
-
*
|
|
13
|
-
* const { boldrPreset } = require('@reekon-tools/boldr-utils/theme/preset');
|
|
14
|
-
* module.exports = { presets: [require('nativewind/preset'), boldrPreset] };
|
|
15
|
-
*
|
|
16
|
-
* Tailwind loads configs through jiti + sucrase, so requiring this ESM file
|
|
17
|
-
* from a CJS config works regardless of Node version.
|
|
18
|
-
*
|
|
19
|
-
* Note that Tailwind merges `theme.extend` per key with the *app* winning, and
|
|
20
|
-
* replaces a color key wholesale rather than deep-merging. An app that keeps
|
|
21
|
-
* its own `colors.background` will silently shadow this preset.
|
|
22
|
-
*/
|
|
23
|
-
export const boldrPreset = {
|
|
24
|
-
theme: { extend: { colors: boldrColors } },
|
|
25
|
-
};
|
package/dist/theme/semantic.d.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structural shape of a Tailwind `theme.extend.colors` tree.
|
|
3
|
-
*
|
|
4
|
-
* Declared locally on purpose: annotating with tailwindcss's own `Config` type
|
|
5
|
-
* would put `import type { Config } from 'tailwindcss'` into the emitted .d.ts
|
|
6
|
-
* and make tailwindcss a hard type dependency of this package.
|
|
7
|
-
*/
|
|
8
|
-
export type ColorTree = {
|
|
9
|
-
[key: string]: string | ColorTree;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Semantic design tokens — the layer apps actually consume.
|
|
13
|
-
*
|
|
14
|
-
* `colors.ts` is the palette (raw Figma variables, named by value).
|
|
15
|
-
* This file maps those values onto *roles*, and is the only color surface the
|
|
16
|
-
* apps should reference. The raw palette is deliberately NOT exposed as Tailwind
|
|
17
|
-
* classes; naming by value is how both apps accumulated hundreds of arbitrary
|
|
18
|
-
* hex classes in the first place.
|
|
19
|
-
*
|
|
20
|
-
* The shadcn/ui token names (background, card, popover, foreground, muted,
|
|
21
|
-
* accent, secondary, border, input, ring, primary, destructive) are reused
|
|
22
|
-
* rather than paralleled, so every shadcn component is re-skinned without any
|
|
23
|
-
* component edits and `shadcn add` keeps generating markup that lands on these
|
|
24
|
-
* tokens.
|
|
25
|
-
*
|
|
26
|
-
* The design is dark-only. The light calculator / form surfaces are the
|
|
27
|
-
* explicitly-named `paper.*` tokens, not a light/dark variant pair — on native
|
|
28
|
-
* NativeWind's `dark:` variant is global, and portal-rendered surfaces
|
|
29
|
-
* (bottom sheets, dialogs, selects) mount outside any scoped subtree, so a
|
|
30
|
-
* scoped override would leak dark chrome onto a light page.
|
|
31
|
-
*/
|
|
32
|
-
export declare const boldrColors: {
|
|
33
|
-
background: "#1D1F21";
|
|
34
|
-
foreground: {
|
|
35
|
-
DEFAULT: "#FFFFFF";
|
|
36
|
-
disabled: "#626364";
|
|
37
|
-
};
|
|
38
|
-
card: {
|
|
39
|
-
DEFAULT: "#2B2C2E";
|
|
40
|
-
foreground: "#FFFFFF";
|
|
41
|
-
};
|
|
42
|
-
popover: {
|
|
43
|
-
DEFAULT: "#2B2C2E";
|
|
44
|
-
foreground: "#FFFFFF";
|
|
45
|
-
};
|
|
46
|
-
muted: {
|
|
47
|
-
DEFAULT: "#424345";
|
|
48
|
-
foreground: "#9FA0A2";
|
|
49
|
-
};
|
|
50
|
-
accent: {
|
|
51
|
-
DEFAULT: "#424345";
|
|
52
|
-
foreground: "#FFFFFF";
|
|
53
|
-
};
|
|
54
|
-
secondary: {
|
|
55
|
-
DEFAULT: "#424345";
|
|
56
|
-
foreground: "#FFFFFF";
|
|
57
|
-
};
|
|
58
|
-
border: {
|
|
59
|
-
DEFAULT: "#424345";
|
|
60
|
-
strong: "#626364";
|
|
61
|
-
};
|
|
62
|
-
input: "#424345";
|
|
63
|
-
ring: "#FFAD00";
|
|
64
|
-
primary: {
|
|
65
|
-
DEFAULT: "#FFAD00";
|
|
66
|
-
foreground: "#1D1F21";
|
|
67
|
-
};
|
|
68
|
-
destructive: {
|
|
69
|
-
DEFAULT: "#DF6358";
|
|
70
|
-
foreground: "#1D1F21";
|
|
71
|
-
};
|
|
72
|
-
/** Chips, inset controls, thumbnail placeholders. */
|
|
73
|
-
elevated: {
|
|
74
|
-
DEFAULT: "#424345";
|
|
75
|
-
foreground: "#FFFFFF";
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Steppers and other interactive fills. FILL ONLY — #0066FF as text on
|
|
79
|
-
* #2B2C2E is 2.89:1. Never `text-interactive`.
|
|
80
|
-
*/
|
|
81
|
-
interactive: {
|
|
82
|
-
DEFAULT: "#0066FF";
|
|
83
|
-
foreground: "#FFFFFF";
|
|
84
|
-
};
|
|
85
|
-
/** Nav chrome (the web app's sidebar). */
|
|
86
|
-
nav: {
|
|
87
|
-
DEFAULT: "#2D3843";
|
|
88
|
-
foreground: "#FFFFFF";
|
|
89
|
-
};
|
|
90
|
-
paper: {
|
|
91
|
-
DEFAULT: "#E8EAED";
|
|
92
|
-
foreground: "#1D1F21";
|
|
93
|
-
field: "#FFFFFF";
|
|
94
|
-
line: "#BCBEC2";
|
|
95
|
-
muted: "#626364";
|
|
96
|
-
};
|
|
97
|
-
tile: {
|
|
98
|
-
/**
|
|
99
|
-
* Ink for any tile fill — `text-tile-foreground`. Shared across the
|
|
100
|
-
* measurement and formula variants because both carry white type; keeping it
|
|
101
|
-
* at the family level avoids two identical `foreground` keys that could
|
|
102
|
-
* drift apart by accident.
|
|
103
|
-
*/
|
|
104
|
-
foreground: "#FFFFFF";
|
|
105
|
-
measurement: {
|
|
106
|
-
DEFAULT: "#0066FF";
|
|
107
|
-
badge: "#50A6FF";
|
|
108
|
-
};
|
|
109
|
-
formula: {
|
|
110
|
-
DEFAULT: "#BD30A8";
|
|
111
|
-
badge: "#6C155F";
|
|
112
|
-
};
|
|
113
|
-
count: {
|
|
114
|
-
DEFAULT: "#02274B";
|
|
115
|
-
foreground: "#FFFFFF";
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
diagram: {
|
|
119
|
-
1: "#2E4C6A";
|
|
120
|
-
2: "#4B6074";
|
|
121
|
-
3: "#67819A";
|
|
122
|
-
};
|
|
123
|
-
tolerance: {
|
|
124
|
-
in: {
|
|
125
|
-
DEFAULT: "#58A942";
|
|
126
|
-
warning: "#00E920";
|
|
127
|
-
muted: "#8BB380";
|
|
128
|
-
};
|
|
129
|
-
out: {
|
|
130
|
-
DEFAULT: "#E83D2F";
|
|
131
|
-
warning: "#DA1100";
|
|
132
|
-
muted: "#DF6358";
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
export type BoldrColors = typeof boldrColors;
|