text-input-guard 1.0.0 → 1.0.1
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/cjs/text-input-guard.cjs +62 -8
- package/dist/cjs/text-input-guard.min.cjs +1 -1
- package/dist/esm/text-input-guard.js +62 -8
- package/dist/esm/text-input-guard.min.js +1 -1
- package/dist/umd/text-input-guard.js +62 -8
- package/dist/umd/text-input-guard.min.js +1 -1
- package/package.json +1 -1
|
@@ -114,11 +114,16 @@ class SwapState {
|
|
|
114
114
|
|
|
115
115
|
const UI_ATTRS = [
|
|
116
116
|
"placeholder",
|
|
117
|
+
"list",
|
|
117
118
|
"inputmode",
|
|
118
119
|
"autocomplete",
|
|
120
|
+
"autocapitalize",
|
|
121
|
+
"autocorrect",
|
|
119
122
|
"minlength",
|
|
120
123
|
"maxlength",
|
|
124
|
+
"size",
|
|
121
125
|
"pattern",
|
|
126
|
+
"dir",
|
|
122
127
|
"title",
|
|
123
128
|
"tabindex",
|
|
124
129
|
"style",
|
|
@@ -150,6 +155,7 @@ class SwapState {
|
|
|
150
155
|
|
|
151
156
|
for (const [k, v] of Object.entries(input.dataset)) {
|
|
152
157
|
if (k.startsWith("tig")) { continue; }
|
|
158
|
+
if (v == null) { continue; }
|
|
153
159
|
this.originalDataset[k] = v;
|
|
154
160
|
}
|
|
155
161
|
}
|
|
@@ -570,7 +576,7 @@ class InputGuard {
|
|
|
570
576
|
|
|
571
577
|
/**
|
|
572
578
|
* attach時に登録されたバリデーション結果コールバック
|
|
573
|
-
* @type {(result: ValidateResult) => void | undefined}
|
|
579
|
+
* @type {((result: ValidateResult) => void) | undefined}
|
|
574
580
|
*/
|
|
575
581
|
this.onValidate = options.onValidate;
|
|
576
582
|
|
|
@@ -748,7 +754,7 @@ class InputGuard {
|
|
|
748
754
|
this.applySeparateValue();
|
|
749
755
|
this.bindEvents();
|
|
750
756
|
// 初期値を評価
|
|
751
|
-
this.
|
|
757
|
+
this.evaluateCommit();
|
|
752
758
|
}
|
|
753
759
|
|
|
754
760
|
/**
|
|
@@ -1040,10 +1046,10 @@ class InputGuard {
|
|
|
1040
1046
|
if (inputType === "deleteContentBackward") {
|
|
1041
1047
|
// Backspace: キャレットの左側1文字を削除
|
|
1042
1048
|
replaceStart = Math.max(0, replaceStart - 1);
|
|
1043
|
-
replaceEnd = snapSel
|
|
1049
|
+
replaceEnd = snapSel?.start ?? replaceEnd;
|
|
1044
1050
|
} else if (inputType === "deleteContentForward") {
|
|
1045
1051
|
// Delete: キャレットの右側1文字を削除
|
|
1046
|
-
replaceStart = snapSel
|
|
1052
|
+
replaceStart = snapSel?.start ?? replaceStart;
|
|
1047
1053
|
replaceEnd = Math.min(beforeText.length, replaceEnd + 1);
|
|
1048
1054
|
}
|
|
1049
1055
|
// 追加で拾うならここ:
|
|
@@ -1250,16 +1256,25 @@ class InputGuard {
|
|
|
1250
1256
|
// console.log("[text-input-guard] input");
|
|
1251
1257
|
// compositionend後に input が来た場合、フォールバックを無効化
|
|
1252
1258
|
this.pendingCompositionCommit = false;
|
|
1253
|
-
|
|
1259
|
+
try {
|
|
1260
|
+
this.evaluateInput();
|
|
1261
|
+
} finally {
|
|
1262
|
+
// beforeinput が来ない入力経路(autocomplete等)で
|
|
1263
|
+
// 古い snapshot を使い回さないよう、1イベントごとに破棄する
|
|
1264
|
+
this.beforeInputSnapshot = null;
|
|
1265
|
+
}
|
|
1254
1266
|
}
|
|
1255
1267
|
|
|
1256
1268
|
/**
|
|
1257
1269
|
* beforeinput:入力が反映される直前に呼ばれる
|
|
1258
1270
|
* - ここでの value/selection が「今回の編集の基準点」になる
|
|
1259
|
-
* @param {
|
|
1271
|
+
* @param {Event} e
|
|
1260
1272
|
* @returns {void}
|
|
1261
1273
|
*/
|
|
1262
1274
|
onBeforeInput(e) {
|
|
1275
|
+
if (!(e instanceof InputEvent)) {
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1263
1278
|
const el = /** @type {HTMLInputElement|HTMLTextAreaElement} */ (this.displayElement);
|
|
1264
1279
|
// 現時点(反映前)の選択範囲
|
|
1265
1280
|
const selection = this.readSelection(el);
|
|
@@ -1406,6 +1421,45 @@ class InputGuard {
|
|
|
1406
1421
|
const ctx = this.createCtx();
|
|
1407
1422
|
ctx.afterText = current;
|
|
1408
1423
|
|
|
1424
|
+
/**
|
|
1425
|
+
* 入力値情報のみを使用するフォールバック
|
|
1426
|
+
* @returns {GuardContext}
|
|
1427
|
+
*/
|
|
1428
|
+
const applyFullNormalizeFromCurrent = () => {
|
|
1429
|
+
let newText = current;
|
|
1430
|
+
ctx.beforeText = "";
|
|
1431
|
+
newText = this.runNormalizeChar(newText, ctx);
|
|
1432
|
+
newText = this.runNormalizeStructure(newText, ctx);
|
|
1433
|
+
this.setDisplayValuePreserveCaret(display, newText, ctx);
|
|
1434
|
+
ctx.afterText = newText;
|
|
1435
|
+
return ctx;
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
// beforeinput が取得できない経路(初回評価)では
|
|
1439
|
+
// 差分再構成を行うと lastAcceptedValue 基準で値を落とす可能性があるため、
|
|
1440
|
+
// 現在の全文を正規化して扱うフォールバックへ切り替える。
|
|
1441
|
+
if (!this.beforeInputSnapshot) {
|
|
1442
|
+
return applyFullNormalizeFromCurrent();
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
// オートコンプリート等では beforeinput は来ても data が空のことがあり、
|
|
1446
|
+
// 差分情報だけでは再構成不能になる。表示値がすでに変わっている場合は
|
|
1447
|
+
// 再構成を諦めて current 全体の正規化に切り替える。
|
|
1448
|
+
const isDeleteInput =
|
|
1449
|
+
ctx.inputType === "deleteContentBackward" ||
|
|
1450
|
+
ctx.inputType === "deleteContentForward";
|
|
1451
|
+
const isInsertLikeInput =
|
|
1452
|
+
ctx.inputType === "" ||
|
|
1453
|
+
ctx.inputType?.startsWith("insert");
|
|
1454
|
+
const lacksDelta =
|
|
1455
|
+
ctx.insertedText === "" &&
|
|
1456
|
+
ctx.beforeText !== current &&
|
|
1457
|
+
isInsertLikeInput &&
|
|
1458
|
+
!isDeleteInput;
|
|
1459
|
+
if (lacksDelta) {
|
|
1460
|
+
return applyFullNormalizeFromCurrent();
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1409
1463
|
// 元のテキスト
|
|
1410
1464
|
const beforeText = ctx.beforeText;
|
|
1411
1465
|
|
|
@@ -7437,11 +7491,11 @@ const rules = {
|
|
|
7437
7491
|
|
|
7438
7492
|
/**
|
|
7439
7493
|
* バージョン(ビルド時に置換したいならここを差し替える)
|
|
7440
|
-
* 例: rollup replace で ""1.0.
|
|
7494
|
+
* 例: rollup replace で ""1.0.1"" を package.json の version に置換
|
|
7441
7495
|
*/
|
|
7442
7496
|
// @ts-ignore
|
|
7443
7497
|
// eslint-disable-next-line no-undef
|
|
7444
|
-
const version = "1.0.
|
|
7498
|
+
const version = "1.0.1" ;
|
|
7445
7499
|
|
|
7446
7500
|
exports.ascii = ascii;
|
|
7447
7501
|
exports.attach = attach;
|