tigma 1.0.3 → 1.0.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.
- package/README.md +6 -3
- package/dist/index.js +90 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
A terminal-based design tool for creating ASCII diagrams and designs.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Running
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
bunx tigma
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Currently this requires [bun](http://bun.sh).
|
|
12
|
+
|
|
11
13
|
## Usage
|
|
12
14
|
|
|
13
15
|
```bash
|
|
@@ -47,6 +49,7 @@ Switch between tools using keyboard shortcuts:
|
|
|
47
49
|
- **Shift+Click** to add/remove objects from selection (multi-select)
|
|
48
50
|
- **Click+Drag** to move selected objects
|
|
49
51
|
- **Click on empty space** to deselect all
|
|
52
|
+
- **Click+Drag on empty space** to box-select multiple items (hold Shift to add)
|
|
50
53
|
|
|
51
54
|
#### Rectangle Resizing
|
|
52
55
|
|
|
@@ -125,7 +128,7 @@ Designs are saved as `.tigma` files in JSON format. The file stores:
|
|
|
125
128
|
## Features
|
|
126
129
|
|
|
127
130
|
- **Layered rendering**: Objects stack based on z-index; newer objects appear on top by default
|
|
128
|
-
- **Multi-selection**: Select multiple objects with Shift+Click
|
|
131
|
+
- **Multi-selection**: Select multiple objects with Shift+Click or box-select
|
|
129
132
|
- **Undo/Redo**: Up to 100 history snapshots
|
|
130
133
|
- **Terminal responsive**: Adapts to terminal resize events
|
|
131
134
|
- **Mouse support**: Full mouse interaction including hover highlighting
|
package/dist/index.js
CHANGED
|
@@ -14876,6 +14876,8 @@ class CanvasApp {
|
|
|
14876
14876
|
currentFilePath = null;
|
|
14877
14877
|
saveStatusMessage = null;
|
|
14878
14878
|
saveStatusTimeout = 0;
|
|
14879
|
+
isSelecting = false;
|
|
14880
|
+
isSelectionPending = false;
|
|
14879
14881
|
showSavePrompt = false;
|
|
14880
14882
|
savePromptInput = "";
|
|
14881
14883
|
gridWidth = 0;
|
|
@@ -15351,6 +15353,11 @@ class CanvasApp {
|
|
|
15351
15353
|
if (event.x !== this.mouseDownX || event.y !== this.mouseDownY) {
|
|
15352
15354
|
this.hasDragged = true;
|
|
15353
15355
|
}
|
|
15356
|
+
if (this.isSelectionPending && this.hasDragged && this.currentTool === "move") {
|
|
15357
|
+
this.isSelectionPending = false;
|
|
15358
|
+
this.isSelecting = true;
|
|
15359
|
+
this.isDraggingMouse = true;
|
|
15360
|
+
}
|
|
15354
15361
|
if (this.isDraggingSelection) {
|
|
15355
15362
|
const dx = event.x - this.dragStartX;
|
|
15356
15363
|
const dy = event.y - this.dragStartY;
|
|
@@ -15362,7 +15369,7 @@ class CanvasApp {
|
|
|
15362
15369
|
if (rectId !== undefined) {
|
|
15363
15370
|
this.resizeRect(rectId, event.x, event.y);
|
|
15364
15371
|
}
|
|
15365
|
-
} else if (this.isDrawingRect || this.isDrawingLine) {
|
|
15372
|
+
} else if (this.isDrawingRect || this.isDrawingLine || this.isSelecting) {
|
|
15366
15373
|
this.drawCursorX = Math.max(0, Math.min(this.gridWidth - 1, event.x));
|
|
15367
15374
|
this.drawCursorY = Math.max(0, Math.min(this.gridHeight - 1, event.y));
|
|
15368
15375
|
this.renderer.requestRender();
|
|
@@ -15380,6 +15387,11 @@ class CanvasApp {
|
|
|
15380
15387
|
this.drawCursorY = Math.max(0, Math.min(this.gridHeight - 1, event.y));
|
|
15381
15388
|
this.commitLine();
|
|
15382
15389
|
}
|
|
15390
|
+
if (this.isSelecting) {
|
|
15391
|
+
this.drawCursorX = Math.max(0, Math.min(this.gridWidth - 1, event.x));
|
|
15392
|
+
this.drawCursorY = Math.max(0, Math.min(this.gridHeight - 1, event.y));
|
|
15393
|
+
this.commitSelection();
|
|
15394
|
+
}
|
|
15383
15395
|
if (this.clickedOnSelectedTextBox && !this.hasDragged && this.selectedTextBoxIds.size === 1) {
|
|
15384
15396
|
const textBoxId = this.selectedTextBoxIds.values().next().value;
|
|
15385
15397
|
const textBox = this.textBoxes.find((b) => b.id === textBoxId);
|
|
@@ -15398,6 +15410,8 @@ class CanvasApp {
|
|
|
15398
15410
|
this.isDraggingMouse = false;
|
|
15399
15411
|
this.clickedOnSelectedTextBox = false;
|
|
15400
15412
|
this.hasDragged = false;
|
|
15413
|
+
this.isSelecting = false;
|
|
15414
|
+
this.isSelectionPending = false;
|
|
15401
15415
|
return;
|
|
15402
15416
|
}
|
|
15403
15417
|
if (event.type === "down") {
|
|
@@ -15502,6 +15516,11 @@ class CanvasApp {
|
|
|
15502
15516
|
if (!shiftHeld) {
|
|
15503
15517
|
this.clearSelection();
|
|
15504
15518
|
}
|
|
15519
|
+
this.isSelectionPending = true;
|
|
15520
|
+
this.drawStartX = event.x;
|
|
15521
|
+
this.drawStartY = event.y;
|
|
15522
|
+
this.drawCursorX = event.x;
|
|
15523
|
+
this.drawCursorY = event.y;
|
|
15505
15524
|
this.renderer.requestRender();
|
|
15506
15525
|
return;
|
|
15507
15526
|
}
|
|
@@ -15877,6 +15896,40 @@ class CanvasApp {
|
|
|
15877
15896
|
this.isDrawingLine = false;
|
|
15878
15897
|
this.setTool("move");
|
|
15879
15898
|
}
|
|
15899
|
+
commitSelection() {
|
|
15900
|
+
if (!this.isSelecting)
|
|
15901
|
+
return;
|
|
15902
|
+
const selX1 = Math.min(this.drawStartX, this.drawCursorX);
|
|
15903
|
+
const selX2 = Math.max(this.drawStartX, this.drawCursorX);
|
|
15904
|
+
const selY1 = Math.min(this.drawStartY, this.drawCursorY);
|
|
15905
|
+
const selY2 = Math.max(this.drawStartY, this.drawCursorY);
|
|
15906
|
+
const isIntersecting = (x1, y1, x2, y2) => {
|
|
15907
|
+
return !(x2 < selX1 || x1 > selX2 || y2 < selY1 || y1 > selY2);
|
|
15908
|
+
};
|
|
15909
|
+
for (const box of this.textBoxes) {
|
|
15910
|
+
const width = Math.max(1, this.getTextLength(box));
|
|
15911
|
+
const bx1 = box.x;
|
|
15912
|
+
const bx2 = box.x + width - 1;
|
|
15913
|
+
const by1 = box.y;
|
|
15914
|
+
const by2 = box.y;
|
|
15915
|
+
if (isIntersecting(bx1, by1, bx2, by2)) {
|
|
15916
|
+
this.selectTextBox(box.id, true);
|
|
15917
|
+
}
|
|
15918
|
+
}
|
|
15919
|
+
for (const rect of this.rectangles) {
|
|
15920
|
+
const { x1, y1, x2, y2 } = this.normalizeRect(rect);
|
|
15921
|
+
if (isIntersecting(x1, y1, x2, y2)) {
|
|
15922
|
+
this.selectRect(rect.id, true);
|
|
15923
|
+
}
|
|
15924
|
+
}
|
|
15925
|
+
for (const line of this.lines) {
|
|
15926
|
+
const { x1, y1, x2, y2 } = this.normalizeLine(line);
|
|
15927
|
+
if (isIntersecting(x1, y1, x2, y2)) {
|
|
15928
|
+
this.selectLine(line.id, true);
|
|
15929
|
+
}
|
|
15930
|
+
}
|
|
15931
|
+
this.isSelecting = false;
|
|
15932
|
+
}
|
|
15880
15933
|
deleteLine(id) {
|
|
15881
15934
|
this.saveSnapshot();
|
|
15882
15935
|
this.lines = this.lines.filter((l) => l.id !== id);
|
|
@@ -16012,6 +16065,8 @@ class CanvasApp {
|
|
|
16012
16065
|
}
|
|
16013
16066
|
this.isDrawingRect = false;
|
|
16014
16067
|
this.isDrawingLine = false;
|
|
16068
|
+
this.isSelecting = false;
|
|
16069
|
+
this.isSelectionPending = false;
|
|
16015
16070
|
this.isDraggingMouse = false;
|
|
16016
16071
|
this.currentTool = tool;
|
|
16017
16072
|
if (tool !== "move") {
|
|
@@ -16057,6 +16112,9 @@ class CanvasApp {
|
|
|
16057
16112
|
if (this.isDrawingLine) {
|
|
16058
16113
|
this.renderLinePreview(buffer);
|
|
16059
16114
|
}
|
|
16115
|
+
if (this.isSelecting) {
|
|
16116
|
+
this.renderSelectionBoxPreview(buffer);
|
|
16117
|
+
}
|
|
16060
16118
|
if (this.activeTextBoxId !== null) {
|
|
16061
16119
|
const activeBox = this.textBoxes.find((b) => b.id === this.activeTextBoxId);
|
|
16062
16120
|
if (activeBox) {
|
|
@@ -16339,6 +16397,36 @@ class CanvasApp {
|
|
|
16339
16397
|
buffer.setCell(x, y, char, fg2, bg2, attrs);
|
|
16340
16398
|
}
|
|
16341
16399
|
}
|
|
16400
|
+
renderSelectionBoxPreview(buffer) {
|
|
16401
|
+
const x1 = Math.min(this.drawStartX, this.drawCursorX);
|
|
16402
|
+
const x2 = Math.max(this.drawStartX, this.drawCursorX);
|
|
16403
|
+
const y1 = Math.min(this.drawStartY, this.drawCursorY);
|
|
16404
|
+
const y2 = Math.max(this.drawStartY, this.drawCursorY);
|
|
16405
|
+
const fg2 = this.toolbarActiveColor;
|
|
16406
|
+
for (let y = y1;y <= y2; y++) {
|
|
16407
|
+
for (let x = x1;x <= x2; x++) {
|
|
16408
|
+
if (x < 0 || x >= this.gridWidth || y < 0 || y >= this.gridHeight)
|
|
16409
|
+
continue;
|
|
16410
|
+
let char = "";
|
|
16411
|
+
if (y === y1 && x === x1)
|
|
16412
|
+
char = "+";
|
|
16413
|
+
else if (y === y1 && x === x2)
|
|
16414
|
+
char = "+";
|
|
16415
|
+
else if (y === y2 && x === x1)
|
|
16416
|
+
char = "+";
|
|
16417
|
+
else if (y === y2 && x === x2)
|
|
16418
|
+
char = "+";
|
|
16419
|
+
else if (y === y1 || y === y2)
|
|
16420
|
+
char = "-";
|
|
16421
|
+
else if (x === x1 || x === x2)
|
|
16422
|
+
char = "\u2502";
|
|
16423
|
+
if (char) {
|
|
16424
|
+
const currentBg = this.readBufferBg(buffer, x, y);
|
|
16425
|
+
buffer.setCell(x, y, char, fg2, currentBg, 0);
|
|
16426
|
+
}
|
|
16427
|
+
}
|
|
16428
|
+
}
|
|
16429
|
+
}
|
|
16342
16430
|
getLineChar(x1, y1, x2, y2, index, total) {
|
|
16343
16431
|
const dx = x2 - x1;
|
|
16344
16432
|
const dy = y2 - y1;
|
|
@@ -16600,7 +16688,7 @@ class CanvasApp {
|
|
|
16600
16688
|
if (this.activeTextBoxId !== null) {
|
|
16601
16689
|
modeText = "| Editing (Esc to finish)";
|
|
16602
16690
|
} else if (this.currentTool === "move") {
|
|
16603
|
-
modeText = "| Click to select, drag to move";
|
|
16691
|
+
modeText = "| Click to select, drag to move, drag empty space to box-select";
|
|
16604
16692
|
} else if (this.currentTool === "text") {
|
|
16605
16693
|
modeText = "| Click to add/edit text";
|
|
16606
16694
|
} else if (this.isDrawingRect || this.isDrawingLine) {
|