@blankdotpage/cake 0.1.21 → 0.1.23
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/cake/editor/cake-editor.d.ts +4 -0
- package/dist/cake/editor/cake-editor.d.ts.map +1 -1
- package/dist/cake/editor/cake-editor.js +124 -19
- package/dist/cake/editor/selection/selection-geometry-dom.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-geometry-dom.js +3 -1
- package/dist/cake/editor/selection/selection-geometry.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-geometry.js +10 -12
- package/dist/cake/editor/selection/selection-layout-dom.d.ts.map +1 -1
- package/dist/cake/editor/selection/selection-layout-dom.js +42 -6
- package/dist/cake/editor/selection/selection-layout.d.ts +5 -0
- package/dist/cake/editor/selection/selection-layout.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -55,6 +55,8 @@ export declare class CakeEditor {
|
|
|
55
55
|
private blockTrustedTextDrag;
|
|
56
56
|
private selectedAtomicLineIndex;
|
|
57
57
|
private lastAppliedSelection;
|
|
58
|
+
private pendingTouchSelectionChangeId;
|
|
59
|
+
private pendingTouchSelection;
|
|
58
60
|
private compositionCommit;
|
|
59
61
|
private compositionCommitTimeoutId;
|
|
60
62
|
private overlayRoot;
|
|
@@ -108,6 +110,7 @@ export declare class CakeEditor {
|
|
|
108
110
|
private pointerDownPosition;
|
|
109
111
|
private hasMovedSincePointerDown;
|
|
110
112
|
private lastTouchTime;
|
|
113
|
+
private debugLog;
|
|
111
114
|
private isTouchDevice;
|
|
112
115
|
constructor(options: EngineOptions);
|
|
113
116
|
installExtensions(extensions: CakeExtension[]): void;
|
|
@@ -186,6 +189,7 @@ export declare class CakeEditor {
|
|
|
186
189
|
private updateContentRootAttributes;
|
|
187
190
|
private applySelection;
|
|
188
191
|
private handleSelectionChange;
|
|
192
|
+
private applyDomSelectionChange;
|
|
189
193
|
private syncSelectionFromDom;
|
|
190
194
|
private adjustSelectionForAtomicBlocks;
|
|
191
195
|
private getAtomicBlockSelectionFromClick;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cake-editor.d.ts","sourceRoot":"","sources":["../../../src/cake/editor/cake-editor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cake-editor.d.ts","sourceRoot":"","sources":["../../../src/cake/editor/cake-editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,14 @@ export class CakeEditor {
|
|
|
45
45
|
return (target instanceof Node &&
|
|
46
46
|
(target === this.contentRoot || this.contentRoot.contains(target)));
|
|
47
47
|
}
|
|
48
|
+
// Debug logging for iOS selection tracing - enable via window.CAKE_DEBUG_SELECTION = true
|
|
49
|
+
debugLog(category, ...args) {
|
|
50
|
+
if (typeof window !== "undefined" &&
|
|
51
|
+
window
|
|
52
|
+
.CAKE_DEBUG_SELECTION) {
|
|
53
|
+
console.log(`[Cake:${category}]`, performance.now().toFixed(2), ...args);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
48
56
|
// Detect if this is a touch-primary device (mobile/tablet)
|
|
49
57
|
// We check for touch support AND coarse pointer to exclude laptops with touchscreens
|
|
50
58
|
isTouchDevice() {
|
|
@@ -79,6 +87,8 @@ export class CakeEditor {
|
|
|
79
87
|
this.blockTrustedTextDrag = false;
|
|
80
88
|
this.selectedAtomicLineIndex = null;
|
|
81
89
|
this.lastAppliedSelection = null;
|
|
90
|
+
this.pendingTouchSelectionChangeId = null;
|
|
91
|
+
this.pendingTouchSelection = null;
|
|
82
92
|
this.compositionCommit = false;
|
|
83
93
|
this.compositionCommitTimeoutId = null;
|
|
84
94
|
this.overlayRoot = null;
|
|
@@ -640,8 +650,7 @@ export class CakeEditor {
|
|
|
640
650
|
}
|
|
641
651
|
if (!this.contentRoot) {
|
|
642
652
|
// Overlay roots are positioned absolutely; ensure the container forms a
|
|
643
|
-
// positioning context
|
|
644
|
-
// keep resolving into line nodes after scrolling.
|
|
653
|
+
// positioning context and doesn't scroll out from under them.
|
|
645
654
|
const containerPosition = window.getComputedStyle(this.container).position;
|
|
646
655
|
if (containerPosition === "static") {
|
|
647
656
|
this.container.style.position = "relative";
|
|
@@ -798,21 +807,35 @@ export class CakeEditor {
|
|
|
798
807
|
this.scheduleOverlayUpdate();
|
|
799
808
|
}
|
|
800
809
|
handleSelectionChange() {
|
|
810
|
+
const isRecentTouchForLog = Date.now() - this.lastTouchTime < 2000;
|
|
811
|
+
this.debugLog("selectionchange", "fired", {
|
|
812
|
+
isRecentTouch: isRecentTouchForLog,
|
|
813
|
+
suppressSelectionChange: this.suppressSelectionChange,
|
|
814
|
+
isApplyingSelection: this.isApplyingSelection,
|
|
815
|
+
isComposing: this.isComposing,
|
|
816
|
+
ignoreTouchUntil: this.ignoreTouchNativeSelectionUntil,
|
|
817
|
+
pendingTouchSelectionChangeId: this.pendingTouchSelectionChangeId,
|
|
818
|
+
});
|
|
801
819
|
if (this.isComposing) {
|
|
820
|
+
this.debugLog("selectionchange", "skip: isComposing");
|
|
802
821
|
return;
|
|
803
822
|
}
|
|
804
823
|
if (this.ignoreTouchNativeSelectionUntil !== null &&
|
|
805
824
|
performance.now() < this.ignoreTouchNativeSelectionUntil) {
|
|
825
|
+
this.debugLog("selectionchange", "skip: ignoreTouchNativeSelectionUntil");
|
|
806
826
|
return;
|
|
807
827
|
}
|
|
808
828
|
if (this.suppressSelectionChange) {
|
|
829
|
+
this.debugLog("selectionchange", "skip: suppressSelectionChange");
|
|
809
830
|
return;
|
|
810
831
|
}
|
|
811
832
|
if (this.isApplyingSelection) {
|
|
833
|
+
this.debugLog("selectionchange", "skip: isApplyingSelection");
|
|
812
834
|
return;
|
|
813
835
|
}
|
|
814
836
|
const domSelection = window.getSelection();
|
|
815
837
|
if (!domSelection || domSelection.rangeCount === 0) {
|
|
838
|
+
this.debugLog("selectionchange", "skip: no DOM selection");
|
|
816
839
|
return;
|
|
817
840
|
}
|
|
818
841
|
const anchorNode = domSelection.anchorNode;
|
|
@@ -821,15 +844,19 @@ export class CakeEditor {
|
|
|
821
844
|
!focusNode ||
|
|
822
845
|
(!this.container.contains(anchorNode) &&
|
|
823
846
|
!this.container.contains(focusNode))) {
|
|
847
|
+
this.debugLog("selectionchange", "skip: selection outside container");
|
|
824
848
|
return;
|
|
825
849
|
}
|
|
826
850
|
if (!this.domMap) {
|
|
851
|
+
this.debugLog("selectionchange", "skip: no domMap");
|
|
827
852
|
return;
|
|
828
853
|
}
|
|
829
854
|
const selection = readDomSelection(this.domMap);
|
|
830
855
|
if (!selection) {
|
|
856
|
+
this.debugLog("selectionchange", "skip: could not read DOM selection");
|
|
831
857
|
return;
|
|
832
858
|
}
|
|
859
|
+
this.debugLog("selectionchange", "read DOM selection", selection);
|
|
833
860
|
if (this.lastAppliedSelection &&
|
|
834
861
|
selectionsEqual(selection, this.lastAppliedSelection)) {
|
|
835
862
|
return;
|
|
@@ -848,9 +875,48 @@ export class CakeEditor {
|
|
|
848
875
|
this.lastAppliedSelection = selection;
|
|
849
876
|
return;
|
|
850
877
|
}
|
|
878
|
+
const isRecentTouch = Date.now() - this.lastTouchTime < 2000;
|
|
879
|
+
const isTouchMode = (this.contentRoot?.classList.contains("cake-touch-mode") ?? false) ||
|
|
880
|
+
this.isTouchDevice() ||
|
|
881
|
+
isRecentTouch;
|
|
882
|
+
if (isTouchMode) {
|
|
883
|
+
// On iOS Safari, a single tap can produce multiple selectionchange events
|
|
884
|
+
// in quick succession (e.g. an intermediate caret at a word boundary,
|
|
885
|
+
// then the final caret at the tapped position). Debounce to the next frame
|
|
886
|
+
// so we sync state once, using the final DOM selection.
|
|
887
|
+
this.pendingTouchSelection = selection;
|
|
888
|
+
this.debugLog("selectionchange", "touch mode - storing pending", {
|
|
889
|
+
selection,
|
|
890
|
+
alreadyScheduled: this.pendingTouchSelectionChangeId !== null,
|
|
891
|
+
});
|
|
892
|
+
if (this.pendingTouchSelectionChangeId !== null) {
|
|
893
|
+
this.debugLog("selectionchange", "RAF already scheduled, updated pending selection");
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
this.pendingTouchSelectionChangeId = window.requestAnimationFrame(() => {
|
|
897
|
+
this.pendingTouchSelectionChangeId = null;
|
|
898
|
+
const pending = this.pendingTouchSelection;
|
|
899
|
+
this.pendingTouchSelection = null;
|
|
900
|
+
this.debugLog("selectionchange", "RAF callback - applying pending", {
|
|
901
|
+
pending,
|
|
902
|
+
});
|
|
903
|
+
if (!pending) {
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
this.applyDomSelectionChange(pending);
|
|
907
|
+
});
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
this.applyDomSelectionChange(selection);
|
|
911
|
+
}
|
|
912
|
+
applyDomSelectionChange(selection) {
|
|
913
|
+
this.debugLog("applyDomSelectionChange", "applying", {
|
|
914
|
+
selection,
|
|
915
|
+
previousSelection: this.state.selection,
|
|
916
|
+
});
|
|
851
917
|
// For collapsed selections (cursor moves), check if we landed on an atomic block
|
|
852
918
|
// and skip over it in the direction of movement
|
|
853
|
-
const adjustedSelection = this.adjustSelectionForAtomicBlocks(selection,
|
|
919
|
+
const adjustedSelection = this.adjustSelectionForAtomicBlocks(selection, this.state.selection);
|
|
854
920
|
this.selectedAtomicLineIndex = null;
|
|
855
921
|
this.state = this.runtime.updateSelection(this.state, adjustedSelection, {
|
|
856
922
|
kind: "dom",
|
|
@@ -956,6 +1022,14 @@ export class CakeEditor {
|
|
|
956
1022
|
};
|
|
957
1023
|
}
|
|
958
1024
|
handleClick(event) {
|
|
1025
|
+
const isRecentTouchForLog = Date.now() - this.lastTouchTime < 2000;
|
|
1026
|
+
this.debugLog("click", "fired", {
|
|
1027
|
+
detail: event.detail,
|
|
1028
|
+
isRecentTouch: isRecentTouchForLog,
|
|
1029
|
+
isTouchDevice: this.isTouchDevice(),
|
|
1030
|
+
x: event.clientX,
|
|
1031
|
+
y: event.clientY,
|
|
1032
|
+
});
|
|
959
1033
|
if (this.isComposing) {
|
|
960
1034
|
return;
|
|
961
1035
|
}
|
|
@@ -972,6 +1046,15 @@ export class CakeEditor {
|
|
|
972
1046
|
// For single clicks (detail=1), selection was already applied in pointerdown.
|
|
973
1047
|
// Skip if user just created a selection via drag (mouse moved since pointer down)
|
|
974
1048
|
if (event.detail === 1 && !this.hasMovedSincePointerDown) {
|
|
1049
|
+
// On touch devices we rely on native caret/selection behavior and sync via
|
|
1050
|
+
// `selectionchange`. Avoid programmatic click hit-testing here: it can
|
|
1051
|
+
// briefly set the selection to a wrong boundary (flash) before iOS Safari
|
|
1052
|
+
// applies the native caret placement.
|
|
1053
|
+
const isRecentTouch = Date.now() - this.lastTouchTime < 2000;
|
|
1054
|
+
if (this.isTouchDevice() || isRecentTouch) {
|
|
1055
|
+
this.debugLog("click", "skip: touch device / recent touch");
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
975
1058
|
// For shift+click, let the browser handle selection extension
|
|
976
1059
|
// (we didn't capture pendingClickHit for shift+click in pointerdown)
|
|
977
1060
|
if (event.shiftKey) {
|
|
@@ -1059,6 +1142,25 @@ export class CakeEditor {
|
|
|
1059
1142
|
}
|
|
1060
1143
|
const lines = getDocLines(this.state.doc);
|
|
1061
1144
|
if (event.detail === 2) {
|
|
1145
|
+
const lineOffsets = getLineOffsets(lines);
|
|
1146
|
+
const { lineIndex } = resolveOffsetToLine(lines, hit.cursorOffset);
|
|
1147
|
+
const lineInfo = lines[lineIndex];
|
|
1148
|
+
if (lineInfo && lineInfo.cursorLength === 0) {
|
|
1149
|
+
const lineStart = lineOffsets[lineIndex] ?? 0;
|
|
1150
|
+
const selection = {
|
|
1151
|
+
start: lineStart,
|
|
1152
|
+
end: lineStart,
|
|
1153
|
+
affinity: "forward",
|
|
1154
|
+
};
|
|
1155
|
+
event.preventDefault();
|
|
1156
|
+
this.state = this.runtime.updateSelection(this.state, selection, {
|
|
1157
|
+
kind: "dom",
|
|
1158
|
+
});
|
|
1159
|
+
this.applySelection(this.state.selection);
|
|
1160
|
+
this.notifySelectionChange();
|
|
1161
|
+
this.suppressSelectionChange = false;
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1062
1164
|
const visibleText = getVisibleText(lines);
|
|
1063
1165
|
const visibleOffset = cursorOffsetToVisibleOffset(lines, hit.cursorOffset);
|
|
1064
1166
|
const wordBounds = getWordBoundaries(visibleText, visibleOffset);
|
|
@@ -1503,9 +1605,6 @@ export class CakeEditor {
|
|
|
1503
1605
|
if (!this.isEventTargetInContentRoot(event.target)) {
|
|
1504
1606
|
return;
|
|
1505
1607
|
}
|
|
1506
|
-
if (this.beforeInputHandled) {
|
|
1507
|
-
return;
|
|
1508
|
-
}
|
|
1509
1608
|
if (this.compositionCommit && event.inputType === "insertText") {
|
|
1510
1609
|
this.clearCompositionCommit();
|
|
1511
1610
|
return;
|
|
@@ -1519,6 +1618,17 @@ export class CakeEditor {
|
|
|
1519
1618
|
event.inputType === "historyRedo") {
|
|
1520
1619
|
return;
|
|
1521
1620
|
}
|
|
1621
|
+
// Some WebKit/iOS flows can dispatch `input` without a corresponding `beforeinput`
|
|
1622
|
+
// while our beforeinput-handled suppression window is still active. In that case,
|
|
1623
|
+
// we must not drop the edit; reconcile if the DOM diverged from the model.
|
|
1624
|
+
if (this.beforeInputHandled) {
|
|
1625
|
+
const domText = this.readDomText();
|
|
1626
|
+
const lines = getDocLines(this.state.doc);
|
|
1627
|
+
const modelText = getVisibleText(lines);
|
|
1628
|
+
if (domText === modelText) {
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1522
1632
|
if (!this.domMap) {
|
|
1523
1633
|
return;
|
|
1524
1634
|
}
|
|
@@ -2589,6 +2699,9 @@ export class CakeEditor {
|
|
|
2589
2699
|
}
|
|
2590
2700
|
}
|
|
2591
2701
|
notifySelectionChange() {
|
|
2702
|
+
this.debugLog("notifySelectionChange", "notifying", {
|
|
2703
|
+
selection: this.state.selection,
|
|
2704
|
+
});
|
|
2592
2705
|
this.onSelectionChangeOption?.(this.state.selection);
|
|
2593
2706
|
for (const callback of this.selectionChangeSubscribers) {
|
|
2594
2707
|
callback(this.state.selection);
|
|
@@ -2958,6 +3071,11 @@ export class CakeEditor {
|
|
|
2958
3071
|
// context menus. We track the touch time to hide the custom caret overlay
|
|
2959
3072
|
// and trust selectionchange events to sync state.
|
|
2960
3073
|
this.lastTouchTime = Date.now();
|
|
3074
|
+
this.debugLog("pointerdown", "touch event - letting browser handle", {
|
|
3075
|
+
x: event.clientX,
|
|
3076
|
+
y: event.clientY,
|
|
3077
|
+
currentSelection: this.state.selection,
|
|
3078
|
+
});
|
|
2961
3079
|
return;
|
|
2962
3080
|
}
|
|
2963
3081
|
const selection = this.state.selection;
|
|
@@ -3729,19 +3847,6 @@ function findTextNodeAtOrAfter(nodes, start) {
|
|
|
3729
3847
|
}
|
|
3730
3848
|
return null;
|
|
3731
3849
|
}
|
|
3732
|
-
function caretPositionFromPoint(x, y) {
|
|
3733
|
-
const doc = document;
|
|
3734
|
-
if (typeof doc.caretPositionFromPoint === "function") {
|
|
3735
|
-
return doc.caretPositionFromPoint(x, y);
|
|
3736
|
-
}
|
|
3737
|
-
return null;
|
|
3738
|
-
}
|
|
3739
|
-
function caretRangeFromPoint(x, y) {
|
|
3740
|
-
if (typeof document.caretRangeFromPoint === "function") {
|
|
3741
|
-
return document.caretRangeFromPoint(x, y);
|
|
3742
|
-
}
|
|
3743
|
-
return null;
|
|
3744
|
-
}
|
|
3745
3850
|
function getVisualRowBoundaries(params) {
|
|
3746
3851
|
const { lines, layout, offset, affinity } = params;
|
|
3747
3852
|
if (!layout || layout.lines.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-geometry-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-geometry-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAUxE,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;CACtB,GAAG,iBAAiB,CAoHpB;AAMD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACnC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"selection-geometry-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-geometry-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAUxE,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;CACtB,GAAG,iBAAiB,CAoHpB;AAMD,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACnC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAuO9C"}
|
|
@@ -260,7 +260,9 @@ export function getCaretRect(params) {
|
|
|
260
260
|
// the *next* visual row even when we explicitly want backward affinity
|
|
261
261
|
// (e.g. "end of visual row"). Anchor the caret to the previous row fragment
|
|
262
262
|
// when a forward-probe indicates there is a next row.
|
|
263
|
-
|
|
263
|
+
// IMPORTANT: Only do this at actual wrap boundaries, not for middle-of-row
|
|
264
|
+
// positions that happen to have backward affinity.
|
|
265
|
+
if (atWrapBoundary && affinity === "backward" && forwardRect) {
|
|
264
266
|
const startPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, 0));
|
|
265
267
|
const endPos = resolveDomPosition(lineElement, cursorOffsetToDomOffset(lineInfo.cursorToCodeUnit, lineInfo.cursorLength));
|
|
266
268
|
const lineRange = document.createRange();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-geometry.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAGX,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,KACjB,MAAM,GAAG,IAAI,CAAC;AAyEnB,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,SAAS,EACpB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,aAAa,EAAE,CA+GjB;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,yBAAyB,GAC/B,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"selection-geometry.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAGX,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,KACjB,MAAM,GAAG,IAAI,CAAC;AAyEnB,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,SAAS,EACpB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,aAAa,EAAE,CA+GjB;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,yBAAyB,GAC/B,aAAa,GAAG,IAAI,CAoBtB"}
|
|
@@ -137,18 +137,16 @@ export function computeSelectionRects(layout, selection, measurer) {
|
|
|
137
137
|
}
|
|
138
138
|
export function computeCaretRect(caret) {
|
|
139
139
|
const height = caret.fontSize * 1.2;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
: caret.lineRect.top;
|
|
151
|
-
const left = caret.lineLength === 0 ? caret.lineRect.left : caret.caretRect.left;
|
|
140
|
+
if (caret.lineLength === 0) {
|
|
141
|
+
return {
|
|
142
|
+
top: caret.lineRect.top,
|
|
143
|
+
left: caret.lineRect.left,
|
|
144
|
+
width: 0,
|
|
145
|
+
height,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const top = caret.caretRect.height > 0 ? caret.caretRect.top : caret.lineRect.top;
|
|
149
|
+
const left = caret.caretRect.left;
|
|
152
150
|
return {
|
|
153
151
|
top,
|
|
154
152
|
left,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-layout-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,UAAU,EAEV,QAAQ,EAET,MAAM,oBAAoB,CAAC;AAG5B,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GAAG,UAAU,CAOb;AAqBD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CA2B9D;
|
|
1
|
+
{"version":3,"file":"selection-layout-dom.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,UAAU,EAEV,QAAQ,EAET,MAAM,oBAAoB,CAAC;AAG5B,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GAAG,UAAU,CAOb;AAqBD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CA2B9D;AA6VD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,cAAc,GAAG,IAAI,CA+CxB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;CACxB,GAAG,WAAW,GAAG,IAAI,CAUrB;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,WAAW,GAAG,IAAI,CA8CrB;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,GAChB,WAAW,GAAG,IAAI,CAEpB;AAMD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,GACnB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAiBhC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAiC7D;AAED,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,GAAG,aAAa,GAAG,IAAI,CAoZvB"}
|
|
@@ -289,6 +289,7 @@ function measureLineRows(params) {
|
|
|
289
289
|
const nextRowStart = findNextRowStartOffset(searchFrom, currentRowTop);
|
|
290
290
|
const currentRowEnd = nextRowStart ?? params.lineLength;
|
|
291
291
|
const domRect = rowRects[rowIndex] ?? params.lineRect;
|
|
292
|
+
const glyphRect = fullLineRects[rowIndex];
|
|
292
293
|
rows.push({
|
|
293
294
|
startOffset: currentRowStart,
|
|
294
295
|
endOffset: currentRowEnd,
|
|
@@ -297,6 +298,15 @@ function measureLineRows(params) {
|
|
|
297
298
|
containerRect: params.containerRect,
|
|
298
299
|
scroll: params.scroll,
|
|
299
300
|
}),
|
|
301
|
+
glyphBand: glyphRect
|
|
302
|
+
? {
|
|
303
|
+
top: glyphRect.top - params.containerRect.top + params.scroll.top,
|
|
304
|
+
bottom: glyphRect.top +
|
|
305
|
+
glyphRect.height -
|
|
306
|
+
params.containerRect.top +
|
|
307
|
+
params.scroll.top,
|
|
308
|
+
}
|
|
309
|
+
: undefined,
|
|
300
310
|
});
|
|
301
311
|
if (nextRowStart === null) {
|
|
302
312
|
break;
|
|
@@ -487,6 +497,9 @@ export function hitTestFromLayout(params) {
|
|
|
487
497
|
const allRows = [];
|
|
488
498
|
for (const lineLayout of layout.lines) {
|
|
489
499
|
for (const row of lineLayout.rows) {
|
|
500
|
+
if (!row) {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
490
503
|
const centerY = row.rect.top + row.rect.height / 2;
|
|
491
504
|
allRows.push({
|
|
492
505
|
lineIndex: lineLayout.lineIndex,
|
|
@@ -499,18 +512,42 @@ export function hitTestFromLayout(params) {
|
|
|
499
512
|
if (allRows.length === 0) {
|
|
500
513
|
return null;
|
|
501
514
|
}
|
|
502
|
-
//
|
|
515
|
+
// Choose the row whose glyph band is closest to the click Y. This properly
|
|
516
|
+
// handles line-height gaps: when clicking between rows, the click goes to
|
|
517
|
+
// the row whose glyphs are closer (not to the row whose clamped rect contains it).
|
|
503
518
|
let targetRowInfo = allRows[0];
|
|
504
|
-
|
|
519
|
+
const glyphBandDistance = (rowInfo) => {
|
|
520
|
+
const band = rowInfo.row.glyphBand ?? {
|
|
521
|
+
top: rowInfo.row.rect.top,
|
|
522
|
+
bottom: rowInfo.row.rect.top + rowInfo.row.rect.height,
|
|
523
|
+
};
|
|
524
|
+
if (relativeY < band.top) {
|
|
525
|
+
return band.top - relativeY;
|
|
526
|
+
}
|
|
527
|
+
if (relativeY > band.bottom) {
|
|
528
|
+
return relativeY - band.bottom;
|
|
529
|
+
}
|
|
530
|
+
return 0; // Click is inside the glyph band
|
|
531
|
+
};
|
|
532
|
+
let smallestDistance = glyphBandDistance(targetRowInfo);
|
|
533
|
+
const TIE_EPS_PX = 0.01;
|
|
505
534
|
for (let i = 1; i < allRows.length; i++) {
|
|
506
535
|
const rowInfo = allRows[i];
|
|
507
|
-
const distance =
|
|
508
|
-
if (distance <
|
|
509
|
-
|
|
536
|
+
const distance = glyphBandDistance(rowInfo);
|
|
537
|
+
if (distance + TIE_EPS_PX < smallestDistance) {
|
|
538
|
+
smallestDistance = distance;
|
|
510
539
|
targetRowInfo = rowInfo;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (Math.abs(distance - smallestDistance) <= TIE_EPS_PX) {
|
|
543
|
+
// Tie-break to the upper row
|
|
544
|
+
if (rowInfo.row.rect.top < targetRowInfo.row.rect.top) {
|
|
545
|
+
targetRowInfo = rowInfo;
|
|
546
|
+
}
|
|
511
547
|
}
|
|
512
548
|
}
|
|
513
549
|
const { lineIndex, lineStartOffset, row } = targetRowInfo;
|
|
550
|
+
const scratchRange = document.createRange();
|
|
514
551
|
const lineInfo = lines[lineIndex];
|
|
515
552
|
if (!lineInfo) {
|
|
516
553
|
return null;
|
|
@@ -526,7 +563,6 @@ export function hitTestFromLayout(params) {
|
|
|
526
563
|
// before an inline wrapper like <a>). Prefer collapsed ranges (caret positions)
|
|
527
564
|
// and pick the fragment that belongs to the target visual row.
|
|
528
565
|
const resolvePosition = createDomPositionResolver(lineElement);
|
|
529
|
-
const scratchRange = document.createRange();
|
|
530
566
|
const rowTop = row.rect.top;
|
|
531
567
|
const approximateX = (cursorOffsetInLine) => {
|
|
532
568
|
const clamped = Math.max(row.startOffset, Math.min(cursorOffsetInLine, row.endOffset));
|
|
@@ -9,6 +9,11 @@ export type LayoutRow = {
|
|
|
9
9
|
startOffset: number;
|
|
10
10
|
endOffset: number;
|
|
11
11
|
rect: LayoutRect;
|
|
12
|
+
/** The actual glyph bounds within this row (before line-height clamping). */
|
|
13
|
+
glyphBand?: {
|
|
14
|
+
top: number;
|
|
15
|
+
bottom: number;
|
|
16
|
+
};
|
|
12
17
|
};
|
|
13
18
|
export type LineLayout = {
|
|
14
19
|
lineIndex: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-layout.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,GAAG,EAAU,MAAM,kBAAkB,CAAC;AAG3D,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"selection-layout.d.ts","sourceRoot":"","sources":["../../../../src/cake/editor/selection/selection-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,GAAG,EAAU,MAAM,kBAAkB,CAAC;AAG3D,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,6EAA6E;IAC7E,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,eAAe,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,QAAQ,EAAE,EACjB,QAAQ,EAAE,cAAc,GACvB,WAAW,CAqCb;AAOD,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,EAAE,CAchD;AA6BD,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAW1D;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,MAAM,GACb;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAsB7C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blankdotpage/cake",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"build:demo": "npm run build && npm --workspace demo run build",
|
|
28
28
|
"test": "vitest run",
|
|
29
29
|
"test:browser": "vitest run --project browser",
|
|
30
|
+
"test:browser:ios": "vitest run --project browser-ios",
|
|
30
31
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
31
32
|
"lint": "eslint .",
|
|
32
33
|
"format": "prettier --write .",
|