@teachinglab/omd 0.7.2 → 0.7.4

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.
@@ -41,6 +41,11 @@ export class SelectTool extends Tool {
41
41
  /** @private - OMD dragging state */
42
42
  this.isDraggingOMD = false;
43
43
  this.draggedOMDElement = null;
44
+
45
+ /** @private - Stroke dragging state */
46
+ this.isDraggingStrokes = false;
47
+ this.dragStartPoint = null;
48
+ this.potentialDeselect = null;
44
49
 
45
50
  // Initialize resize handle manager for OMD visuals
46
51
  this.resizeHandleManager = new ResizeHandleManager(canvas);
@@ -78,9 +83,33 @@ export class SelectTool extends Tool {
78
83
  }
79
84
 
80
85
  if (segmentSelection) {
81
- // Clicking on a stroke segment - clear OMD selection and handle segment selection
82
- this.resizeHandleManager.clearSelection();
83
- this._handleSegmentClick(segmentSelection, event.shiftKey);
86
+ // Check if already selected
87
+ const isSelected = this._isSegmentSelected(segmentSelection);
88
+
89
+ if (isSelected) {
90
+ // Already selected - prepare for drag, but don't deselect yet
91
+ this.isDraggingStrokes = true;
92
+ this.dragStartPoint = { x: event.x, y: event.y };
93
+ this.potentialDeselect = segmentSelection;
94
+
95
+ // Set isDrawing so we get pointermove events
96
+ if (this.canvas.eventManager) {
97
+ this.canvas.eventManager.isDrawing = true;
98
+ }
99
+ return;
100
+ } else {
101
+ // Clicking on a stroke segment - clear OMD selection and handle segment selection
102
+ this.resizeHandleManager.clearSelection();
103
+ this._handleSegmentClick(segmentSelection, event.shiftKey);
104
+
105
+ // Prepare for drag immediately after selection
106
+ this.isDraggingStrokes = true;
107
+ this.dragStartPoint = { x: event.x, y: event.y };
108
+
109
+ if (this.canvas.eventManager) {
110
+ this.canvas.eventManager.isDrawing = true;
111
+ }
112
+ }
84
113
  } else if (omdElement) {
85
114
  // Clicking on an OMD visual - clear segment selection and select OMD
86
115
  if (!event.shiftKey) {
@@ -132,6 +161,37 @@ export class SelectTool extends Tool {
132
161
  this._dragOMDElement(event.x, event.y);
133
162
  return;
134
163
  }
164
+
165
+ // Handle stroke dragging if in progress
166
+ if (this.isDraggingStrokes && this.dragStartPoint) {
167
+ const dx = event.x - this.dragStartPoint.x;
168
+ const dy = event.y - this.dragStartPoint.y;
169
+
170
+ if (dx === 0 && dy === 0) return;
171
+
172
+ // If we moved, it's a drag, so cancel potential deselect
173
+ this.potentialDeselect = null;
174
+
175
+ // Move all selected strokes
176
+ const movedStrokes = new Set();
177
+ for (const [strokeId, _] of this.selectedSegments) {
178
+ const stroke = this.canvas.strokes.get(strokeId);
179
+ if (stroke) {
180
+ stroke.move(dx, dy);
181
+ movedStrokes.add(strokeId);
182
+ }
183
+ }
184
+
185
+ this.dragStartPoint = { x: event.x, y: event.y };
186
+ this._updateSegmentSelectionVisuals();
187
+
188
+ // Emit event
189
+ this.canvas.emit('strokesMoved', {
190
+ dx, dy,
191
+ strokeIds: Array.from(movedStrokes)
192
+ });
193
+ return;
194
+ }
135
195
 
136
196
  // Handle box selection if in progress
137
197
  if (!this.isSelecting || !this.selectionBox) return;
@@ -164,6 +224,23 @@ export class SelectTool extends Tool {
164
224
  }
165
225
  return;
166
226
  }
227
+
228
+ // Handle stroke drag completion
229
+ if (this.isDraggingStrokes) {
230
+ if (this.potentialDeselect) {
231
+ // We clicked a selected segment but didn't drag -> toggle selection
232
+ this._handleSegmentClick(this.potentialDeselect, event.shiftKey);
233
+ this.potentialDeselect = null;
234
+ }
235
+
236
+ this.isDraggingStrokes = false;
237
+ this.dragStartPoint = null;
238
+
239
+ if (this.canvas.eventManager) {
240
+ this.canvas.eventManager.isDrawing = false;
241
+ }
242
+ return;
243
+ }
167
244
 
168
245
  // Handle box selection completion
169
246
  if (this.isSelecting) {
@@ -396,6 +473,17 @@ export class SelectTool extends Tool {
396
473
  return selected;
397
474
  }
398
475
 
476
+ /**
477
+ * Checks if a segment is currently selected.
478
+ * @private
479
+ * @param {{strokeId: string, segmentIndex: number}} selection - The selection to check.
480
+ * @returns {boolean}
481
+ */
482
+ _isSegmentSelected({ strokeId, segmentIndex }) {
483
+ const segmentSet = this.selectedSegments.get(strokeId);
484
+ return segmentSet ? segmentSet.has(segmentIndex) : false;
485
+ }
486
+
399
487
  /**
400
488
  * Drags the selected OMD element
401
489
  * @private
@@ -198,13 +198,13 @@ export class Toolbar {
198
198
  _updateActiveButton(toolName) {
199
199
  // Reset all buttons
200
200
  this.buttons.forEach(button => {
201
- button.setFillColor('white');
201
+ button.setFillColor(this.omdColor.lightGray);
202
202
  });
203
203
 
204
204
  // Highlight active button
205
205
  const activeButton = this.buttons.get(toolName);
206
206
  if (activeButton) {
207
- activeButton.setFillColor(this.omdColor.lightGray);
207
+ activeButton.setFillColor('white');
208
208
  this.activeButton = activeButton;
209
209
  } else {
210
210
  this.activeButton = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teachinglab/omd",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "omd",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -35,6 +35,14 @@ export class omdExpression extends omdMetaExpression
35
35
  const parsed = parseExpressionString(data);
36
36
  if ( parsed ) data = parsed;
37
37
  }
38
+ // Handle object with 'expression' string property
39
+ else if ( typeof data === 'object' && data.expression && typeof data.expression === 'string' ) {
40
+ const parsed = parseExpressionString(data.expression);
41
+ if ( parsed ) {
42
+ // Merge parsed data into data object
43
+ data = { ...data, ...parsed };
44
+ }
45
+ }
38
46
 
39
47
  if ( typeof data.termsAndOpers != "undefined" )
40
48
  {
@@ -73,6 +81,14 @@ export class omdExpression extends omdMetaExpression
73
81
  this.operatorSet.push( P );
74
82
  this.expressionStack.addChild( P );
75
83
  }
84
+ else if ( elem.omdType == "string" )
85
+ {
86
+ // Fallback for string tokens - treat as term with variable name
87
+ var T = new omdTerm(1, elem.name, 1);
88
+ T.hideBackgroundByDefault();
89
+ this.termSet.push( T );
90
+ this.expressionStack.addChild( T );
91
+ }
76
92
  }
77
93
  }
78
94
 
@@ -108,9 +124,10 @@ export class omdExpression extends omdMetaExpression
108
124
 
109
125
  this.setWidthAndHeight( this.backRect.width, this.backRect.height );
110
126
 
111
- // Set individual width/height properties and viewBox for API compatibility
127
+ // Set individual width/height properties
112
128
  this.width = this.backRect.width;
113
129
  this.height = this.backRect.height;
114
- this.svgObject.setAttribute('viewBox', `0 0 ${this.width} ${this.height}`);
130
+ // Removed viewBox setting as it is not valid for 'g' elements and can cause rendering issues
131
+ // this.svgObject.setAttribute('viewBox', `0 0 ${this.width} ${this.height}`);
115
132
  }
116
133
  }