@fieldnotes/core 0.19.0 → 0.20.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/README.md +472 -472
- package/dist/index.cjs +84 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +83 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -92,6 +92,7 @@ __export(index_exports, {
|
|
|
92
92
|
getHexDistance: () => getHexDistance,
|
|
93
93
|
isBindable: () => isBindable,
|
|
94
94
|
isNearBezier: () => isNearBezier,
|
|
95
|
+
isNoteContentEmpty: () => isNoteContentEmpty,
|
|
95
96
|
parseState: () => parseState,
|
|
96
97
|
sanitizeNoteHtml: () => sanitizeNoteHtml,
|
|
97
98
|
setFontSize: () => setFontSize,
|
|
@@ -382,6 +383,12 @@ function sanitizeNode(node) {
|
|
|
382
383
|
sanitizeNode(el);
|
|
383
384
|
}
|
|
384
385
|
}
|
|
386
|
+
function isNoteContentEmpty(html) {
|
|
387
|
+
if (!html) return true;
|
|
388
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
389
|
+
const text = doc.body.textContent ?? "";
|
|
390
|
+
return text.replace(/\u00a0/g, " ").trim().length === 0;
|
|
391
|
+
}
|
|
385
392
|
function sanitizeAttributes(el, tag) {
|
|
386
393
|
const attrs = Array.from(el.attributes);
|
|
387
394
|
for (const attr of attrs) {
|
|
@@ -3473,17 +3480,36 @@ var FORMAT_SHORTCUTS = {
|
|
|
3473
3480
|
i: toggleItalic,
|
|
3474
3481
|
u: toggleUnderline
|
|
3475
3482
|
};
|
|
3483
|
+
function ensureEditorStyles() {
|
|
3484
|
+
if (document.querySelector("style[data-fieldnotes-editor]")) return;
|
|
3485
|
+
const style = document.createElement("style");
|
|
3486
|
+
style.setAttribute("data-fieldnotes-editor", "");
|
|
3487
|
+
style.textContent = `[data-fn-placeholder][data-fn-empty='true']::before {
|
|
3488
|
+
content: attr(data-fn-placeholder);
|
|
3489
|
+
color: #9e9e9e;
|
|
3490
|
+
position: absolute;
|
|
3491
|
+
pointer-events: none;
|
|
3492
|
+
}`;
|
|
3493
|
+
document.head.appendChild(style);
|
|
3494
|
+
}
|
|
3495
|
+
function isNodeEmpty(node) {
|
|
3496
|
+
const text = node.textContent ?? "";
|
|
3497
|
+
return text.replace(/\u00a0/g, " ").trim().length === 0;
|
|
3498
|
+
}
|
|
3476
3499
|
var NoteEditor = class {
|
|
3477
3500
|
editingId = null;
|
|
3478
3501
|
editingNode = null;
|
|
3479
3502
|
blurHandler = null;
|
|
3480
3503
|
keyHandler = null;
|
|
3481
3504
|
pointerHandler = null;
|
|
3505
|
+
inputHandler = null;
|
|
3482
3506
|
pendingEditId = null;
|
|
3483
3507
|
onStopCallback = null;
|
|
3484
3508
|
toolbar;
|
|
3509
|
+
placeholder;
|
|
3485
3510
|
constructor(options) {
|
|
3486
3511
|
this.toolbar = options?.toolbar === false ? null : new NoteToolbar(options?.fontSizePresets);
|
|
3512
|
+
this.placeholder = options?.placeholder ?? "Type\u2026";
|
|
3487
3513
|
}
|
|
3488
3514
|
get isEditing() {
|
|
3489
3515
|
return this.editingId !== null;
|
|
@@ -3518,6 +3544,11 @@ var NoteEditor = class {
|
|
|
3518
3544
|
if (this.pointerHandler) {
|
|
3519
3545
|
this.editingNode.removeEventListener("pointerdown", this.pointerHandler);
|
|
3520
3546
|
}
|
|
3547
|
+
if (this.inputHandler) {
|
|
3548
|
+
this.editingNode.removeEventListener("input", this.inputHandler);
|
|
3549
|
+
}
|
|
3550
|
+
this.editingNode.removeAttribute("data-fn-placeholder");
|
|
3551
|
+
this.editingNode.removeAttribute("data-fn-empty");
|
|
3521
3552
|
const text = sanitizeNoteHtml(this.editingNode.innerHTML);
|
|
3522
3553
|
store.update(this.editingId, { text });
|
|
3523
3554
|
this.editingNode.contentEditable = "false";
|
|
@@ -3534,6 +3565,7 @@ var NoteEditor = class {
|
|
|
3534
3565
|
this.blurHandler = null;
|
|
3535
3566
|
this.keyHandler = null;
|
|
3536
3567
|
this.pointerHandler = null;
|
|
3568
|
+
this.inputHandler = null;
|
|
3537
3569
|
}
|
|
3538
3570
|
destroy(store) {
|
|
3539
3571
|
this.pendingEditId = null;
|
|
@@ -3564,6 +3596,13 @@ var NoteEditor = class {
|
|
|
3564
3596
|
selection.removeAllRanges();
|
|
3565
3597
|
selection.addRange(range);
|
|
3566
3598
|
}
|
|
3599
|
+
ensureEditorStyles();
|
|
3600
|
+
node.setAttribute("data-fn-placeholder", this.placeholder);
|
|
3601
|
+
node.setAttribute("data-fn-empty", String(isNodeEmpty(node)));
|
|
3602
|
+
this.inputHandler = () => {
|
|
3603
|
+
node.setAttribute("data-fn-empty", String(isNodeEmpty(node)));
|
|
3604
|
+
};
|
|
3605
|
+
node.addEventListener("input", this.inputHandler);
|
|
3567
3606
|
this.toolbar?.show(node);
|
|
3568
3607
|
this.blurHandler = (e) => {
|
|
3569
3608
|
const related = e.relatedTarget;
|
|
@@ -5002,7 +5041,8 @@ var Viewport = class {
|
|
|
5002
5041
|
});
|
|
5003
5042
|
this.noteEditor = new NoteEditor({
|
|
5004
5043
|
fontSizePresets: options.fontSizePresets,
|
|
5005
|
-
toolbar: options.toolbar
|
|
5044
|
+
toolbar: options.toolbar,
|
|
5045
|
+
placeholder: options.placeholder
|
|
5006
5046
|
});
|
|
5007
5047
|
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
5008
5048
|
this.onHtmlElementMount = options.onHtmlElementMount;
|
|
@@ -5348,7 +5388,16 @@ var Viewport = class {
|
|
|
5348
5388
|
}
|
|
5349
5389
|
onTextEditStop(elementId) {
|
|
5350
5390
|
const element = this.store.getById(elementId);
|
|
5351
|
-
if (!element
|
|
5391
|
+
if (!element) return;
|
|
5392
|
+
if (element.type === "note") {
|
|
5393
|
+
if (isNoteContentEmpty(element.text)) {
|
|
5394
|
+
this.historyRecorder.begin();
|
|
5395
|
+
this.store.remove(elementId);
|
|
5396
|
+
this.historyRecorder.commit();
|
|
5397
|
+
}
|
|
5398
|
+
return;
|
|
5399
|
+
}
|
|
5400
|
+
if (element.type !== "text") return;
|
|
5352
5401
|
if (!element.text || element.text.trim() === "") {
|
|
5353
5402
|
this.historyRecorder.begin();
|
|
5354
5403
|
this.store.remove(elementId);
|
|
@@ -5897,6 +5946,7 @@ var SelectTool = class {
|
|
|
5897
5946
|
pendingSingleSelectId = null;
|
|
5898
5947
|
hasDragged = false;
|
|
5899
5948
|
resizeAspectRatio = 0;
|
|
5949
|
+
hoveredId = null;
|
|
5900
5950
|
get selectedIds() {
|
|
5901
5951
|
return [...this._selectedIds];
|
|
5902
5952
|
}
|
|
@@ -5913,6 +5963,7 @@ var SelectTool = class {
|
|
|
5913
5963
|
onDeactivate(ctx) {
|
|
5914
5964
|
this._selectedIds = [];
|
|
5915
5965
|
this.mode = { type: "idle" };
|
|
5966
|
+
this.hoveredId = null;
|
|
5916
5967
|
ctx.setCursor?.("default");
|
|
5917
5968
|
}
|
|
5918
5969
|
snap(point, ctx) {
|
|
@@ -5920,6 +5971,7 @@ var SelectTool = class {
|
|
|
5920
5971
|
}
|
|
5921
5972
|
onPointerDown(state, ctx) {
|
|
5922
5973
|
this.ctx = ctx;
|
|
5974
|
+
this.setHovered(null, ctx);
|
|
5923
5975
|
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
5924
5976
|
this.lastWorld = this.snap(world, ctx);
|
|
5925
5977
|
this.currentWorld = world;
|
|
@@ -6062,7 +6114,8 @@ var SelectTool = class {
|
|
|
6062
6114
|
}
|
|
6063
6115
|
onHover(state, ctx) {
|
|
6064
6116
|
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
6065
|
-
this.updateHoverCursor(world, ctx);
|
|
6117
|
+
const hoverId = this.updateHoverCursor(world, ctx);
|
|
6118
|
+
this.setHovered(hoverId, ctx);
|
|
6066
6119
|
}
|
|
6067
6120
|
renderOverlay(canvasCtx) {
|
|
6068
6121
|
this.renderMarquee(canvasCtx);
|
|
@@ -6083,6 +6136,23 @@ var SelectTool = class {
|
|
|
6083
6136
|
canvasCtx.restore();
|
|
6084
6137
|
}
|
|
6085
6138
|
}
|
|
6139
|
+
if (this.hoveredId && this.ctx && this.mode.type === "idle") {
|
|
6140
|
+
if (!this._selectedIds.includes(this.hoveredId)) {
|
|
6141
|
+
const el = this.ctx.store.getById(this.hoveredId);
|
|
6142
|
+
if (el) {
|
|
6143
|
+
const b = getElementBounds(el);
|
|
6144
|
+
if (b) {
|
|
6145
|
+
canvasCtx.save();
|
|
6146
|
+
canvasCtx.strokeStyle = "#2196F3";
|
|
6147
|
+
canvasCtx.globalAlpha = 0.35;
|
|
6148
|
+
canvasCtx.lineWidth = 1.5 / this.ctx.camera.zoom;
|
|
6149
|
+
canvasCtx.setLineDash([]);
|
|
6150
|
+
canvasCtx.strokeRect(b.x, b.y, b.w, b.h);
|
|
6151
|
+
canvasCtx.restore();
|
|
6152
|
+
}
|
|
6153
|
+
}
|
|
6154
|
+
}
|
|
6155
|
+
}
|
|
6086
6156
|
}
|
|
6087
6157
|
updateArrowsBoundTo(ids, ctx) {
|
|
6088
6158
|
const movedNonArrowIds = /* @__PURE__ */ new Set();
|
|
@@ -6131,20 +6201,26 @@ var SelectTool = class {
|
|
|
6131
6201
|
const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);
|
|
6132
6202
|
if (arrowHit) {
|
|
6133
6203
|
ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));
|
|
6134
|
-
return;
|
|
6204
|
+
return null;
|
|
6135
6205
|
}
|
|
6136
6206
|
const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);
|
|
6137
6207
|
if (templateResizeHit) {
|
|
6138
6208
|
ctx.setCursor?.("nwse-resize");
|
|
6139
|
-
return;
|
|
6209
|
+
return null;
|
|
6140
6210
|
}
|
|
6141
6211
|
const resizeHit = this.hitTestResizeHandle(world, ctx);
|
|
6142
6212
|
if (resizeHit) {
|
|
6143
6213
|
ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);
|
|
6144
|
-
return;
|
|
6214
|
+
return null;
|
|
6145
6215
|
}
|
|
6146
6216
|
const hit = this.hitTest(world, ctx);
|
|
6147
6217
|
ctx.setCursor?.(hit ? "move" : "default");
|
|
6218
|
+
return hit ? hit.id : null;
|
|
6219
|
+
}
|
|
6220
|
+
setHovered(id, ctx) {
|
|
6221
|
+
if (this.hoveredId === id) return;
|
|
6222
|
+
this.hoveredId = id;
|
|
6223
|
+
ctx.requestRender();
|
|
6148
6224
|
}
|
|
6149
6225
|
handleResize(world, ctx, shiftKey = false) {
|
|
6150
6226
|
if (this.mode.type !== "resizing") return;
|
|
@@ -7251,7 +7327,7 @@ var TemplateTool = class {
|
|
|
7251
7327
|
};
|
|
7252
7328
|
|
|
7253
7329
|
// src/index.ts
|
|
7254
|
-
var VERSION = "0.
|
|
7330
|
+
var VERSION = "0.20.0";
|
|
7255
7331
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7256
7332
|
0 && (module.exports = {
|
|
7257
7333
|
AddElementCommand,
|
|
@@ -7326,6 +7402,7 @@ var VERSION = "0.19.0";
|
|
|
7326
7402
|
getHexDistance,
|
|
7327
7403
|
isBindable,
|
|
7328
7404
|
isNearBezier,
|
|
7405
|
+
isNoteContentEmpty,
|
|
7329
7406
|
parseState,
|
|
7330
7407
|
sanitizeNoteHtml,
|
|
7331
7408
|
setFontSize,
|