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