dytools-capture-engine 1.2.6 → 1.3.1

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/index.cjs CHANGED
@@ -143,13 +143,14 @@ var CaptureToEngineEventType = {
143
143
  // ObjectDeselected: "object:deselected",
144
144
  };
145
145
  var CaptureZoneBase = class {
146
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
146
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
147
147
  this._example = null;
148
148
  this.needsAnchorReposition = false;
149
149
  // This is true when the zone needs to be repositioned to the parent's anchor point when the anchor is moved.
150
150
  this.primaryCanvasRectangleId = null;
151
151
  // a queue for pending internal events
152
152
  this.pendingInternalEvents = [];
153
+ this.options = this.createOptions(opts);
153
154
  this._id = this.makeId();
154
155
  this._name = name;
155
156
  this._rect = rect;
@@ -162,6 +163,17 @@ var CaptureZoneBase = class {
162
163
  this._excludeFromOutput = excludeFromOutput;
163
164
  this._defaultValueIfEmpty = defaultValueIfEmpty;
164
165
  }
166
+ get defaultOptions() {
167
+ return {
168
+ zoneColor: "blue",
169
+ ocrMatchColor: "rgba(0, 255, 0, 0.25)",
170
+ anchorPointColor: ""
171
+ };
172
+ }
173
+ /** INTERNAL SETUP **/
174
+ createOptions(opts) {
175
+ return { ...this.defaultOptions, ...opts };
176
+ }
165
177
  handleInternalZoneEvent(type, payload) {
166
178
  if (this.primaryCanvasRectangleId === null || !this.canvasManager) {
167
179
  return;
@@ -468,12 +480,17 @@ var CaptureZoneBase = class {
468
480
  }
469
481
  };
470
482
  var SimpleZone = class extends CaptureZoneBase {
471
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
472
- super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty);
483
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
484
+ super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty, opts);
473
485
  this.type = "simple";
474
486
  this.ocrOverlayIds = [];
475
487
  this.lastMatchHash = "";
476
488
  }
489
+ get defaultOptions() {
490
+ return {
491
+ ...super.defaultOptions
492
+ };
493
+ }
477
494
  handleInternalZoneEvent(type, payload) {
478
495
  super.handleInternalZoneEvent(type, payload);
479
496
  if (this.canvasManager === null) {
@@ -481,7 +498,7 @@ var SimpleZone = class extends CaptureZoneBase {
481
498
  return;
482
499
  }
483
500
  if (type === CaptureZoneEventType.ZoneCanvasManagerSet) {
484
- this.primaryCanvasRectangleId = this.canvasManager.addRectangle(this.rect, this.name, "blue", true, true);
501
+ this.primaryCanvasRectangleId = this.canvasManager.addRectangle(this.rect, this.name, this.options.zoneColor ?? "black", true, true);
485
502
  }
486
503
  if (type === CaptureZoneEventType.ZoneHiddenChanged) {
487
504
  const zoneHiddenChangedPayload = payload;
@@ -498,7 +515,7 @@ var SimpleZone = class extends CaptureZoneBase {
498
515
  let isFirstMatch = true;
499
516
  for (const match of ocrMatches) {
500
517
  if (match.templateZoneId != this.id) continue;
501
- this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, "rgba(0, 255, 0, 0.25)", false));
518
+ this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, this.options.ocrMatchColor ?? "grey", false));
502
519
  break;
503
520
  }
504
521
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.setVisibility(id, !this.hidden));
@@ -553,6 +570,11 @@ var AnchorChildZone = class extends SimpleZone {
553
570
  super(...arguments);
554
571
  this.type = "anchor-child";
555
572
  }
573
+ get defaultOptions() {
574
+ return {
575
+ ...super.defaultOptions
576
+ };
577
+ }
556
578
  toExternalChild(docWidth, docHeight, parentAnchor) {
557
579
  let external = this.toExternal(docWidth, docHeight);
558
580
  if (!external) return null;
@@ -566,8 +588,8 @@ var AnchorChildZone = class extends SimpleZone {
566
588
  }
567
589
  };
568
590
  var AnchorZone = class extends CaptureZoneBase {
569
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
570
- super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty);
591
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
592
+ super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty, opts);
571
593
  this.type = "anchor";
572
594
  //private primaryCanvasRectangleId: string | null = null;
573
595
  this._anchorLocation = "MiddleLeft";
@@ -577,7 +599,6 @@ var AnchorZone = class extends CaptureZoneBase {
577
599
  this.ocrOverlayIds = [];
578
600
  this.lastMatchHash = "";
579
601
  this.currentAnchorPoint = null;
580
- this._cycle = 50;
581
602
  const internalArray = [];
582
603
  const snapshotChildren = (arr) => {
583
604
  const map = /* @__PURE__ */ new Map();
@@ -631,6 +652,28 @@ var AnchorZone = class extends CaptureZoneBase {
631
652
  configurable: false
632
653
  });
633
654
  }
655
+ get defaultOptions() {
656
+ return {
657
+ ...super.defaultOptions,
658
+ zoneColor: "green",
659
+ ocrMatchColor: "rgba(0, 255, 255, 0.25)",
660
+ anchorPointColor: "rgba(0, 0, 255, 0.25)",
661
+ zoneAdditionalChildrenColor: (index) => {
662
+ let maxOpacity = 0.5;
663
+ let minOpacity = 0.25;
664
+ let percentThroughArray = (index + 1) / this.children.length;
665
+ let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
666
+ let color = `rgba(50, 128, 255, ${opacity.toFixed(2)})`;
667
+ return color;
668
+ }
669
+ };
670
+ }
671
+ resolveValue(value, index, total, defaultValue = "black") {
672
+ if (value === void 0 || value === null) {
673
+ return defaultValue;
674
+ }
675
+ return typeof value === "function" ? value(index, total) : value;
676
+ }
634
677
  get anchorLocation() {
635
678
  return this._anchorLocation;
636
679
  }
@@ -656,7 +699,7 @@ var AnchorZone = class extends CaptureZoneBase {
656
699
  return;
657
700
  }
658
701
  if (type === CaptureZoneEventType.ZoneCanvasManagerSet) {
659
- this.primaryCanvasRectangleId = this.canvasManager?.addRectangle(this.rect, this.name, "green", true, true);
702
+ this.primaryCanvasRectangleId = this.canvasManager?.addRectangle(this.rect, this.name, this.options.zoneColor ?? "black", true, true);
660
703
  }
661
704
  if (type === CaptureZoneEventType.ZoneAnchorLocationChanged) {
662
705
  const zoneAnchorLocationChangedPayload = payload;
@@ -693,12 +736,11 @@ var AnchorZone = class extends CaptureZoneBase {
693
736
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.removeObject(id));
694
737
  this.ocrOverlayIds = [];
695
738
  let isFirstMatch = true;
696
- let cycle = this.cycle;
697
739
  for (const match of ocrMatches) {
698
740
  if (match.templateZoneId != this.id) continue;
699
- this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, "rgba(0, 255, 255, 0.25)", false));
741
+ this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, this.options.ocrMatchColor ?? "black", false));
700
742
  if (match.anchorPointAbsolute) {
701
- this.ocrOverlayIds.push(this.canvasManager?.addCircle(match.anchorPointAbsolute, 2, "rgba(0, 0, 255, 0.25)", false, false));
743
+ this.ocrOverlayIds.push(this.canvasManager?.addCircle(match.anchorPointAbsolute, 2, this.options.anchorPointColor ?? "black", false, false));
702
744
  if (isFirstMatch) {
703
745
  for (const child of this.children.filter((e) => e.needsAnchorReposition)) {
704
746
  let currentAnchorPoint = this.currentAnchorPoint ?? this.rect.origin;
@@ -711,11 +753,7 @@ var AnchorZone = class extends CaptureZoneBase {
711
753
  const child = this.children[i];
712
754
  if (child.hidden == false) {
713
755
  let vector = this.currentAnchorPoint ? match.anchorPointAbsolute.getDeltaFromPoint(this.currentAnchorPoint) : new import_dytools_geometry.Vector(0, 0);
714
- let maxOpacity = 0.5;
715
- let minOpacity = 0.25;
716
- let percentThroughArray = (i + 1) / this.children.length;
717
- let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
718
- let color = `rgba(${cycle}, 128, 255, ${opacity.toFixed(2)})`;
756
+ let color = this.resolveValue(this.options.zoneAdditionalChildrenColor, i, this.children.length, "black");
719
757
  const polygon = child.rect.move(vector).toPolygon().points;
720
758
  this.ocrOverlayIds.push(this.canvasManager?.addPolygon(polygon, color, false));
721
759
  }
@@ -730,10 +768,6 @@ var AnchorZone = class extends CaptureZoneBase {
730
768
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.setVisibility(id, !this.hidden));
731
769
  }
732
770
  }
733
- get cycle() {
734
- this._cycle = (this._cycle + 64) % 255;
735
- return this._cycle;
736
- }
737
771
  handleEvent(id, type, payload) {
738
772
  if (this.id == id) {
739
773
  if (type == CaptureEngineToZoneEventType.CanvasObjectPositionChanged) {
@@ -909,7 +943,7 @@ var DefaultZoneCanvasManager = class {
909
943
  }
910
944
  };
911
945
  var CaptureEngine = class {
912
- constructor(selector, serverApi) {
946
+ constructor(selector, serverApi, opts = {}) {
913
947
  this.listeners = {};
914
948
  // Template properties
915
949
  this._name = "Untitled";
@@ -923,6 +957,28 @@ var CaptureEngine = class {
923
957
  // key = object id, value = set of flags
924
958
  // Refactor properties
925
959
  this.zoneCounter = 1;
960
+ this.defaultOptions = {
961
+ initialZoom: 1,
962
+ initialPan: { x: 10, y: 10 },
963
+ defaultMode: "default",
964
+ // Default mode to switch into on startup
965
+ ocrOverlayColor: "rgba(0, 128, 255, 0.25)",
966
+ simpleZoneColor: "blue",
967
+ simpleZoneOcrMatchColor: "rgba(0, 255, 0, 0.25)",
968
+ anchorZoneColor: "green",
969
+ anchorZoneOcrMatchColor: "rgba(0, 255, 255, 0.25)",
970
+ anchorZoneAnchorPointColor: "rgba(0, 0, 255, 0.25)",
971
+ anchorZoneAdditionalChildrenColor: (index, total) => {
972
+ let maxOpacity = 0.5;
973
+ let minOpacity = 0.25;
974
+ let percentThroughArray = (index + 1) / total;
975
+ let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
976
+ let color = `rgba(50, 128, 255, ${opacity.toFixed(2)})`;
977
+ return color;
978
+ },
979
+ anchorChildZoneColor: "blue",
980
+ anchorChildZoneOcrMatchColor: "rgba(0, 255, 0, 0.25)"
981
+ };
926
982
  /* --- INTERNAL ENGINE EVENT METHODS --- */
927
983
  // These are used for messages to the engine itself (e.g. from a zone if the zone mutated.)
928
984
  this.refreshMatches = this.createMeteredFn(async () => {
@@ -930,7 +986,12 @@ var CaptureEngine = class {
930
986
  const matches = await this.getZoneMatchesFromServer();
931
987
  this.setOcrMatchesSnapshot(matches);
932
988
  }, 1e3);
933
- this.engine = new import_dytools_canvas_engine.CanvasEngine(selector, {});
989
+ this.options = this.createOptions(opts);
990
+ this.engine = new import_dytools_canvas_engine.CanvasEngine(selector, {
991
+ initialPan: this.options.initialPan,
992
+ defaultMode: this.options.defaultMode,
993
+ initialZoom: this.options.initialZoom
994
+ });
934
995
  if (serverApi) {
935
996
  this.setServerApi(serverApi);
936
997
  }
@@ -988,6 +1049,10 @@ var CaptureEngine = class {
988
1049
  });
989
1050
  this.setupEngine();
990
1051
  }
1052
+ /** INTERNAL SETUP **/
1053
+ createOptions(opts) {
1054
+ return { ...this.defaultOptions, ...opts };
1055
+ }
991
1056
  // This is used to attach event handlers to the canvas engine (this.engine)
992
1057
  // All zone-related events (like position changed, resized, etc.) will be sent to the zones and not externally.
993
1058
  // All zones will listen to these events and update their internal state accordingly and send the completed event
@@ -1348,29 +1413,43 @@ var CaptureEngine = class {
1348
1413
  * Add a new simple zone
1349
1414
  * @param bounds Rectangle
1350
1415
  */
1351
- addSimpleZone(bounds) {
1416
+ addSimpleZone(bounds, makeCurrentSelected = false) {
1352
1417
  let newZone = new SimpleZone("Test1", bounds, false, null, null, null);
1353
1418
  this.zones.push(newZone);
1419
+ if (makeCurrentSelected) {
1420
+ this.setSelectedZones([newZone]);
1421
+ }
1422
+ return newZone;
1354
1423
  }
1355
1424
  /**
1356
1425
  * Add a new anchor zone
1357
1426
  * @param bounds Rectangle
1358
1427
  */
1359
- addAnchorZone(bounds) {
1428
+ addAnchorZone(bounds, makeCurrentSelected = false) {
1360
1429
  let newZone = new AnchorZone(`Anchor ${this.zoneCounter++}`, bounds, false, null, null, null);
1361
1430
  this.zones.push(newZone);
1431
+ if (makeCurrentSelected) {
1432
+ this.setSelectedZones([newZone]);
1433
+ }
1434
+ return newZone;
1362
1435
  }
1363
1436
  /**
1364
1437
  * Add a child zone linked to an anchor
1365
1438
  * @param anchorId string
1366
1439
  * @param bounds Rectangle
1367
1440
  */
1368
- addAnchorChildZone(anchorId, bounds) {
1441
+ addAnchorChildZone(anchorId, bounds, makeCurrentSelected = false) {
1369
1442
  const anchorZone = this.zones.find((z) => z.id === anchorId);
1370
- if (!anchorZone) return;
1443
+ if (!anchorZone) {
1444
+ throw new Error(`Anchor zone with id ${anchorId} not found`);
1445
+ }
1371
1446
  let newZone = new AnchorChildZone(`Child ${this.zoneCounter++}`, bounds, false, null, null, null);
1372
1447
  if (!anchorZone.children) anchorZone.children = [];
1373
1448
  anchorZone.children.push(newZone);
1449
+ if (makeCurrentSelected) {
1450
+ this.setSelectedZones([newZone]);
1451
+ }
1452
+ return newZone;
1374
1453
  }
1375
1454
  /**
1376
1455
  * Remove a zone and its canvas representation by id
@@ -1633,7 +1712,7 @@ var CaptureEngine = class {
1633
1712
  const overlay = new import_dytools_canvas_engine.PolygonObject(
1634
1713
  overlayId,
1635
1714
  pts,
1636
- "rgba(0, 128, 255, 0.25)",
1715
+ this.options.ocrOverlayColor ?? "rgba(0, 128, 255, 0.25)",
1637
1716
  false,
1638
1717
  // isSelectable
1639
1718
  false,
package/dist/index.d.cts CHANGED
@@ -444,7 +444,11 @@ declare class CaptureEngine {
444
444
  private ocrOverlayIds;
445
445
  private flags;
446
446
  private zoneCounter;
447
- constructor(selector: string, serverApi?: CaptureEngineServerApi);
447
+ private options;
448
+ private readonly defaultOptions;
449
+ constructor(selector: string, serverApi?: CaptureEngineServerApi, opts?: CaptureEngineOptions);
450
+ /** INTERNAL SETUP **/
451
+ private createOptions;
448
452
  private setupEngine;
449
453
  on<T extends CapturePublicEventType>(event: T, handler: (payload: CapturePublicEventPayloads[T]) => void, options?: {
450
454
  once?: boolean;
@@ -471,18 +475,18 @@ declare class CaptureEngine {
471
475
  * Add a new simple zone
472
476
  * @param bounds Rectangle
473
477
  */
474
- addSimpleZone(bounds: Rectangle): void;
478
+ addSimpleZone(bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
475
479
  /**
476
480
  * Add a new anchor zone
477
481
  * @param bounds Rectangle
478
482
  */
479
- addAnchorZone(bounds: Rectangle): void;
483
+ addAnchorZone(bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
480
484
  /**
481
485
  * Add a child zone linked to an anchor
482
486
  * @param anchorId string
483
487
  * @param bounds Rectangle
484
488
  */
485
- addAnchorChildZone(anchorId: string, bounds: Rectangle): void;
489
+ addAnchorChildZone(anchorId: string, bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
486
490
  /**
487
491
  * Remove a zone and its canvas representation by id
488
492
  * @param id string
@@ -567,5 +571,29 @@ interface CaptureEngineServerApi {
567
571
  ocr: OcrRead;
568
572
  }): Promise<Result<ZoneOcrMatch[]>>;
569
573
  }
574
+ interface CaptureEngineOptions {
575
+ initialZoom?: number;
576
+ initialPan?: {
577
+ x: number;
578
+ y: number;
579
+ };
580
+ defaultMode?: string;
581
+ ocrOverlayColor?: string;
582
+ simpleZoneColor?: string;
583
+ simpleZoneOcrMatchColor?: string;
584
+ anchorZoneColor?: string;
585
+ anchorZoneOcrMatchColor?: string;
586
+ anchorZoneAnchorPointColor?: string;
587
+ anchorZoneAdditionalChildrenColor?: StringOrFactory;
588
+ anchorChildZoneColor?: string;
589
+ anchorChildZoneOcrMatchColor?: string;
590
+ }
591
+ type StringOrFactory = string | ((index: number, total: number) => string);
592
+ interface CaptureZoneOptions {
593
+ zoneColor?: string;
594
+ anchorPointColor?: string;
595
+ ocrMatchColor?: string;
596
+ zoneAdditionalChildrenColor?: StringOrFactory;
597
+ }
570
598
 
571
- export { CaptureEngine, type CaptureEngineServerApi, type CaptureEngineToZoneEventPayloads, CaptureEngineToZoneEventType, type CapturePublicEventPayloads, CapturePublicEventType, type CaptureToEngineEventPayloads, CaptureToEngineEventType, type CaptureZoneEventPayloads, type ExternalTemplate, type ExternalTemplateZone, type ExternalZoneType, type OcrRead, type OcrWord, type TemplateZoneBase, type ZoneCanvasManager, type ZoneExample, type ZoneKind, type ZoneOcrMatch };
599
+ export { CaptureEngine, type CaptureEngineOptions, type CaptureEngineServerApi, type CaptureEngineToZoneEventPayloads, CaptureEngineToZoneEventType, type CapturePublicEventPayloads, CapturePublicEventType, type CaptureToEngineEventPayloads, CaptureToEngineEventType, type CaptureZoneEventPayloads, type CaptureZoneOptions, type ExternalTemplate, type ExternalTemplateZone, type ExternalZoneType, type OcrRead, type OcrWord, type TemplateZoneBase, type ZoneCanvasManager, type ZoneExample, type ZoneKind, type ZoneOcrMatch };
package/dist/index.d.ts CHANGED
@@ -444,7 +444,11 @@ declare class CaptureEngine {
444
444
  private ocrOverlayIds;
445
445
  private flags;
446
446
  private zoneCounter;
447
- constructor(selector: string, serverApi?: CaptureEngineServerApi);
447
+ private options;
448
+ private readonly defaultOptions;
449
+ constructor(selector: string, serverApi?: CaptureEngineServerApi, opts?: CaptureEngineOptions);
450
+ /** INTERNAL SETUP **/
451
+ private createOptions;
448
452
  private setupEngine;
449
453
  on<T extends CapturePublicEventType>(event: T, handler: (payload: CapturePublicEventPayloads[T]) => void, options?: {
450
454
  once?: boolean;
@@ -471,18 +475,18 @@ declare class CaptureEngine {
471
475
  * Add a new simple zone
472
476
  * @param bounds Rectangle
473
477
  */
474
- addSimpleZone(bounds: Rectangle): void;
478
+ addSimpleZone(bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
475
479
  /**
476
480
  * Add a new anchor zone
477
481
  * @param bounds Rectangle
478
482
  */
479
- addAnchorZone(bounds: Rectangle): void;
483
+ addAnchorZone(bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
480
484
  /**
481
485
  * Add a child zone linked to an anchor
482
486
  * @param anchorId string
483
487
  * @param bounds Rectangle
484
488
  */
485
- addAnchorChildZone(anchorId: string, bounds: Rectangle): void;
489
+ addAnchorChildZone(anchorId: string, bounds: Rectangle, makeCurrentSelected?: boolean): TemplateZoneBase;
486
490
  /**
487
491
  * Remove a zone and its canvas representation by id
488
492
  * @param id string
@@ -567,5 +571,29 @@ interface CaptureEngineServerApi {
567
571
  ocr: OcrRead;
568
572
  }): Promise<Result<ZoneOcrMatch[]>>;
569
573
  }
574
+ interface CaptureEngineOptions {
575
+ initialZoom?: number;
576
+ initialPan?: {
577
+ x: number;
578
+ y: number;
579
+ };
580
+ defaultMode?: string;
581
+ ocrOverlayColor?: string;
582
+ simpleZoneColor?: string;
583
+ simpleZoneOcrMatchColor?: string;
584
+ anchorZoneColor?: string;
585
+ anchorZoneOcrMatchColor?: string;
586
+ anchorZoneAnchorPointColor?: string;
587
+ anchorZoneAdditionalChildrenColor?: StringOrFactory;
588
+ anchorChildZoneColor?: string;
589
+ anchorChildZoneOcrMatchColor?: string;
590
+ }
591
+ type StringOrFactory = string | ((index: number, total: number) => string);
592
+ interface CaptureZoneOptions {
593
+ zoneColor?: string;
594
+ anchorPointColor?: string;
595
+ ocrMatchColor?: string;
596
+ zoneAdditionalChildrenColor?: StringOrFactory;
597
+ }
570
598
 
571
- export { CaptureEngine, type CaptureEngineServerApi, type CaptureEngineToZoneEventPayloads, CaptureEngineToZoneEventType, type CapturePublicEventPayloads, CapturePublicEventType, type CaptureToEngineEventPayloads, CaptureToEngineEventType, type CaptureZoneEventPayloads, type ExternalTemplate, type ExternalTemplateZone, type ExternalZoneType, type OcrRead, type OcrWord, type TemplateZoneBase, type ZoneCanvasManager, type ZoneExample, type ZoneKind, type ZoneOcrMatch };
599
+ export { CaptureEngine, type CaptureEngineOptions, type CaptureEngineServerApi, type CaptureEngineToZoneEventPayloads, CaptureEngineToZoneEventType, type CapturePublicEventPayloads, CapturePublicEventType, type CaptureToEngineEventPayloads, CaptureToEngineEventType, type CaptureZoneEventPayloads, type CaptureZoneOptions, type ExternalTemplate, type ExternalTemplateZone, type ExternalZoneType, type OcrRead, type OcrWord, type TemplateZoneBase, type ZoneCanvasManager, type ZoneExample, type ZoneKind, type ZoneOcrMatch };
package/dist/index.js CHANGED
@@ -127,13 +127,14 @@ var CaptureToEngineEventType = {
127
127
  // ObjectDeselected: "object:deselected",
128
128
  };
129
129
  var CaptureZoneBase = class {
130
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
130
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
131
131
  this._example = null;
132
132
  this.needsAnchorReposition = false;
133
133
  // This is true when the zone needs to be repositioned to the parent's anchor point when the anchor is moved.
134
134
  this.primaryCanvasRectangleId = null;
135
135
  // a queue for pending internal events
136
136
  this.pendingInternalEvents = [];
137
+ this.options = this.createOptions(opts);
137
138
  this._id = this.makeId();
138
139
  this._name = name;
139
140
  this._rect = rect;
@@ -146,6 +147,17 @@ var CaptureZoneBase = class {
146
147
  this._excludeFromOutput = excludeFromOutput;
147
148
  this._defaultValueIfEmpty = defaultValueIfEmpty;
148
149
  }
150
+ get defaultOptions() {
151
+ return {
152
+ zoneColor: "blue",
153
+ ocrMatchColor: "rgba(0, 255, 0, 0.25)",
154
+ anchorPointColor: ""
155
+ };
156
+ }
157
+ /** INTERNAL SETUP **/
158
+ createOptions(opts) {
159
+ return { ...this.defaultOptions, ...opts };
160
+ }
149
161
  handleInternalZoneEvent(type, payload) {
150
162
  if (this.primaryCanvasRectangleId === null || !this.canvasManager) {
151
163
  return;
@@ -452,12 +464,17 @@ var CaptureZoneBase = class {
452
464
  }
453
465
  };
454
466
  var SimpleZone = class extends CaptureZoneBase {
455
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
456
- super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty);
467
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
468
+ super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty, opts);
457
469
  this.type = "simple";
458
470
  this.ocrOverlayIds = [];
459
471
  this.lastMatchHash = "";
460
472
  }
473
+ get defaultOptions() {
474
+ return {
475
+ ...super.defaultOptions
476
+ };
477
+ }
461
478
  handleInternalZoneEvent(type, payload) {
462
479
  super.handleInternalZoneEvent(type, payload);
463
480
  if (this.canvasManager === null) {
@@ -465,7 +482,7 @@ var SimpleZone = class extends CaptureZoneBase {
465
482
  return;
466
483
  }
467
484
  if (type === CaptureZoneEventType.ZoneCanvasManagerSet) {
468
- this.primaryCanvasRectangleId = this.canvasManager.addRectangle(this.rect, this.name, "blue", true, true);
485
+ this.primaryCanvasRectangleId = this.canvasManager.addRectangle(this.rect, this.name, this.options.zoneColor ?? "black", true, true);
469
486
  }
470
487
  if (type === CaptureZoneEventType.ZoneHiddenChanged) {
471
488
  const zoneHiddenChangedPayload = payload;
@@ -482,7 +499,7 @@ var SimpleZone = class extends CaptureZoneBase {
482
499
  let isFirstMatch = true;
483
500
  for (const match of ocrMatches) {
484
501
  if (match.templateZoneId != this.id) continue;
485
- this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, "rgba(0, 255, 0, 0.25)", false));
502
+ this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, this.options.ocrMatchColor ?? "grey", false));
486
503
  break;
487
504
  }
488
505
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.setVisibility(id, !this.hidden));
@@ -537,6 +554,11 @@ var AnchorChildZone = class extends SimpleZone {
537
554
  super(...arguments);
538
555
  this.type = "anchor-child";
539
556
  }
557
+ get defaultOptions() {
558
+ return {
559
+ ...super.defaultOptions
560
+ };
561
+ }
540
562
  toExternalChild(docWidth, docHeight, parentAnchor) {
541
563
  let external = this.toExternal(docWidth, docHeight);
542
564
  if (!external) return null;
@@ -550,8 +572,8 @@ var AnchorChildZone = class extends SimpleZone {
550
572
  }
551
573
  };
552
574
  var AnchorZone = class extends CaptureZoneBase {
553
- constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null) {
554
- super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty);
575
+ constructor(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required = false, dataType = null, excludeFromOutput = false, defaultValueIfEmpty = null, opts = {}) {
576
+ super(name, rect, hidden, filterRegex, outputRegex, outputReplacement, required, dataType, excludeFromOutput, defaultValueIfEmpty, opts);
555
577
  this.type = "anchor";
556
578
  //private primaryCanvasRectangleId: string | null = null;
557
579
  this._anchorLocation = "MiddleLeft";
@@ -561,7 +583,6 @@ var AnchorZone = class extends CaptureZoneBase {
561
583
  this.ocrOverlayIds = [];
562
584
  this.lastMatchHash = "";
563
585
  this.currentAnchorPoint = null;
564
- this._cycle = 50;
565
586
  const internalArray = [];
566
587
  const snapshotChildren = (arr) => {
567
588
  const map = /* @__PURE__ */ new Map();
@@ -615,6 +636,28 @@ var AnchorZone = class extends CaptureZoneBase {
615
636
  configurable: false
616
637
  });
617
638
  }
639
+ get defaultOptions() {
640
+ return {
641
+ ...super.defaultOptions,
642
+ zoneColor: "green",
643
+ ocrMatchColor: "rgba(0, 255, 255, 0.25)",
644
+ anchorPointColor: "rgba(0, 0, 255, 0.25)",
645
+ zoneAdditionalChildrenColor: (index) => {
646
+ let maxOpacity = 0.5;
647
+ let minOpacity = 0.25;
648
+ let percentThroughArray = (index + 1) / this.children.length;
649
+ let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
650
+ let color = `rgba(50, 128, 255, ${opacity.toFixed(2)})`;
651
+ return color;
652
+ }
653
+ };
654
+ }
655
+ resolveValue(value, index, total, defaultValue = "black") {
656
+ if (value === void 0 || value === null) {
657
+ return defaultValue;
658
+ }
659
+ return typeof value === "function" ? value(index, total) : value;
660
+ }
618
661
  get anchorLocation() {
619
662
  return this._anchorLocation;
620
663
  }
@@ -640,7 +683,7 @@ var AnchorZone = class extends CaptureZoneBase {
640
683
  return;
641
684
  }
642
685
  if (type === CaptureZoneEventType.ZoneCanvasManagerSet) {
643
- this.primaryCanvasRectangleId = this.canvasManager?.addRectangle(this.rect, this.name, "green", true, true);
686
+ this.primaryCanvasRectangleId = this.canvasManager?.addRectangle(this.rect, this.name, this.options.zoneColor ?? "black", true, true);
644
687
  }
645
688
  if (type === CaptureZoneEventType.ZoneAnchorLocationChanged) {
646
689
  const zoneAnchorLocationChangedPayload = payload;
@@ -677,12 +720,11 @@ var AnchorZone = class extends CaptureZoneBase {
677
720
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.removeObject(id));
678
721
  this.ocrOverlayIds = [];
679
722
  let isFirstMatch = true;
680
- let cycle = this.cycle;
681
723
  for (const match of ocrMatches) {
682
724
  if (match.templateZoneId != this.id) continue;
683
- this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, "rgba(0, 255, 255, 0.25)", false));
725
+ this.ocrOverlayIds.push(this.canvasManager?.addPolygon(match.polygonAbsolute.points, this.options.ocrMatchColor ?? "black", false));
684
726
  if (match.anchorPointAbsolute) {
685
- this.ocrOverlayIds.push(this.canvasManager?.addCircle(match.anchorPointAbsolute, 2, "rgba(0, 0, 255, 0.25)", false, false));
727
+ this.ocrOverlayIds.push(this.canvasManager?.addCircle(match.anchorPointAbsolute, 2, this.options.anchorPointColor ?? "black", false, false));
686
728
  if (isFirstMatch) {
687
729
  for (const child of this.children.filter((e) => e.needsAnchorReposition)) {
688
730
  let currentAnchorPoint = this.currentAnchorPoint ?? this.rect.origin;
@@ -695,11 +737,7 @@ var AnchorZone = class extends CaptureZoneBase {
695
737
  const child = this.children[i];
696
738
  if (child.hidden == false) {
697
739
  let vector = this.currentAnchorPoint ? match.anchorPointAbsolute.getDeltaFromPoint(this.currentAnchorPoint) : new Vector(0, 0);
698
- let maxOpacity = 0.5;
699
- let minOpacity = 0.25;
700
- let percentThroughArray = (i + 1) / this.children.length;
701
- let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
702
- let color = `rgba(${cycle}, 128, 255, ${opacity.toFixed(2)})`;
740
+ let color = this.resolveValue(this.options.zoneAdditionalChildrenColor, i, this.children.length, "black");
703
741
  const polygon = child.rect.move(vector).toPolygon().points;
704
742
  this.ocrOverlayIds.push(this.canvasManager?.addPolygon(polygon, color, false));
705
743
  }
@@ -714,10 +752,6 @@ var AnchorZone = class extends CaptureZoneBase {
714
752
  this.ocrOverlayIds.forEach((id) => this.canvasManager?.setVisibility(id, !this.hidden));
715
753
  }
716
754
  }
717
- get cycle() {
718
- this._cycle = (this._cycle + 64) % 255;
719
- return this._cycle;
720
- }
721
755
  handleEvent(id, type, payload) {
722
756
  if (this.id == id) {
723
757
  if (type == CaptureEngineToZoneEventType.CanvasObjectPositionChanged) {
@@ -893,7 +927,7 @@ var DefaultZoneCanvasManager = class {
893
927
  }
894
928
  };
895
929
  var CaptureEngine = class {
896
- constructor(selector, serverApi) {
930
+ constructor(selector, serverApi, opts = {}) {
897
931
  this.listeners = {};
898
932
  // Template properties
899
933
  this._name = "Untitled";
@@ -907,6 +941,28 @@ var CaptureEngine = class {
907
941
  // key = object id, value = set of flags
908
942
  // Refactor properties
909
943
  this.zoneCounter = 1;
944
+ this.defaultOptions = {
945
+ initialZoom: 1,
946
+ initialPan: { x: 10, y: 10 },
947
+ defaultMode: "default",
948
+ // Default mode to switch into on startup
949
+ ocrOverlayColor: "rgba(0, 128, 255, 0.25)",
950
+ simpleZoneColor: "blue",
951
+ simpleZoneOcrMatchColor: "rgba(0, 255, 0, 0.25)",
952
+ anchorZoneColor: "green",
953
+ anchorZoneOcrMatchColor: "rgba(0, 255, 255, 0.25)",
954
+ anchorZoneAnchorPointColor: "rgba(0, 0, 255, 0.25)",
955
+ anchorZoneAdditionalChildrenColor: (index, total) => {
956
+ let maxOpacity = 0.5;
957
+ let minOpacity = 0.25;
958
+ let percentThroughArray = (index + 1) / total;
959
+ let opacity = maxOpacity - (maxOpacity - minOpacity) * percentThroughArray;
960
+ let color = `rgba(50, 128, 255, ${opacity.toFixed(2)})`;
961
+ return color;
962
+ },
963
+ anchorChildZoneColor: "blue",
964
+ anchorChildZoneOcrMatchColor: "rgba(0, 255, 0, 0.25)"
965
+ };
910
966
  /* --- INTERNAL ENGINE EVENT METHODS --- */
911
967
  // These are used for messages to the engine itself (e.g. from a zone if the zone mutated.)
912
968
  this.refreshMatches = this.createMeteredFn(async () => {
@@ -914,7 +970,12 @@ var CaptureEngine = class {
914
970
  const matches = await this.getZoneMatchesFromServer();
915
971
  this.setOcrMatchesSnapshot(matches);
916
972
  }, 1e3);
917
- this.engine = new CanvasEngine(selector, {});
973
+ this.options = this.createOptions(opts);
974
+ this.engine = new CanvasEngine(selector, {
975
+ initialPan: this.options.initialPan,
976
+ defaultMode: this.options.defaultMode,
977
+ initialZoom: this.options.initialZoom
978
+ });
918
979
  if (serverApi) {
919
980
  this.setServerApi(serverApi);
920
981
  }
@@ -972,6 +1033,10 @@ var CaptureEngine = class {
972
1033
  });
973
1034
  this.setupEngine();
974
1035
  }
1036
+ /** INTERNAL SETUP **/
1037
+ createOptions(opts) {
1038
+ return { ...this.defaultOptions, ...opts };
1039
+ }
975
1040
  // This is used to attach event handlers to the canvas engine (this.engine)
976
1041
  // All zone-related events (like position changed, resized, etc.) will be sent to the zones and not externally.
977
1042
  // All zones will listen to these events and update their internal state accordingly and send the completed event
@@ -1332,29 +1397,43 @@ var CaptureEngine = class {
1332
1397
  * Add a new simple zone
1333
1398
  * @param bounds Rectangle
1334
1399
  */
1335
- addSimpleZone(bounds) {
1400
+ addSimpleZone(bounds, makeCurrentSelected = false) {
1336
1401
  let newZone = new SimpleZone("Test1", bounds, false, null, null, null);
1337
1402
  this.zones.push(newZone);
1403
+ if (makeCurrentSelected) {
1404
+ this.setSelectedZones([newZone]);
1405
+ }
1406
+ return newZone;
1338
1407
  }
1339
1408
  /**
1340
1409
  * Add a new anchor zone
1341
1410
  * @param bounds Rectangle
1342
1411
  */
1343
- addAnchorZone(bounds) {
1412
+ addAnchorZone(bounds, makeCurrentSelected = false) {
1344
1413
  let newZone = new AnchorZone(`Anchor ${this.zoneCounter++}`, bounds, false, null, null, null);
1345
1414
  this.zones.push(newZone);
1415
+ if (makeCurrentSelected) {
1416
+ this.setSelectedZones([newZone]);
1417
+ }
1418
+ return newZone;
1346
1419
  }
1347
1420
  /**
1348
1421
  * Add a child zone linked to an anchor
1349
1422
  * @param anchorId string
1350
1423
  * @param bounds Rectangle
1351
1424
  */
1352
- addAnchorChildZone(anchorId, bounds) {
1425
+ addAnchorChildZone(anchorId, bounds, makeCurrentSelected = false) {
1353
1426
  const anchorZone = this.zones.find((z) => z.id === anchorId);
1354
- if (!anchorZone) return;
1427
+ if (!anchorZone) {
1428
+ throw new Error(`Anchor zone with id ${anchorId} not found`);
1429
+ }
1355
1430
  let newZone = new AnchorChildZone(`Child ${this.zoneCounter++}`, bounds, false, null, null, null);
1356
1431
  if (!anchorZone.children) anchorZone.children = [];
1357
1432
  anchorZone.children.push(newZone);
1433
+ if (makeCurrentSelected) {
1434
+ this.setSelectedZones([newZone]);
1435
+ }
1436
+ return newZone;
1358
1437
  }
1359
1438
  /**
1360
1439
  * Remove a zone and its canvas representation by id
@@ -1617,7 +1696,7 @@ var CaptureEngine = class {
1617
1696
  const overlay = new PolygonObject(
1618
1697
  overlayId,
1619
1698
  pts,
1620
- "rgba(0, 128, 255, 0.25)",
1699
+ this.options.ocrOverlayColor ?? "rgba(0, 128, 255, 0.25)",
1621
1700
  false,
1622
1701
  // isSelectable
1623
1702
  false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dytools-capture-engine",
3
- "version": "1.2.6",
3
+ "version": "1.3.1",
4
4
  "description": "An editor allowing the creation of templates for ocr capture.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",