@fieldnotes/core 0.2.2 → 0.3.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/index.cjs +131 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -5
- package/dist/index.d.ts +44 -5
- package/dist/index.js +129 -9
- package/dist/index.js.map +1 -1
- package/package.json +18 -1
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
PencilTool: () => PencilTool,
|
|
41
41
|
RemoveElementCommand: () => RemoveElementCommand,
|
|
42
42
|
SelectTool: () => SelectTool,
|
|
43
|
+
TextTool: () => TextTool,
|
|
43
44
|
ToolManager: () => ToolManager,
|
|
44
45
|
UpdateElementCommand: () => UpdateElementCommand,
|
|
45
46
|
VERSION: () => VERSION,
|
|
@@ -50,6 +51,7 @@ __export(index_exports, {
|
|
|
50
51
|
createImage: () => createImage,
|
|
51
52
|
createNote: () => createNote,
|
|
52
53
|
createStroke: () => createStroke,
|
|
54
|
+
createText: () => createText,
|
|
53
55
|
exportState: () => exportState,
|
|
54
56
|
getArrowBounds: () => getArrowBounds,
|
|
55
57
|
getArrowControlPoint: () => getArrowControlPoint,
|
|
@@ -132,7 +134,7 @@ function validateState(data) {
|
|
|
132
134
|
migrateElement(el);
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
|
-
var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html"]);
|
|
137
|
+
var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html", "text"]);
|
|
136
138
|
function validateElement(el) {
|
|
137
139
|
if (!el || typeof el !== "object") {
|
|
138
140
|
throw new Error("Invalid element: expected an object");
|
|
@@ -815,7 +817,7 @@ function smoothToSegments(points) {
|
|
|
815
817
|
}
|
|
816
818
|
|
|
817
819
|
// src/elements/element-renderer.ts
|
|
818
|
-
var DOM_ELEMENT_TYPES = /* @__PURE__ */ new Set(["note", "image", "html"]);
|
|
820
|
+
var DOM_ELEMENT_TYPES = /* @__PURE__ */ new Set(["note", "image", "html", "text"]);
|
|
819
821
|
var ARROWHEAD_LENGTH = 12;
|
|
820
822
|
var ARROWHEAD_ANGLE = Math.PI / 6;
|
|
821
823
|
var ElementRenderer = class {
|
|
@@ -894,12 +896,16 @@ var NoteEditor = class {
|
|
|
894
896
|
keyHandler = null;
|
|
895
897
|
pointerHandler = null;
|
|
896
898
|
pendingEditId = null;
|
|
899
|
+
onStopCallback = null;
|
|
897
900
|
get isEditing() {
|
|
898
901
|
return this.editingId !== null;
|
|
899
902
|
}
|
|
900
903
|
get editingElementId() {
|
|
901
904
|
return this.editingId;
|
|
902
905
|
}
|
|
906
|
+
setOnStop(callback) {
|
|
907
|
+
this.onStopCallback = callback;
|
|
908
|
+
}
|
|
903
909
|
startEditing(node, elementId, store) {
|
|
904
910
|
if (this.editingId === elementId) return;
|
|
905
911
|
if (this.editingId) {
|
|
@@ -931,6 +937,9 @@ var NoteEditor = class {
|
|
|
931
937
|
if (this.pointerHandler) {
|
|
932
938
|
this.editingNode.removeEventListener("pointerdown", this.pointerHandler);
|
|
933
939
|
}
|
|
940
|
+
if (this.editingId && this.onStopCallback) {
|
|
941
|
+
this.onStopCallback(this.editingId);
|
|
942
|
+
}
|
|
934
943
|
this.editingId = null;
|
|
935
944
|
this.editingNode = null;
|
|
936
945
|
this.blurHandler = null;
|
|
@@ -1281,6 +1290,20 @@ function createHtmlElement(input) {
|
|
|
1281
1290
|
size: input.size
|
|
1282
1291
|
};
|
|
1283
1292
|
}
|
|
1293
|
+
function createText(input) {
|
|
1294
|
+
return {
|
|
1295
|
+
id: createId("text"),
|
|
1296
|
+
type: "text",
|
|
1297
|
+
position: input.position,
|
|
1298
|
+
zIndex: input.zIndex ?? 0,
|
|
1299
|
+
locked: input.locked ?? false,
|
|
1300
|
+
size: input.size ?? { w: 200, h: 28 },
|
|
1301
|
+
text: input.text ?? "",
|
|
1302
|
+
fontSize: input.fontSize ?? 16,
|
|
1303
|
+
color: input.color ?? "#1a1a1a",
|
|
1304
|
+
textAlign: input.textAlign ?? "left"
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1284
1307
|
|
|
1285
1308
|
// src/canvas/viewport.ts
|
|
1286
1309
|
var Viewport = class {
|
|
@@ -1292,6 +1315,7 @@ var Viewport = class {
|
|
|
1292
1315
|
this.toolManager = new ToolManager();
|
|
1293
1316
|
this.renderer = new ElementRenderer();
|
|
1294
1317
|
this.noteEditor = new NoteEditor();
|
|
1318
|
+
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
1295
1319
|
this.history = new HistoryStack();
|
|
1296
1320
|
this.historyRecorder = new HistoryRecorder(this.store, this.history);
|
|
1297
1321
|
this.wrapper = this.createWrapper();
|
|
@@ -1305,7 +1329,7 @@ var Viewport = class {
|
|
|
1305
1329
|
store: this.store,
|
|
1306
1330
|
requestRender: () => this.requestRender(),
|
|
1307
1331
|
switchTool: (name) => this.toolManager.setTool(name, this.toolContext),
|
|
1308
|
-
editElement: (id) => this.
|
|
1332
|
+
editElement: (id) => this.startEditingElement(id),
|
|
1309
1333
|
setCursor: (cursor) => {
|
|
1310
1334
|
this.wrapper.style.cursor = cursor;
|
|
1311
1335
|
}
|
|
@@ -1459,15 +1483,34 @@ var Viewport = class {
|
|
|
1459
1483
|
ctx.restore();
|
|
1460
1484
|
ctx.restore();
|
|
1461
1485
|
}
|
|
1462
|
-
|
|
1486
|
+
startEditingElement(id) {
|
|
1463
1487
|
const element = this.store.getById(id);
|
|
1464
|
-
if (!element || element.type !== "note") return;
|
|
1488
|
+
if (!element || element.type !== "note" && element.type !== "text") return;
|
|
1465
1489
|
this.render();
|
|
1466
1490
|
const node = this.domNodes.get(id);
|
|
1467
1491
|
if (node) {
|
|
1468
1492
|
this.noteEditor.startEditing(node, id, this.store);
|
|
1469
1493
|
}
|
|
1470
1494
|
}
|
|
1495
|
+
onTextEditStop(elementId) {
|
|
1496
|
+
const element = this.store.getById(elementId);
|
|
1497
|
+
if (!element || element.type !== "text") return;
|
|
1498
|
+
if (!element.text || element.text.trim() === "") {
|
|
1499
|
+
this.historyRecorder.begin();
|
|
1500
|
+
this.store.remove(elementId);
|
|
1501
|
+
this.historyRecorder.commit();
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
const node = this.domNodes.get(elementId);
|
|
1505
|
+
if (node && "size" in element) {
|
|
1506
|
+
const measuredHeight = node.scrollHeight;
|
|
1507
|
+
if (measuredHeight !== element.size.h) {
|
|
1508
|
+
this.store.update(elementId, {
|
|
1509
|
+
size: { w: element.size.w, h: measuredHeight }
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1471
1514
|
onDblClick = (e) => {
|
|
1472
1515
|
const el = document.elementFromPoint(e.clientX, e.clientY);
|
|
1473
1516
|
const nodeEl = el?.closest("[data-element-id]");
|
|
@@ -1475,8 +1518,8 @@ var Viewport = class {
|
|
|
1475
1518
|
const elementId = nodeEl.dataset["elementId"];
|
|
1476
1519
|
if (elementId) {
|
|
1477
1520
|
const element = this.store.getById(elementId);
|
|
1478
|
-
if (element?.type === "note") {
|
|
1479
|
-
this.
|
|
1521
|
+
if (element?.type === "note" || element?.type === "text") {
|
|
1522
|
+
this.startEditingElement(elementId);
|
|
1480
1523
|
return;
|
|
1481
1524
|
}
|
|
1482
1525
|
}
|
|
@@ -1600,7 +1643,7 @@ var Viewport = class {
|
|
|
1600
1643
|
node.addEventListener("dblclick", (e) => {
|
|
1601
1644
|
e.stopPropagation();
|
|
1602
1645
|
const id = node.dataset["elementId"];
|
|
1603
|
-
if (id) this.
|
|
1646
|
+
if (id) this.startEditingElement(id);
|
|
1604
1647
|
});
|
|
1605
1648
|
}
|
|
1606
1649
|
if (!this.noteEditor.isEditing || this.noteEditor.editingElementId !== element.id) {
|
|
@@ -1641,6 +1684,42 @@ var Viewport = class {
|
|
|
1641
1684
|
node.appendChild(content);
|
|
1642
1685
|
}
|
|
1643
1686
|
}
|
|
1687
|
+
if (element.type === "text") {
|
|
1688
|
+
if (!node.dataset["initialized"]) {
|
|
1689
|
+
node.dataset["initialized"] = "true";
|
|
1690
|
+
Object.assign(node.style, {
|
|
1691
|
+
padding: "2px",
|
|
1692
|
+
fontSize: `${element.fontSize}px`,
|
|
1693
|
+
color: element.color,
|
|
1694
|
+
textAlign: element.textAlign,
|
|
1695
|
+
background: "none",
|
|
1696
|
+
border: "none",
|
|
1697
|
+
boxShadow: "none",
|
|
1698
|
+
overflow: "visible",
|
|
1699
|
+
cursor: "default",
|
|
1700
|
+
userSelect: "none",
|
|
1701
|
+
wordWrap: "break-word",
|
|
1702
|
+
whiteSpace: "pre-wrap",
|
|
1703
|
+
lineHeight: "1.4"
|
|
1704
|
+
});
|
|
1705
|
+
node.textContent = element.text || "";
|
|
1706
|
+
node.addEventListener("dblclick", (e) => {
|
|
1707
|
+
e.stopPropagation();
|
|
1708
|
+
const id = node.dataset["elementId"];
|
|
1709
|
+
if (id) this.startEditingElement(id);
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
if (!this.noteEditor.isEditing || this.noteEditor.editingElementId !== element.id) {
|
|
1713
|
+
if (node.textContent !== element.text) {
|
|
1714
|
+
node.textContent = element.text || "";
|
|
1715
|
+
}
|
|
1716
|
+
Object.assign(node.style, {
|
|
1717
|
+
fontSize: `${element.fontSize}px`,
|
|
1718
|
+
color: element.color,
|
|
1719
|
+
textAlign: element.textAlign
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1644
1723
|
}
|
|
1645
1724
|
removeDomNode(id) {
|
|
1646
1725
|
this.htmlContent.delete(id);
|
|
@@ -2394,6 +2473,47 @@ var NoteTool = class {
|
|
|
2394
2473
|
}
|
|
2395
2474
|
};
|
|
2396
2475
|
|
|
2476
|
+
// src/tools/text-tool.ts
|
|
2477
|
+
var TextTool = class {
|
|
2478
|
+
name = "text";
|
|
2479
|
+
fontSize;
|
|
2480
|
+
color;
|
|
2481
|
+
textAlign;
|
|
2482
|
+
constructor(options = {}) {
|
|
2483
|
+
this.fontSize = options.fontSize ?? 16;
|
|
2484
|
+
this.color = options.color ?? "#1a1a1a";
|
|
2485
|
+
this.textAlign = options.textAlign ?? "left";
|
|
2486
|
+
}
|
|
2487
|
+
setOptions(options) {
|
|
2488
|
+
if (options.fontSize !== void 0) this.fontSize = options.fontSize;
|
|
2489
|
+
if (options.color !== void 0) this.color = options.color;
|
|
2490
|
+
if (options.textAlign !== void 0) this.textAlign = options.textAlign;
|
|
2491
|
+
}
|
|
2492
|
+
onActivate(ctx) {
|
|
2493
|
+
ctx.setCursor?.("text");
|
|
2494
|
+
}
|
|
2495
|
+
onDeactivate(ctx) {
|
|
2496
|
+
ctx.setCursor?.("default");
|
|
2497
|
+
}
|
|
2498
|
+
onPointerDown(_state, _ctx) {
|
|
2499
|
+
}
|
|
2500
|
+
onPointerMove(_state, _ctx) {
|
|
2501
|
+
}
|
|
2502
|
+
onPointerUp(state, ctx) {
|
|
2503
|
+
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
2504
|
+
const textEl = createText({
|
|
2505
|
+
position: world,
|
|
2506
|
+
fontSize: this.fontSize,
|
|
2507
|
+
color: this.color,
|
|
2508
|
+
textAlign: this.textAlign
|
|
2509
|
+
});
|
|
2510
|
+
ctx.store.add(textEl);
|
|
2511
|
+
ctx.requestRender();
|
|
2512
|
+
ctx.switchTool?.("select");
|
|
2513
|
+
ctx.editElement?.(textEl.id);
|
|
2514
|
+
}
|
|
2515
|
+
};
|
|
2516
|
+
|
|
2397
2517
|
// src/tools/image-tool.ts
|
|
2398
2518
|
var ImageTool = class {
|
|
2399
2519
|
name = "image";
|
|
@@ -2425,7 +2545,7 @@ var ImageTool = class {
|
|
|
2425
2545
|
};
|
|
2426
2546
|
|
|
2427
2547
|
// src/index.ts
|
|
2428
|
-
var VERSION = "0.
|
|
2548
|
+
var VERSION = "0.3.0";
|
|
2429
2549
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2430
2550
|
0 && (module.exports = {
|
|
2431
2551
|
AddElementCommand,
|
|
@@ -2448,6 +2568,7 @@ var VERSION = "0.2.2";
|
|
|
2448
2568
|
PencilTool,
|
|
2449
2569
|
RemoveElementCommand,
|
|
2450
2570
|
SelectTool,
|
|
2571
|
+
TextTool,
|
|
2451
2572
|
ToolManager,
|
|
2452
2573
|
UpdateElementCommand,
|
|
2453
2574
|
VERSION,
|
|
@@ -2458,6 +2579,7 @@ var VERSION = "0.2.2";
|
|
|
2458
2579
|
createImage,
|
|
2459
2580
|
createNote,
|
|
2460
2581
|
createStroke,
|
|
2582
|
+
createText,
|
|
2461
2583
|
exportState,
|
|
2462
2584
|
getArrowBounds,
|
|
2463
2585
|
getArrowControlPoint,
|