@input/pen-core 0.2.0 → 0.2.2
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 +53 -4
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +53 -4
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -4353,6 +4353,12 @@ var DecorationSetImpl = class _DecorationSetImpl {
|
|
|
4353
4353
|
get decorations() {
|
|
4354
4354
|
return this._decorations;
|
|
4355
4355
|
}
|
|
4356
|
+
get blockIndex() {
|
|
4357
|
+
return this._blockIndex;
|
|
4358
|
+
}
|
|
4359
|
+
get isReleased() {
|
|
4360
|
+
return this._released;
|
|
4361
|
+
}
|
|
4356
4362
|
forBlock(blockId) {
|
|
4357
4363
|
return this._blockIndex.get(blockId) ?? EMPTY_ARRAY;
|
|
4358
4364
|
}
|
|
@@ -4428,6 +4434,36 @@ function mergeDecorationSets(...sets) {
|
|
|
4428
4434
|
if (all.length === 0) return EMPTY_SET;
|
|
4429
4435
|
return new DecorationSetImpl(all);
|
|
4430
4436
|
}
|
|
4437
|
+
function reconcileDecorationSets(previous, next) {
|
|
4438
|
+
if (previous === next) return previous;
|
|
4439
|
+
if (!(previous instanceof DecorationSetImpl) || !(next instanceof DecorationSetImpl) || previous.isReleased) {
|
|
4440
|
+
return next;
|
|
4441
|
+
}
|
|
4442
|
+
const previousIndex = previous.blockIndex;
|
|
4443
|
+
const nextIndex = next.blockIndex;
|
|
4444
|
+
if (previousIndex.size !== nextIndex.size) {
|
|
4445
|
+
return reuseUnchangedBlocks(previousIndex, nextIndex);
|
|
4446
|
+
}
|
|
4447
|
+
for (const [blockId, nextList] of nextIndex) {
|
|
4448
|
+
const previousList = previousIndex.get(blockId);
|
|
4449
|
+
if (!previousList || !decorationsListEqual(previousList, nextList)) {
|
|
4450
|
+
return reuseUnchangedBlocks(previousIndex, nextIndex);
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
return previous;
|
|
4454
|
+
}
|
|
4455
|
+
function reuseUnchangedBlocks(previousIndex, nextIndex) {
|
|
4456
|
+
const index = /* @__PURE__ */ new Map();
|
|
4457
|
+
const flat = [];
|
|
4458
|
+
for (const [blockId, nextList] of nextIndex) {
|
|
4459
|
+
const previousList = previousIndex.get(blockId);
|
|
4460
|
+
const list = previousList && decorationsListEqual(previousList, nextList) ? previousList : nextList;
|
|
4461
|
+
index.set(blockId, list);
|
|
4462
|
+
flat.push(...list);
|
|
4463
|
+
}
|
|
4464
|
+
if (flat.length === 0) return EMPTY_SET;
|
|
4465
|
+
return new DecorationSetImpl(flat, void 0, index);
|
|
4466
|
+
}
|
|
4431
4467
|
function buildBlockIndex(decorations) {
|
|
4432
4468
|
const index = /* @__PURE__ */ new Map();
|
|
4433
4469
|
for (const dec of decorations) {
|
|
@@ -7990,6 +8026,13 @@ function readTextFocus(editor) {
|
|
|
7990
8026
|
}
|
|
7991
8027
|
return selection.focus;
|
|
7992
8028
|
}
|
|
8029
|
+
function readTextAffinity(editor) {
|
|
8030
|
+
const selection = editor.selection;
|
|
8031
|
+
if (!selection || selection.type !== "text") {
|
|
8032
|
+
return "downstream";
|
|
8033
|
+
}
|
|
8034
|
+
return selection.affinity ?? "downstream";
|
|
8035
|
+
}
|
|
7993
8036
|
function readTextAnchor(editor) {
|
|
7994
8037
|
const selection = editor.selection;
|
|
7995
8038
|
if (!selection || selection.type !== "text") {
|
|
@@ -9153,7 +9196,11 @@ function handleVerticalCaret(editor, param, direction) {
|
|
|
9153
9196
|
if (!focus) {
|
|
9154
9197
|
return false;
|
|
9155
9198
|
}
|
|
9156
|
-
const measured = measureVerticalStep(
|
|
9199
|
+
const measured = measureVerticalStep(
|
|
9200
|
+
editor,
|
|
9201
|
+
{ ...focus, affinity: readTextAffinity(editor) },
|
|
9202
|
+
direction
|
|
9203
|
+
);
|
|
9157
9204
|
if (measured) {
|
|
9158
9205
|
const measuredBlockId = measured.point.blockId;
|
|
9159
9206
|
if (!isEditableTextBlock(editor, measuredBlockId) && getBlockInputMode(editor, measuredBlockId) !== "table") {
|
|
@@ -13351,7 +13398,9 @@ var EditorImpl = class {
|
|
|
13351
13398
|
}
|
|
13352
13399
|
// ── Decorations ──────────────────────────────────────────
|
|
13353
13400
|
requestDecorationUpdate() {
|
|
13401
|
+
const previousGeneration = this._decorations.generation;
|
|
13354
13402
|
const decoSet = this._refreshDecorations();
|
|
13403
|
+
if (decoSet.generation === previousGeneration) return;
|
|
13355
13404
|
this._emitter.emit("decorationsChange", decoSet.generation);
|
|
13356
13405
|
}
|
|
13357
13406
|
getDecorations() {
|
|
@@ -13361,9 +13410,9 @@ var EditorImpl = class {
|
|
|
13361
13410
|
return this._emitter.on(event, handler);
|
|
13362
13411
|
}
|
|
13363
13412
|
_refreshDecorations() {
|
|
13364
|
-
this._decorations =
|
|
13365
|
-
this.
|
|
13366
|
-
this
|
|
13413
|
+
this._decorations = reconcileDecorationSets(
|
|
13414
|
+
this._decorations,
|
|
13415
|
+
this._extensions.collectDecorations(this._documentState, this)
|
|
13367
13416
|
);
|
|
13368
13417
|
return this._decorations;
|
|
13369
13418
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -939,6 +939,13 @@ type VerticalCaretDirection = "up" | "down";
|
|
|
939
939
|
type VerticalCaretPoint = {
|
|
940
940
|
readonly blockId: string;
|
|
941
941
|
readonly offset: number;
|
|
942
|
+
/**
|
|
943
|
+
* Side the caret is drawn on at a line boundary. The measure must read
|
|
944
|
+
* the current line from this, not from the motion direction: an offset
|
|
945
|
+
* right after a wrap or `\n` is upstream the end of the line above and
|
|
946
|
+
* downstream the start of the line below. Absent means `"downstream"`.
|
|
947
|
+
*/
|
|
948
|
+
readonly affinity?: Affinity;
|
|
942
949
|
};
|
|
943
950
|
type VerticalCaretMeasureResult = {
|
|
944
951
|
readonly point: VerticalCaretPoint;
|
package/dist/index.d.ts
CHANGED
|
@@ -939,6 +939,13 @@ type VerticalCaretDirection = "up" | "down";
|
|
|
939
939
|
type VerticalCaretPoint = {
|
|
940
940
|
readonly blockId: string;
|
|
941
941
|
readonly offset: number;
|
|
942
|
+
/**
|
|
943
|
+
* Side the caret is drawn on at a line boundary. The measure must read
|
|
944
|
+
* the current line from this, not from the motion direction: an offset
|
|
945
|
+
* right after a wrap or `\n` is upstream the end of the line above and
|
|
946
|
+
* downstream the start of the line below. Absent means `"downstream"`.
|
|
947
|
+
*/
|
|
948
|
+
readonly affinity?: Affinity;
|
|
942
949
|
};
|
|
943
950
|
type VerticalCaretMeasureResult = {
|
|
944
951
|
readonly point: VerticalCaretPoint;
|
package/dist/index.mjs
CHANGED
|
@@ -4118,6 +4118,12 @@ var DecorationSetImpl = class _DecorationSetImpl {
|
|
|
4118
4118
|
get decorations() {
|
|
4119
4119
|
return this._decorations;
|
|
4120
4120
|
}
|
|
4121
|
+
get blockIndex() {
|
|
4122
|
+
return this._blockIndex;
|
|
4123
|
+
}
|
|
4124
|
+
get isReleased() {
|
|
4125
|
+
return this._released;
|
|
4126
|
+
}
|
|
4121
4127
|
forBlock(blockId) {
|
|
4122
4128
|
return this._blockIndex.get(blockId) ?? EMPTY_ARRAY;
|
|
4123
4129
|
}
|
|
@@ -4193,6 +4199,36 @@ function mergeDecorationSets(...sets) {
|
|
|
4193
4199
|
if (all.length === 0) return EMPTY_SET;
|
|
4194
4200
|
return new DecorationSetImpl(all);
|
|
4195
4201
|
}
|
|
4202
|
+
function reconcileDecorationSets(previous, next) {
|
|
4203
|
+
if (previous === next) return previous;
|
|
4204
|
+
if (!(previous instanceof DecorationSetImpl) || !(next instanceof DecorationSetImpl) || previous.isReleased) {
|
|
4205
|
+
return next;
|
|
4206
|
+
}
|
|
4207
|
+
const previousIndex = previous.blockIndex;
|
|
4208
|
+
const nextIndex = next.blockIndex;
|
|
4209
|
+
if (previousIndex.size !== nextIndex.size) {
|
|
4210
|
+
return reuseUnchangedBlocks(previousIndex, nextIndex);
|
|
4211
|
+
}
|
|
4212
|
+
for (const [blockId, nextList] of nextIndex) {
|
|
4213
|
+
const previousList = previousIndex.get(blockId);
|
|
4214
|
+
if (!previousList || !decorationsListEqual(previousList, nextList)) {
|
|
4215
|
+
return reuseUnchangedBlocks(previousIndex, nextIndex);
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
return previous;
|
|
4219
|
+
}
|
|
4220
|
+
function reuseUnchangedBlocks(previousIndex, nextIndex) {
|
|
4221
|
+
const index = /* @__PURE__ */ new Map();
|
|
4222
|
+
const flat = [];
|
|
4223
|
+
for (const [blockId, nextList] of nextIndex) {
|
|
4224
|
+
const previousList = previousIndex.get(blockId);
|
|
4225
|
+
const list = previousList && decorationsListEqual(previousList, nextList) ? previousList : nextList;
|
|
4226
|
+
index.set(blockId, list);
|
|
4227
|
+
flat.push(...list);
|
|
4228
|
+
}
|
|
4229
|
+
if (flat.length === 0) return EMPTY_SET;
|
|
4230
|
+
return new DecorationSetImpl(flat, void 0, index);
|
|
4231
|
+
}
|
|
4196
4232
|
function buildBlockIndex(decorations) {
|
|
4197
4233
|
const index = /* @__PURE__ */ new Map();
|
|
4198
4234
|
for (const dec of decorations) {
|
|
@@ -7768,6 +7804,13 @@ function readTextFocus(editor) {
|
|
|
7768
7804
|
}
|
|
7769
7805
|
return selection.focus;
|
|
7770
7806
|
}
|
|
7807
|
+
function readTextAffinity(editor) {
|
|
7808
|
+
const selection = editor.selection;
|
|
7809
|
+
if (!selection || selection.type !== "text") {
|
|
7810
|
+
return "downstream";
|
|
7811
|
+
}
|
|
7812
|
+
return selection.affinity ?? "downstream";
|
|
7813
|
+
}
|
|
7771
7814
|
function readTextAnchor(editor) {
|
|
7772
7815
|
const selection = editor.selection;
|
|
7773
7816
|
if (!selection || selection.type !== "text") {
|
|
@@ -8931,7 +8974,11 @@ function handleVerticalCaret(editor, param, direction) {
|
|
|
8931
8974
|
if (!focus) {
|
|
8932
8975
|
return false;
|
|
8933
8976
|
}
|
|
8934
|
-
const measured = measureVerticalStep(
|
|
8977
|
+
const measured = measureVerticalStep(
|
|
8978
|
+
editor,
|
|
8979
|
+
{ ...focus, affinity: readTextAffinity(editor) },
|
|
8980
|
+
direction
|
|
8981
|
+
);
|
|
8935
8982
|
if (measured) {
|
|
8936
8983
|
const measuredBlockId = measured.point.blockId;
|
|
8937
8984
|
if (!isEditableTextBlock(editor, measuredBlockId) && getBlockInputMode(editor, measuredBlockId) !== "table") {
|
|
@@ -13154,7 +13201,9 @@ var EditorImpl = class {
|
|
|
13154
13201
|
}
|
|
13155
13202
|
// ── Decorations ──────────────────────────────────────────
|
|
13156
13203
|
requestDecorationUpdate() {
|
|
13204
|
+
const previousGeneration = this._decorations.generation;
|
|
13157
13205
|
const decoSet = this._refreshDecorations();
|
|
13206
|
+
if (decoSet.generation === previousGeneration) return;
|
|
13158
13207
|
this._emitter.emit("decorationsChange", decoSet.generation);
|
|
13159
13208
|
}
|
|
13160
13209
|
getDecorations() {
|
|
@@ -13164,9 +13213,9 @@ var EditorImpl = class {
|
|
|
13164
13213
|
return this._emitter.on(event, handler);
|
|
13165
13214
|
}
|
|
13166
13215
|
_refreshDecorations() {
|
|
13167
|
-
this._decorations =
|
|
13168
|
-
this.
|
|
13169
|
-
this
|
|
13216
|
+
this._decorations = reconcileDecorationSets(
|
|
13217
|
+
this._decorations,
|
|
13218
|
+
this._extensions.collectDecorations(this._documentState, this)
|
|
13170
13219
|
);
|
|
13171
13220
|
return this._decorations;
|
|
13172
13221
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@input/pen-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Headless, extension-first editor engine for human-AI co-authoring",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/input-systems/pen#readme",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@input/pen-yjs": "^0.2.
|
|
47
|
-
"@input/pen-types": "^0.2.
|
|
46
|
+
"@input/pen-yjs": "^0.2.2",
|
|
47
|
+
"@input/pen-types": "^0.2.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"tsup": "^8.4.0",
|