@memberjunction/ng-whiteboard 6.1.4 → 6.2.0-edge.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.
@@ -15,11 +15,11 @@ type ZoomDirection = 1 | -1;
15
15
  */
16
16
  export declare class RealtimeWhiteboardZoomComponent implements OnDestroy {
17
17
  /** How long a press must be held before continuous zooming kicks in. */
18
- private static readonly HoldDelayMs;
18
+ private static readonly holdDelayMs;
19
19
  /** Continuous-zoom tick cadence while held. */
20
- private static readonly HoldIntervalMs;
20
+ private static readonly holdIntervalMs;
21
21
  /** Multiplicative zoom factor per held tick (~3.5%). */
22
- private static readonly HoldFactor;
22
+ private static readonly holdFactor;
23
23
  /** Current zoom as a percentage (e.g. 90). */
24
24
  ZoomPercent: number;
25
25
  /** Whether the minimap is currently shown (highlights the map button). */
@@ -35,11 +35,11 @@ export class RealtimeWhiteboardZoomComponent {
35
35
  this.suppressNextClick = false;
36
36
  }
37
37
  /** How long a press must be held before continuous zooming kicks in. */
38
- static { this.HoldDelayMs = 350; }
38
+ static { this.holdDelayMs = 350; }
39
39
  /** Continuous-zoom tick cadence while held. */
40
- static { this.HoldIntervalMs = 50; }
40
+ static { this.holdIntervalMs = 50; }
41
41
  /** Multiplicative zoom factor per held tick (~3.5%). */
42
- static { this.HoldFactor = 1.035; }
42
+ static { this.holdFactor = 1.035; }
43
43
  ngOnDestroy() {
44
44
  this.stopHold();
45
45
  }
@@ -54,11 +54,11 @@ export class RealtimeWhiteboardZoomComponent {
54
54
  this.holdDelayTimer = null;
55
55
  this.suppressNextClick = true;
56
56
  const factor = direction === 1
57
- ? RealtimeWhiteboardZoomComponent.HoldFactor
58
- : 1 / RealtimeWhiteboardZoomComponent.HoldFactor;
57
+ ? RealtimeWhiteboardZoomComponent.holdFactor
58
+ : 1 / RealtimeWhiteboardZoomComponent.holdFactor;
59
59
  this.ZoomBy.emit(factor); // first tick fires immediately when the hold engages
60
- this.holdIntervalTimer = setInterval(() => this.ZoomBy.emit(factor), RealtimeWhiteboardZoomComponent.HoldIntervalMs);
61
- }, RealtimeWhiteboardZoomComponent.HoldDelayMs);
60
+ this.holdIntervalTimer = setInterval(() => this.ZoomBy.emit(factor), RealtimeWhiteboardZoomComponent.holdIntervalMs);
61
+ }, RealtimeWhiteboardZoomComponent.holdDelayMs);
62
62
  }
63
63
  /** Pointer up / leave / cancel: stop any pending or running continuous zoom. */
64
64
  OnZoomPressEnd() {
@@ -1 +1 @@
1
- {"version":3,"file":"whiteboard-zoom.component.js","sourceRoot":"","sources":["../../src/lib/whiteboard-zoom.component.ts","../../src/lib/whiteboard-zoom.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n/** Which way a zoom button points. */\ntype ZoomDirection = 1 | -1;\n\n/**\n * The bottom-right zoom cluster of the live whiteboard: zoom out / percentage / zoom in,\n * fit-to-content, and the minimap toggle. Pure presentational; the board owns the\n * viewport math and the minimap rendering.\n *\n * HOLD-TO-ZOOM: a plain click on +/− still emits the existing single preset step\n * ({@link ZoomIn} / {@link ZoomOut}); holding the button down (pointerdown held past a\n * short delay) emits {@link ZoomBy} factors (~3.5%) every 50 ms for smooth continuous\n * zooming, stopping on pointerup / pointerleave / pointercancel / destroy — the timers\n * never leak. The board clamps to its usual 25%–200% limits.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-whiteboard-zoom',\n imports: [CommonModule],\n templateUrl: './whiteboard-zoom.component.html',\n styleUrl: './whiteboard-zoom.component.css'\n})\nexport class RealtimeWhiteboardZoomComponent implements OnDestroy {\n /** How long a press must be held before continuous zooming kicks in. */\n private static readonly HoldDelayMs = 350;\n /** Continuous-zoom tick cadence while held. */\n private static readonly HoldIntervalMs = 50;\n /** Multiplicative zoom factor per held tick (~3.5%). */\n private static readonly HoldFactor = 1.035;\n\n /** Current zoom as a percentage (e.g. 90). */\n @Input() ZoomPercent = 100;\n /** Whether the minimap is currently shown (highlights the map button). */\n @Input() MinimapOpen = false;\n\n /** Single preset step out (a plain click on −). */\n @Output() ZoomOut = new EventEmitter<void>();\n /** Single preset step in (a plain click on +). */\n @Output() ZoomIn = new EventEmitter<void>();\n /**\n * Continuous (held-button) zoom tick: a multiplicative factor (>1 zooms in, <1 zooms\n * out) emitted every 50 ms while + or − is held. Wire to the board's `ZoomByFactor`.\n */\n @Output() ZoomBy = new EventEmitter<number>();\n @Output() Fit = new EventEmitter<void>();\n @Output() ToggleMinimap = new EventEmitter<void>();\n\n private holdDelayTimer: ReturnType<typeof setTimeout> | null = null;\n private holdIntervalTimer: ReturnType<typeof setInterval> | null = null;\n /** Set once continuous ticks started, so the trailing click doesn't ALSO step. */\n private suppressNextClick = false;\n\n ngOnDestroy(): void {\n this.stopHold();\n }\n\n /** Pointer down on +/−: arm the hold — after the delay, tick {@link ZoomBy} repeatedly. */\n public OnZoomPressStart(event: PointerEvent, direction: ZoomDirection): void {\n if (event.button !== 0) {\n return;\n }\n this.stopHold();\n this.suppressNextClick = false;\n this.holdDelayTimer = setTimeout(() => {\n this.holdDelayTimer = null;\n this.suppressNextClick = true;\n const factor = direction === 1\n ? RealtimeWhiteboardZoomComponent.HoldFactor\n : 1 / RealtimeWhiteboardZoomComponent.HoldFactor;\n this.ZoomBy.emit(factor); // first tick fires immediately when the hold engages\n this.holdIntervalTimer = setInterval(() => this.ZoomBy.emit(factor), RealtimeWhiteboardZoomComponent.HoldIntervalMs);\n }, RealtimeWhiteboardZoomComponent.HoldDelayMs);\n }\n\n /** Pointer up / leave / cancel: stop any pending or running continuous zoom. */\n public OnZoomPressEnd(): void {\n this.stopHold();\n }\n\n /** The click that follows the press: a single preset step unless a hold already zoomed. */\n public OnZoomClick(direction: ZoomDirection): void {\n if (this.suppressNextClick) {\n this.suppressNextClick = false;\n return;\n }\n if (direction === 1) {\n this.ZoomIn.emit();\n }\n else {\n this.ZoomOut.emit();\n }\n }\n\n /** Clear both hold timers (idempotent — safe from any stop path). */\n private stopHold(): void {\n if (this.holdDelayTimer !== null) {\n clearTimeout(this.holdDelayTimer);\n this.holdDelayTimer = null;\n }\n if (this.holdIntervalTimer !== null) {\n clearInterval(this.holdIntervalTimer);\n this.holdIntervalTimer = null;\n }\n }\n}\n","<div class=\"zoom-cluster\">\n <button type=\"button\" title=\"Zoom out (hold for continuous)\" aria-label=\"Zoom out\"\n (pointerdown)=\"OnZoomPressStart($event, -1)\"\n (pointerup)=\"OnZoomPressEnd()\"\n (pointerleave)=\"OnZoomPressEnd()\"\n (pointercancel)=\"OnZoomPressEnd()\"\n (click)=\"OnZoomClick(-1)\"><i class=\"fa-solid fa-minus\" aria-hidden=\"true\"></i></button>\n <span class=\"zoom-pct\">{{ ZoomPercent }}%</span>\n <button type=\"button\" title=\"Zoom in (hold for continuous)\" aria-label=\"Zoom in\"\n (pointerdown)=\"OnZoomPressStart($event, 1)\"\n (pointerup)=\"OnZoomPressEnd()\"\n (pointerleave)=\"OnZoomPressEnd()\"\n (pointercancel)=\"OnZoomPressEnd()\"\n (click)=\"OnZoomClick(1)\"><i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i></button>\n <span class=\"zoom-sep\"></span>\n <button type=\"button\" title=\"Fit to content\" aria-label=\"Fit to content\" (click)=\"Fit.emit()\"><i class=\"fa-solid fa-compress\" aria-hidden=\"true\"></i></button>\n <button type=\"button\" title=\"Mini-map\" aria-label=\"Toggle mini-map\" [class.on]=\"MinimapOpen\" (click)=\"ToggleMinimap.emit()\"><i class=\"fa-regular fa-map\" aria-hidden=\"true\"></i></button>\n</div>\n"]}
1
+ {"version":3,"file":"whiteboard-zoom.component.js","sourceRoot":"","sources":["../../src/lib/whiteboard-zoom.component.ts","../../src/lib/whiteboard-zoom.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n/** Which way a zoom button points. */\ntype ZoomDirection = 1 | -1;\n\n/**\n * The bottom-right zoom cluster of the live whiteboard: zoom out / percentage / zoom in,\n * fit-to-content, and the minimap toggle. Pure presentational; the board owns the\n * viewport math and the minimap rendering.\n *\n * HOLD-TO-ZOOM: a plain click on +/− still emits the existing single preset step\n * ({@link ZoomIn} / {@link ZoomOut}); holding the button down (pointerdown held past a\n * short delay) emits {@link ZoomBy} factors (~3.5%) every 50 ms for smooth continuous\n * zooming, stopping on pointerup / pointerleave / pointercancel / destroy — the timers\n * never leak. The board clamps to its usual 25%–200% limits.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-whiteboard-zoom',\n imports: [CommonModule],\n templateUrl: './whiteboard-zoom.component.html',\n styleUrl: './whiteboard-zoom.component.css'\n})\nexport class RealtimeWhiteboardZoomComponent implements OnDestroy {\n /** How long a press must be held before continuous zooming kicks in. */\n private static readonly holdDelayMs = 350;\n /** Continuous-zoom tick cadence while held. */\n private static readonly holdIntervalMs = 50;\n /** Multiplicative zoom factor per held tick (~3.5%). */\n private static readonly holdFactor = 1.035;\n\n /** Current zoom as a percentage (e.g. 90). */\n @Input() ZoomPercent = 100;\n /** Whether the minimap is currently shown (highlights the map button). */\n @Input() MinimapOpen = false;\n\n /** Single preset step out (a plain click on −). */\n @Output() ZoomOut = new EventEmitter<void>();\n /** Single preset step in (a plain click on +). */\n @Output() ZoomIn = new EventEmitter<void>();\n /**\n * Continuous (held-button) zoom tick: a multiplicative factor (>1 zooms in, <1 zooms\n * out) emitted every 50 ms while + or − is held. Wire to the board's `ZoomByFactor`.\n */\n @Output() ZoomBy = new EventEmitter<number>();\n @Output() Fit = new EventEmitter<void>();\n @Output() ToggleMinimap = new EventEmitter<void>();\n\n private holdDelayTimer: ReturnType<typeof setTimeout> | null = null;\n private holdIntervalTimer: ReturnType<typeof setInterval> | null = null;\n /** Set once continuous ticks started, so the trailing click doesn't ALSO step. */\n private suppressNextClick = false;\n\n ngOnDestroy(): void {\n this.stopHold();\n }\n\n /** Pointer down on +/−: arm the hold — after the delay, tick {@link ZoomBy} repeatedly. */\n public OnZoomPressStart(event: PointerEvent, direction: ZoomDirection): void {\n if (event.button !== 0) {\n return;\n }\n this.stopHold();\n this.suppressNextClick = false;\n this.holdDelayTimer = setTimeout(() => {\n this.holdDelayTimer = null;\n this.suppressNextClick = true;\n const factor = direction === 1\n ? RealtimeWhiteboardZoomComponent.holdFactor\n : 1 / RealtimeWhiteboardZoomComponent.holdFactor;\n this.ZoomBy.emit(factor); // first tick fires immediately when the hold engages\n this.holdIntervalTimer = setInterval(() => this.ZoomBy.emit(factor), RealtimeWhiteboardZoomComponent.holdIntervalMs);\n }, RealtimeWhiteboardZoomComponent.holdDelayMs);\n }\n\n /** Pointer up / leave / cancel: stop any pending or running continuous zoom. */\n public OnZoomPressEnd(): void {\n this.stopHold();\n }\n\n /** The click that follows the press: a single preset step unless a hold already zoomed. */\n public OnZoomClick(direction: ZoomDirection): void {\n if (this.suppressNextClick) {\n this.suppressNextClick = false;\n return;\n }\n if (direction === 1) {\n this.ZoomIn.emit();\n }\n else {\n this.ZoomOut.emit();\n }\n }\n\n /** Clear both hold timers (idempotent — safe from any stop path). */\n private stopHold(): void {\n if (this.holdDelayTimer !== null) {\n clearTimeout(this.holdDelayTimer);\n this.holdDelayTimer = null;\n }\n if (this.holdIntervalTimer !== null) {\n clearInterval(this.holdIntervalTimer);\n this.holdIntervalTimer = null;\n }\n }\n}\n","<div class=\"zoom-cluster\">\n <button type=\"button\" title=\"Zoom out (hold for continuous)\" aria-label=\"Zoom out\"\n (pointerdown)=\"OnZoomPressStart($event, -1)\"\n (pointerup)=\"OnZoomPressEnd()\"\n (pointerleave)=\"OnZoomPressEnd()\"\n (pointercancel)=\"OnZoomPressEnd()\"\n (click)=\"OnZoomClick(-1)\"><i class=\"fa-solid fa-minus\" aria-hidden=\"true\"></i></button>\n <span class=\"zoom-pct\">{{ ZoomPercent }}%</span>\n <button type=\"button\" title=\"Zoom in (hold for continuous)\" aria-label=\"Zoom in\"\n (pointerdown)=\"OnZoomPressStart($event, 1)\"\n (pointerup)=\"OnZoomPressEnd()\"\n (pointerleave)=\"OnZoomPressEnd()\"\n (pointercancel)=\"OnZoomPressEnd()\"\n (click)=\"OnZoomClick(1)\"><i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i></button>\n <span class=\"zoom-sep\"></span>\n <button type=\"button\" title=\"Fit to content\" aria-label=\"Fit to content\" (click)=\"Fit.emit()\"><i class=\"fa-solid fa-compress\" aria-hidden=\"true\"></i></button>\n <button type=\"button\" title=\"Mini-map\" aria-label=\"Toggle mini-map\" [class.on]=\"MinimapOpen\" (click)=\"ToggleMinimap.emit()\"><i class=\"fa-regular fa-map\" aria-hidden=\"true\"></i></button>\n</div>\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-whiteboard",
3
- "version": "6.1.4",
3
+ "version": "6.2.0-edge.1",
4
4
  "description": "MemberJunction: Generic collaborative whiteboard for any Angular application — Angular-free state engine with undo/redo + change journal, agent perception deltas, a programmatic (AI-agent-ready) mutation tool API, sandboxed HTML widgets with an input bridge, markdown panels, and self-contained HTML/SVG export",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -20,7 +20,7 @@
20
20
  "devDependencies": {
21
21
  "@angular/compiler": "21.2.22",
22
22
  "@angular/compiler-cli": "21.2.22",
23
- "@memberjunction/ng-test-utils": "6.1.4",
23
+ "@memberjunction/ng-test-utils": "6.2.0-edge.1",
24
24
  "vitest": "^4.0.18"
25
25
  },
26
26
  "peerDependencies": {
@@ -29,10 +29,10 @@
29
29
  "@angular/platform-browser": "^21.2.22"
30
30
  },
31
31
  "dependencies": {
32
- "@memberjunction/ng-ui-components": "6.1.4",
33
- "@memberjunction/global": "6.1.4",
34
- "@memberjunction/ng-code-editor": "6.1.4",
35
- "@memberjunction/ng-markdown": "6.1.4",
32
+ "@memberjunction/ng-ui-components": "6.2.0-edge.1",
33
+ "@memberjunction/global": "6.2.0-edge.1",
34
+ "@memberjunction/ng-code-editor": "6.2.0-edge.1",
35
+ "@memberjunction/ng-markdown": "6.2.0-edge.1",
36
36
  "rxjs": "^7.8.2",
37
37
  "tslib": "^2.8.1"
38
38
  },