@fieldnotes/core 0.27.0 → 0.28.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 +8 -0
- package/dist/index.cjs +138 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +138 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -50,6 +50,8 @@ interface ArrowElement extends BaseElement {
|
|
|
50
50
|
toBinding?: Binding;
|
|
51
51
|
/** Derived from from/to/bend. Redundant in serialized state — safe to omit. */
|
|
52
52
|
cachedControlPoint?: Point;
|
|
53
|
+
/** Optional text rendered at the curve midpoint. */
|
|
54
|
+
label?: string;
|
|
53
55
|
}
|
|
54
56
|
interface ImageElement extends BaseElement {
|
|
55
57
|
type: 'image';
|
|
@@ -446,6 +448,7 @@ declare class Viewport {
|
|
|
446
448
|
private readonly background;
|
|
447
449
|
private readonly renderer;
|
|
448
450
|
private readonly noteEditor;
|
|
451
|
+
private readonly arrowLabelEditor;
|
|
449
452
|
private readonly historyRecorder;
|
|
450
453
|
readonly toolContext: ToolContext;
|
|
451
454
|
private readonly marginViewport;
|
|
@@ -517,6 +520,8 @@ declare class Viewport {
|
|
|
517
520
|
private onTextEditStop;
|
|
518
521
|
private onTapDown;
|
|
519
522
|
private onDoubleTap;
|
|
523
|
+
private findArrowAt;
|
|
524
|
+
private startArrowLabelEdit;
|
|
520
525
|
private hitTestWorld;
|
|
521
526
|
stopInteracting(): void;
|
|
522
527
|
private onDragOver;
|
|
@@ -574,6 +579,7 @@ interface ArrowInput extends BaseDefaults {
|
|
|
574
579
|
width?: number;
|
|
575
580
|
fromBinding?: Binding;
|
|
576
581
|
toBinding?: Binding;
|
|
582
|
+
label?: string;
|
|
577
583
|
}
|
|
578
584
|
interface ImageInput extends BaseDefaults {
|
|
579
585
|
position: Point;
|
|
@@ -951,6 +957,6 @@ declare class TemplateTool implements Tool {
|
|
|
951
957
|
private notifyOptionsChange;
|
|
952
958
|
}
|
|
953
959
|
|
|
954
|
-
declare const VERSION = "0.
|
|
960
|
+
declare const VERSION = "0.28.0";
|
|
955
961
|
|
|
956
962
|
export { type ActiveFormats, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ interface ArrowElement extends BaseElement {
|
|
|
50
50
|
toBinding?: Binding;
|
|
51
51
|
/** Derived from from/to/bend. Redundant in serialized state — safe to omit. */
|
|
52
52
|
cachedControlPoint?: Point;
|
|
53
|
+
/** Optional text rendered at the curve midpoint. */
|
|
54
|
+
label?: string;
|
|
53
55
|
}
|
|
54
56
|
interface ImageElement extends BaseElement {
|
|
55
57
|
type: 'image';
|
|
@@ -446,6 +448,7 @@ declare class Viewport {
|
|
|
446
448
|
private readonly background;
|
|
447
449
|
private readonly renderer;
|
|
448
450
|
private readonly noteEditor;
|
|
451
|
+
private readonly arrowLabelEditor;
|
|
449
452
|
private readonly historyRecorder;
|
|
450
453
|
readonly toolContext: ToolContext;
|
|
451
454
|
private readonly marginViewport;
|
|
@@ -517,6 +520,8 @@ declare class Viewport {
|
|
|
517
520
|
private onTextEditStop;
|
|
518
521
|
private onTapDown;
|
|
519
522
|
private onDoubleTap;
|
|
523
|
+
private findArrowAt;
|
|
524
|
+
private startArrowLabelEdit;
|
|
520
525
|
private hitTestWorld;
|
|
521
526
|
stopInteracting(): void;
|
|
522
527
|
private onDragOver;
|
|
@@ -574,6 +579,7 @@ interface ArrowInput extends BaseDefaults {
|
|
|
574
579
|
width?: number;
|
|
575
580
|
fromBinding?: Binding;
|
|
576
581
|
toBinding?: Binding;
|
|
582
|
+
label?: string;
|
|
577
583
|
}
|
|
578
584
|
interface ImageInput extends BaseDefaults {
|
|
579
585
|
position: Point;
|
|
@@ -951,6 +957,6 @@ declare class TemplateTool implements Tool {
|
|
|
951
957
|
private notifyOptionsChange;
|
|
952
958
|
}
|
|
953
959
|
|
|
954
|
-
declare const VERSION = "0.
|
|
960
|
+
declare const VERSION = "0.28.0";
|
|
955
961
|
|
|
956
962
|
export { type ActiveFormats, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.js
CHANGED
|
@@ -2658,6 +2658,7 @@ function drawHexPath(ctx, cx, cy, cellSize, orientation) {
|
|
|
2658
2658
|
var DOM_ELEMENT_TYPES = /* @__PURE__ */ new Set(["note", "html", "text"]);
|
|
2659
2659
|
var ARROWHEAD_LENGTH = 12;
|
|
2660
2660
|
var ARROWHEAD_ANGLE = Math.PI / 6;
|
|
2661
|
+
var ARROW_LABEL_FONT_SIZE = 14;
|
|
2661
2662
|
var ElementRenderer = class {
|
|
2662
2663
|
store = null;
|
|
2663
2664
|
imageCache = /* @__PURE__ */ new Map();
|
|
@@ -2668,6 +2669,7 @@ var ElementRenderer = class {
|
|
|
2668
2669
|
hexTileCache = null;
|
|
2669
2670
|
hexTileCacheKey = "";
|
|
2670
2671
|
gridBoundsOverride = null;
|
|
2672
|
+
labelEditingId = null;
|
|
2671
2673
|
setStore(store) {
|
|
2672
2674
|
this.store = store;
|
|
2673
2675
|
}
|
|
@@ -2686,6 +2688,9 @@ var ElementRenderer = class {
|
|
|
2686
2688
|
setGridBoundsOverride(bounds) {
|
|
2687
2689
|
this.gridBoundsOverride = bounds;
|
|
2688
2690
|
}
|
|
2691
|
+
setLabelEditingId(id) {
|
|
2692
|
+
this.labelEditingId = id;
|
|
2693
|
+
}
|
|
2689
2694
|
isDomElement(element) {
|
|
2690
2695
|
return DOM_ELEMENT_TYPES.has(element.type);
|
|
2691
2696
|
}
|
|
@@ -2762,6 +2767,28 @@ var ElementRenderer = class {
|
|
|
2762
2767
|
ctx.stroke();
|
|
2763
2768
|
this.renderArrowhead(ctx, arrow, visualTo, geometry.tangentEnd);
|
|
2764
2769
|
ctx.restore();
|
|
2770
|
+
this.renderArrowLabel(ctx, arrow);
|
|
2771
|
+
}
|
|
2772
|
+
renderArrowLabel(ctx, arrow) {
|
|
2773
|
+
if (!arrow.label || arrow.label.length === 0) return;
|
|
2774
|
+
if (arrow.id === this.labelEditingId) return;
|
|
2775
|
+
const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);
|
|
2776
|
+
ctx.save();
|
|
2777
|
+
ctx.font = `${ARROW_LABEL_FONT_SIZE}px system-ui, sans-serif`;
|
|
2778
|
+
const metrics = ctx.measureText(arrow.label);
|
|
2779
|
+
const padX = 6;
|
|
2780
|
+
const padY = 4;
|
|
2781
|
+
const w = metrics.width + padX * 2;
|
|
2782
|
+
const h = ARROW_LABEL_FONT_SIZE + padY * 2;
|
|
2783
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.9)";
|
|
2784
|
+
ctx.beginPath();
|
|
2785
|
+
ctx.roundRect(mid.x - w / 2, mid.y - h / 2, w, h, 4);
|
|
2786
|
+
ctx.fill();
|
|
2787
|
+
ctx.fillStyle = "#1a1a1a";
|
|
2788
|
+
ctx.textAlign = "center";
|
|
2789
|
+
ctx.textBaseline = "middle";
|
|
2790
|
+
ctx.fillText(arrow.label, mid.x, mid.y);
|
|
2791
|
+
ctx.restore();
|
|
2765
2792
|
}
|
|
2766
2793
|
renderArrowhead(ctx, arrow, tip, angle) {
|
|
2767
2794
|
ctx.beginPath();
|
|
@@ -3172,6 +3199,7 @@ function createArrow(input) {
|
|
|
3172
3199
|
};
|
|
3173
3200
|
if (input.fromBinding) result.fromBinding = input.fromBinding;
|
|
3174
3201
|
if (input.toBinding) result.toBinding = input.toBinding;
|
|
3202
|
+
if (input.label !== void 0) result.label = input.label;
|
|
3175
3203
|
return result;
|
|
3176
3204
|
}
|
|
3177
3205
|
function createImage(input) {
|
|
@@ -3635,6 +3663,84 @@ var NoteEditor = class {
|
|
|
3635
3663
|
}
|
|
3636
3664
|
};
|
|
3637
3665
|
|
|
3666
|
+
// src/elements/arrow-label-editor.ts
|
|
3667
|
+
var ArrowLabelEditor = class {
|
|
3668
|
+
input = null;
|
|
3669
|
+
done = false;
|
|
3670
|
+
get isEditing() {
|
|
3671
|
+
return this.input !== null;
|
|
3672
|
+
}
|
|
3673
|
+
startEditing(start) {
|
|
3674
|
+
if (this.input) this.cleanup();
|
|
3675
|
+
const { arrow, layer, store, recorder, onDone } = start;
|
|
3676
|
+
const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);
|
|
3677
|
+
const input = document.createElement("input");
|
|
3678
|
+
input.type = "text";
|
|
3679
|
+
input.value = arrow.label ?? "";
|
|
3680
|
+
Object.assign(input.style, {
|
|
3681
|
+
position: "absolute",
|
|
3682
|
+
left: `${mid.x}px`,
|
|
3683
|
+
top: `${mid.y}px`,
|
|
3684
|
+
transform: "translate(-50%, -50%)",
|
|
3685
|
+
// domLayer is pointer-events:none; the input must opt back in to receive taps/clicks.
|
|
3686
|
+
pointerEvents: "auto",
|
|
3687
|
+
font: "14px system-ui, sans-serif",
|
|
3688
|
+
padding: "2px 6px",
|
|
3689
|
+
border: "1px solid #2196F3",
|
|
3690
|
+
borderRadius: "4px",
|
|
3691
|
+
background: "#ffffff",
|
|
3692
|
+
color: "#1a1a1a",
|
|
3693
|
+
outline: "none",
|
|
3694
|
+
minWidth: "40px"
|
|
3695
|
+
});
|
|
3696
|
+
this.done = false;
|
|
3697
|
+
const commit = () => {
|
|
3698
|
+
if (this.done) return;
|
|
3699
|
+
this.done = true;
|
|
3700
|
+
const next = input.value.trim() || void 0;
|
|
3701
|
+
if (next !== arrow.label) {
|
|
3702
|
+
recorder.begin();
|
|
3703
|
+
store.update(arrow.id, { label: next });
|
|
3704
|
+
recorder.commit();
|
|
3705
|
+
}
|
|
3706
|
+
this.cleanup();
|
|
3707
|
+
onDone();
|
|
3708
|
+
};
|
|
3709
|
+
const cancel = () => {
|
|
3710
|
+
if (this.done) return;
|
|
3711
|
+
this.done = true;
|
|
3712
|
+
this.cleanup();
|
|
3713
|
+
onDone();
|
|
3714
|
+
};
|
|
3715
|
+
input.addEventListener("keydown", (e) => {
|
|
3716
|
+
if (e.key === "Enter") {
|
|
3717
|
+
e.preventDefault();
|
|
3718
|
+
commit();
|
|
3719
|
+
} else if (e.key === "Escape") {
|
|
3720
|
+
e.preventDefault();
|
|
3721
|
+
cancel();
|
|
3722
|
+
}
|
|
3723
|
+
e.stopPropagation();
|
|
3724
|
+
});
|
|
3725
|
+
input.addEventListener("blur", commit);
|
|
3726
|
+
layer.appendChild(input);
|
|
3727
|
+
this.input = input;
|
|
3728
|
+
input.focus();
|
|
3729
|
+
input.select();
|
|
3730
|
+
}
|
|
3731
|
+
/** Abort any in-progress edit without committing (e.g. on viewport teardown). */
|
|
3732
|
+
cancel() {
|
|
3733
|
+
this.done = true;
|
|
3734
|
+
this.cleanup();
|
|
3735
|
+
}
|
|
3736
|
+
cleanup() {
|
|
3737
|
+
if (this.input) {
|
|
3738
|
+
this.input.remove();
|
|
3739
|
+
this.input = null;
|
|
3740
|
+
}
|
|
3741
|
+
}
|
|
3742
|
+
};
|
|
3743
|
+
|
|
3638
3744
|
// src/tools/tool-manager.ts
|
|
3639
3745
|
var ToolManager = class {
|
|
3640
3746
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -5244,6 +5350,7 @@ function getElementStyle(element) {
|
|
|
5244
5350
|
|
|
5245
5351
|
// src/canvas/viewport.ts
|
|
5246
5352
|
var EMPTY_IDS = [];
|
|
5353
|
+
var ARROW_HIT_THRESHOLD = 10;
|
|
5247
5354
|
function noop() {
|
|
5248
5355
|
}
|
|
5249
5356
|
function sharedValue(values) {
|
|
@@ -5285,6 +5392,7 @@ var Viewport = class {
|
|
|
5285
5392
|
placeholder: options.placeholder
|
|
5286
5393
|
});
|
|
5287
5394
|
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
5395
|
+
this.arrowLabelEditor = new ArrowLabelEditor();
|
|
5288
5396
|
this.noteEditor.setHistoryHooks(
|
|
5289
5397
|
() => this.historyRecorder.begin(),
|
|
5290
5398
|
() => this.historyRecorder.commit()
|
|
@@ -5411,6 +5519,7 @@ var Viewport = class {
|
|
|
5411
5519
|
background;
|
|
5412
5520
|
renderer;
|
|
5413
5521
|
noteEditor;
|
|
5522
|
+
arrowLabelEditor;
|
|
5414
5523
|
historyRecorder;
|
|
5415
5524
|
toolContext;
|
|
5416
5525
|
marginViewport;
|
|
@@ -5665,6 +5774,7 @@ var Viewport = class {
|
|
|
5665
5774
|
this.renderLoop.stop();
|
|
5666
5775
|
this.interactMode.destroy();
|
|
5667
5776
|
this.noteEditor.destroy(this.store);
|
|
5777
|
+
this.arrowLabelEditor.cancel();
|
|
5668
5778
|
this.historyRecorder.destroy();
|
|
5669
5779
|
this.wrapper.removeEventListener("pointerdown", this.onTapDown);
|
|
5670
5780
|
this.wrapper.removeEventListener("pointerup", this.onDoubleTap);
|
|
@@ -5750,8 +5860,35 @@ var Viewport = class {
|
|
|
5750
5860
|
const hit = this.hitTestWorld(world);
|
|
5751
5861
|
if (hit?.type === "html") {
|
|
5752
5862
|
this.interactMode.startInteracting(hit.id);
|
|
5863
|
+
return;
|
|
5864
|
+
}
|
|
5865
|
+
const arrow = this.findArrowAt(world);
|
|
5866
|
+
if (arrow) {
|
|
5867
|
+
this.startArrowLabelEdit(arrow);
|
|
5753
5868
|
}
|
|
5754
5869
|
};
|
|
5870
|
+
findArrowAt(world) {
|
|
5871
|
+
const candidates = this.store.queryPoint(world).reverse();
|
|
5872
|
+
for (const el of candidates) {
|
|
5873
|
+
if (el.type === "arrow" && isNearBezier(world, el.from, el.to, el.bend, ARROW_HIT_THRESHOLD)) {
|
|
5874
|
+
return el;
|
|
5875
|
+
}
|
|
5876
|
+
}
|
|
5877
|
+
return void 0;
|
|
5878
|
+
}
|
|
5879
|
+
startArrowLabelEdit(arrow) {
|
|
5880
|
+
this.arrowLabelEditor.startEditing({
|
|
5881
|
+
arrow,
|
|
5882
|
+
layer: this.domLayer,
|
|
5883
|
+
store: this.store,
|
|
5884
|
+
recorder: this.historyRecorder,
|
|
5885
|
+
onDone: () => {
|
|
5886
|
+
this.renderer.setLabelEditingId(null);
|
|
5887
|
+
this.requestRender();
|
|
5888
|
+
}
|
|
5889
|
+
});
|
|
5890
|
+
this.renderer.setLabelEditingId(arrow.id);
|
|
5891
|
+
}
|
|
5755
5892
|
hitTestWorld(world) {
|
|
5756
5893
|
const candidates = this.store.queryPoint(world).reverse();
|
|
5757
5894
|
for (const el of candidates) {
|
|
@@ -7665,7 +7802,7 @@ var TemplateTool = class {
|
|
|
7665
7802
|
};
|
|
7666
7803
|
|
|
7667
7804
|
// src/index.ts
|
|
7668
|
-
var VERSION = "0.
|
|
7805
|
+
var VERSION = "0.28.0";
|
|
7669
7806
|
export {
|
|
7670
7807
|
ArrowTool,
|
|
7671
7808
|
AutoSave,
|