@threestarsoftware/tssgrid 0.1.37 → 0.1.39
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/CHANGELOG.md +11 -0
- package/README.md +2 -0
- package/package.json +1 -1
- package/plugins/tss-autocomplete.css +1 -1
- package/plugins/tss-calendar.js +1 -0
- package/plugins/tss-datetime.js +1 -0
- package/plugins/tss-time.js +1 -0
- package/src/tssgrid.css +8 -0
- package/src/tssgrid.js +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
TssGrid の各リリースの変更点。日付は JST。形式は [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) 準拠(ゆるめ)。
|
|
4
4
|
数値は特記なき限り**自社調べ**(headless Chrome / Windows 11・環境差あり)。
|
|
5
5
|
|
|
6
|
+
## [0.1.39] - 2026-11-08
|
|
7
|
+
|
|
8
|
+
### 修正
|
|
9
|
+
- **TssAutocomplete の候補ボックスがページスクロールでズレる不具合**。ポップアップは `getBoundingClientRect()`(ビューポート基準)の座標で位置決めしているのに CSS が `position: absolute`(=ページ基準で解釈)だったため、下へスクロールするほど候補ボックスが上へずれていた。`position: fixed` に修正(他ピッカー tss-calendar / tss-time / tss-datetime / tss-combo / tss-cascade は元から `fixed`=これで同挙動に揃う)。CSS 1行のみ・JS 変更なし。利用側で `.tss-ac { position: fixed }` を上書きしていた場合、その回避策は不要。
|
|
10
|
+
|
|
11
|
+
## [0.1.38] - 2026-11-06
|
|
12
|
+
|
|
13
|
+
### 追加
|
|
14
|
+
- **`selectOnEdit`(編集開始で中身を全選択=打てば丸ごと置き換わる)**。クリック/F2 で編集を始めた時に共有 input を `select()`。**時刻/日付ピッカー(tss-time / tss-calendar / tss-datetime)は既定 ON**(値が入ったセルをクリックしてそのまま打てば置換)。列単位 `columns[c].selectOnEdit: true|false` でも指定でき、任意の列や個別の上書きに使える。
|
|
15
|
+
- **`flashInvalid`(不正値を弾いて巻き戻した時にセルを短く点滅して知らせる・コア/既定 ON)**。確定時の検証で弾かれた(=元の値へ巻き戻した)セルに短い赤パルス(`.tg-reject` 0.5s、`prefers-reduced-motion` 配慮)。従来 "revert" は無言で戻っていた穴を埋める(他グリッド同様「弾いたら知らせる」)。既存の `onInvalid(rejections, source)` コールバックはそのまま発火。`flashInvalid: false` で無効化。
|
|
16
|
+
|
|
6
17
|
## [0.1.37] - 2026-11-06
|
|
7
18
|
|
|
8
19
|
### 追加(公式フレームワークアダプタ)
|
package/README.md
CHANGED
|
@@ -1029,6 +1029,7 @@ new TssGrid(el, { hiddenColumns: [1] }); // 初期で隠す
|
|
|
1029
1029
|
| `hiddenColumns` | `number[]` | `[]` | 初期で隠す列インデックス。実行時は `hideColumn`/`showColumn`/`toggleColumn`(→ [列の表示/非表示](#列の表示非表示)) |
|
|
1030
1030
|
| `wordWrap` | `boolean` | `false` | セル内で折り返し(行高は内容に合わせ伸びる)。`columns[c].wordWrap` で列単位も可 |
|
|
1031
1031
|
| `ellipsis` | `boolean` | `false` | 溢れた文字を **… で省略**し、溢れたセルは**ホバーで全文(`title`)**。`columns[c].ellipsis` で列単位も可。見え方だけ=値・コピー・編集は全文のまま。`wordWrap` と同時なら折り返しが優先 |
|
|
1032
|
+
| `columns[c].selectOnEdit` | `boolean` | — | クリック/F2 の**編集開始で中身を全選択**(打てば丸ごと置換)。**時刻/日付ピッカーは既定 ON**。列に明示すれば任意の列で有効/無効にできる(列指定がエディタ既定より優先) |
|
|
1032
1033
|
| `placeholder` | `string` | — | 空セルに薄いヒント文字(`getData` には入らない)。`columns[c].placeholder` で列単位も可 |
|
|
1033
1034
|
| `className` | `string` | — | コンテナ(`.tssgrid`)に付ける任意クラス(テーマ付け) |
|
|
1034
1035
|
| `fillHandle` | `boolean \| {direction,autoInsertRow}` | `true` | **`false`でフィル完全OFF**(ハンドルを出さない=ドラッグでの消去/上書きなし。フィルの起点はハンドルのみなので fill 自体が無効に)。`{direction:'vertical'\|'horizontal'\|'both', autoInsertRow:true}`で詳細指定(下へドラッグで行追加)。設定/表示専用グリッドで誤フィルを防ぐのに有効 |
|
|
@@ -1045,6 +1046,7 @@ new TssGrid(el, { hiddenColumns: [1] }); // 初期で隠す
|
|
|
1045
1046
|
| `columns[c].readOnly` | `boolean \| (value,{r,c})=>boolean` | — | **列単位**の読み取り専用。関数を渡すとセル単位で判定(→ [読み取り専用](#読み取り専用readonly)) |
|
|
1046
1047
|
| `onChange` | `(grid)=>void` | — | データ変更時に呼ばれる(後方互換) |
|
|
1047
1048
|
| `onInvalid` | `(rejections, source)=>void` | — | 列ルールで弾かれた時。`rejections = [{ r, c, value, message }]` |
|
|
1049
|
+
| `flashInvalid` | `boolean` | `true` | 不正値を弾いて**巻き戻した時にセルを短く赤く点滅**して知らせる(`.tg-reject`・`prefers-reduced-motion` 配慮)。`onInvalid` は別途そのまま発火。`false` で無効 |
|
|
1048
1050
|
| `onReadOnly` | `(blocked, source)=>void` | — | 読み取り専用セルへの変更を弾いた時。`blocked = [{ r, c, value }]` |
|
|
1049
1051
|
| `contextMenu` | `boolean \| Array \| {items}` | `true` | 右クリックメニュー。`true`=既定項目 / `false`=無効 / **配列**=項目を構成(組込キー+カスタム項目)(→ [右クリックメニュー](#右クリックメニュー行列の挿入削除)) |
|
|
1050
1052
|
| `allowInsertRows` / `allowDeleteRows` | `boolean` | `true` | 行の挿入 / 削除の可否(メニュー項目の表示も連動) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threestarsoftware/tssgrid",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.39",
|
|
4
4
|
"description": "軽量・ノービルド・日本語IME堅牢な編集グリッド(vanilla JS / 依存なし / MIT)。Excel ライクな入力画面を <script> タグ1本で。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ThreeStarSoftware (https://www.threestarsoftware.co.jp/)",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* TssAutocomplete — 候補サジェスト ポップアップ。見た目は変数とクラスで自由に。 */
|
|
2
2
|
.tss-ac {
|
|
3
|
-
position:
|
|
3
|
+
position: fixed; z-index: 9999; background: #fff;
|
|
4
4
|
border: 1px solid var(--ac-border, #c3ccd6); border-radius: 6px;
|
|
5
5
|
box-shadow: 0 6px 24px rgba(20, 40, 80, .18); padding: 4px;
|
|
6
6
|
font: inherit; box-sizing: border-box;
|
package/plugins/tss-calendar.js
CHANGED
|
@@ -214,6 +214,7 @@
|
|
|
214
214
|
close: function () { teardown(); },
|
|
215
215
|
icon: opts.icon != null ? opts.icon : '📅', // セル右端に表示する合図(opts.icon:'' で消せる)
|
|
216
216
|
openOnClick: opts.openOnClick !== false, // シングルクリックで開く(既定 ON)
|
|
217
|
+
selectOnEdit: true, // クリック/F2 の編集開始で中身を全選択=打てば丸ごと置き換わる
|
|
217
218
|
inline: inline, // true=共有 input に乗る(_usesTextEditor が見る)
|
|
218
219
|
// inline のみ: 打った内容にカレンダーが追従(列の parse があれば表示形→保存値に変換して解釈)。
|
|
219
220
|
// 矢印/Enter/Esc は本体に返す=onKeyDown は持たない(キー派は打つ・マウス派はクリック)。
|
package/plugins/tss-datetime.js
CHANGED
|
@@ -184,6 +184,7 @@
|
|
|
184
184
|
close: function () { teardown(); },
|
|
185
185
|
icon: opts.icon != null ? opts.icon : '📅',
|
|
186
186
|
openOnClick: opts.openOnClick !== false,
|
|
187
|
+
selectOnEdit: true, // クリック/F2 の編集開始で中身を全選択=打てば丸ごと置き換わる
|
|
187
188
|
inline: inline, // true=共有 input に乗る=日時をそのまま直打ちできる(矢印/Enter/Esc は本体の既定)
|
|
188
189
|
// inline のみ: 打った内容にピッカーが追従(ctx.parseCell=セルの確定と同じ読み方。上で付けた parse を使う)。
|
|
189
190
|
onInput: inline ? function (v, ctx) {
|
package/plugins/tss-time.js
CHANGED
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
close: function () { teardown(); },
|
|
105
105
|
icon: opts.icon != null ? opts.icon : '🕐',
|
|
106
106
|
openOnClick: opts.openOnClick !== false,
|
|
107
|
+
selectOnEdit: true, // クリック/F2 の編集開始で中身を全選択=打てば丸ごと置き換わる
|
|
107
108
|
inline: inline, // true=共有 input に乗る=時刻をそのまま直打ちできる(矢印/Enter/Esc は本体の既定)
|
|
108
109
|
openAt: function (anchorEl, value, onPick) { show(anchorEl, value, function (v) { onPick(v); }, null); },
|
|
109
110
|
};
|
package/src/tssgrid.css
CHANGED
|
@@ -109,6 +109,14 @@
|
|
|
109
109
|
/* invalidMode:'keep' で検証 NG のセル: 値は残して赤く警告(色は変数で調整可) */
|
|
110
110
|
.tssgrid .tg-table td.tg-invalid { color: var(--tg-invalid-fg); background: var(--tg-invalid-bg); }
|
|
111
111
|
.tssgrid .tg-table td.tg-invalid.sel { background: #ffd0d6; }
|
|
112
|
+
/* 不正入力を弾いて巻き戻した時の合図(短い赤パルス)。flashInvalid:false で無効。 */
|
|
113
|
+
.tssgrid .tg-table td.tg-reject { animation: tg-reject-flash .5s ease; }
|
|
114
|
+
@keyframes tg-reject-flash {
|
|
115
|
+
0% { background: var(--tg-invalid-bg); box-shadow: inset 0 0 0 2px var(--tg-invalid-fg); }
|
|
116
|
+
70% { background: var(--tg-invalid-bg); box-shadow: inset 0 0 0 2px var(--tg-invalid-fg); }
|
|
117
|
+
100% { background: transparent; box-shadow: none; }
|
|
118
|
+
}
|
|
119
|
+
@media (prefers-reduced-motion: reduce) { .tssgrid .tg-table td.tg-reject { animation-duration: .01s; } }
|
|
112
120
|
.tssgrid .tg-table th.rowhead { background: var(--tg-rowhead-bg); width: 40px; text-align: center; color: var(--tg-rowhead-fg); position: sticky; left: 0; z-index: 2; }
|
|
113
121
|
.tssgrid .tg-table thead th.corner { z-index: 7; } /* 左上の角は最前面(top+left 固定) */
|
|
114
122
|
/* 列固定: 左から frozenCols 列を sticky で固定(left は JS が設定)。z は 選択オーバーレイ(3)より下に */
|
package/src/tssgrid.js
CHANGED
|
@@ -113,6 +113,7 @@
|
|
|
113
113
|
// parse/format を付けるか picker:false にするとテキスト入力(並び順を自分で決められる)。
|
|
114
114
|
// data: オブジェクト配列で渡す時の**バインド先キー**(例 {data:'品番'})。getRows/getValue(r,'品番') で使う。
|
|
115
115
|
this.onInvalid = opts.onInvalid || null; // (rejections, source) 検証で弾かれた時
|
|
116
|
+
this.flashInvalid = opts.flashInvalid; // 既定 undefined=点滅ON(不正で巻き戻した時にセルを短く赤く)。false で無効
|
|
116
117
|
// 読み取り専用: グリッド全体(opts.readOnly)/ 列単位(columns[c].readOnly)。編集と全変更経路を拒否。
|
|
117
118
|
this.readOnly = !!opts.readOnly;
|
|
118
119
|
this.onReadOnly = opts.onReadOnly || null; // (blocked, source) 読み取り専用セルへの変更を弾いた時
|
|
@@ -2348,6 +2349,7 @@
|
|
|
2348
2349
|
}
|
|
2349
2350
|
for (let i = changes.length - 1; i >= 0; i--) if (changes[i].neu === changes[i].old) changes.splice(i, 1);
|
|
2350
2351
|
if (rejections.length && this.onInvalid) { try { this.onInvalid(rejections, source); } catch (_) {} }
|
|
2352
|
+
if (rejections.length) this._flashInvalid(rejections); // 不正で巻き戻した/赤くしたセルを短く点滅して「知らせる」
|
|
2351
2353
|
if (!changes.length) { this.renderDump(); this.focusAndSelect(selBefore); return; }
|
|
2352
2354
|
}
|
|
2353
2355
|
// onBeforeChange: 検証 / 整形 / 取消。値は既に適用済みなので、取消は old へ巻き戻す。
|
|
@@ -2379,6 +2381,20 @@
|
|
|
2379
2381
|
if (this.onAfterChange) { try { this.onAfterChange(this._pubChanges(changes, source), source); } catch (_) {} }
|
|
2380
2382
|
this._syncHeaderCheckboxes(); // ヘッダ全選択チェックの見た目を同期
|
|
2381
2383
|
}
|
|
2384
|
+
// 不正で巻き戻した(または赤くした)セルを短く点滅して利用者に知らせる。確定後のレンダ確定を待って付与。
|
|
2385
|
+
_flashInvalid(cells) {
|
|
2386
|
+
if (this.flashInvalid === false || !cells || !cells.length) return;
|
|
2387
|
+
const grid = this;
|
|
2388
|
+
setTimeout(function () {
|
|
2389
|
+
cells.forEach(function (rc) {
|
|
2390
|
+
const td = grid.cellEl(rc.r, rc.c);
|
|
2391
|
+
if (!td) return;
|
|
2392
|
+
td.classList.remove('tg-reject'); void td.offsetWidth; // 連続でも毎回アニメを再発火
|
|
2393
|
+
td.classList.add('tg-reject');
|
|
2394
|
+
setTimeout(function () { try { td.classList.remove('tg-reject'); } catch (e) {} }, 550);
|
|
2395
|
+
});
|
|
2396
|
+
}, 0);
|
|
2397
|
+
}
|
|
2382
2398
|
commit() {
|
|
2383
2399
|
const wasEditing = this.mode === 'edit';
|
|
2384
2400
|
const r = this.active.r, c = this.active.c, oldValue = this.data[r][c];
|
|
@@ -3315,6 +3331,10 @@
|
|
|
3315
3331
|
if (t === 'checkbox') { this._toggleCheckbox(r, c); return; }
|
|
3316
3332
|
if (t === 'dropdown') { this._openSelect(); return; }
|
|
3317
3333
|
this.toEdit(this._editText(r, c), true);
|
|
3334
|
+
// selectOnEdit: クリック/F2 の編集開始で中身を全選択=打てば丸ごと置き換わる(時刻/日付ピッカー等)。
|
|
3335
|
+
// 列の selectOnEdit を最優先、無ければエディタ申告(editor.selectOnEdit)に従う。
|
|
3336
|
+
const _se = this.colCfg(c).selectOnEdit;
|
|
3337
|
+
if ((_se != null ? _se : (_ed && _ed.selectOnEdit)) && this.editor.select) { try { this.editor.select(); } catch (_) {} }
|
|
3318
3338
|
}
|
|
3319
3339
|
// カスタムエディタ口(base-editor 相当)。columns[c].editor = オブジェクト or ()=>オブジェクト。
|
|
3320
3340
|
// 契約: editor.open({ grid, r, c, value, td, commit(value), cancel() }) / 任意で editor.close()。
|