@takagaki/cortex-decisions-viewer 0.4.60 → 0.4.61

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.
Files changed (2) hide show
  1. package/dist/render.js +38 -14
  2. package/package.json +1 -1
package/dist/render.js CHANGED
@@ -3243,15 +3243,14 @@ ${capabilityState.toString()}
3243
3243
  // ノード**で、掴んでいる一覧も古い。作り直すと、下のタイルは「2リポジトリ」・
3244
3244
  // 上のモーダルは「1リポジトリ」という食い違いになる。
3245
3245
  // 取り込みは**最後の1枚を閉じたとき**に行えば足りる
3246
+ // **戻り先は畳む前に取る。** 既存の close() が前のタイルへフォーカスを戻すので、
3247
+ // 後で取ると押し替え後に閉じたとき「1枚目に開いたタイル」へ戻ってしまう
3248
+ var returnTo = document.activeElement;
3246
3249
  var existing = app.querySelector(".modal-overlay");
3247
3250
  if (existing) {
3248
3251
  if (existing.__close) existing.__close(true);
3249
3252
  else if (existing.parentNode) existing.parentNode.removeChild(existing);
3250
3253
  }
3251
-
3252
- // 開く前にフォーカスがどこにあったかを覚え、閉じたら戻す。
3253
- // 戻さないと、キーボードだけで操作している人は一覧の先頭へ飛ばされる
3254
- var returnTo = document.activeElement;
3255
3254
  var overlay = el("div", { class: "modal-overlay" });
3256
3255
  var modal = el("div", { class: wide ? "modal modal-wide" : "modal", role: "dialog", "aria-modal": "true" });
3257
3256
  // **dialog に名前を付ける。** 無いとスクリーンリーダは「ダイアログ」としか
@@ -3277,13 +3276,18 @@ ${capabilityState.toString()}
3277
3276
 
3278
3277
  function close(skipRefresh) {
3279
3278
  if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
3280
- var behind = app.querySelector(".datasources");
3281
- if (behind) { behind.removeAttribute("inert"); behind.removeAttribute("aria-hidden"); }
3279
+ setBackdropInert(overlay, false);
3282
3280
  document.removeEventListener("keydown", onKey);
3283
- if (returnTo && typeof returnTo.focus === "function" && returnTo.isConnected !== false) returnTo.focus();
3284
- // **閉じたら差し替えを試し直す。** 開いている間はライブ値の反映を見送るが、
3285
- // 見送ったままだと再取得の口が無く、タブを離れて戻るまで古い値のままになる。
3281
+ // **差し替えを先に、フォーカスを戻すのは後。**
3282
+ // isBeingEdited は「節の中にフォーカスがあるか」を見て早期returnする。
3283
+ // 先にタイルへフォーカスを戻すと、直後の refreshDataSources が自分で
3284
+ // 弾かれる——**実ブラウザではクリックでもフォーカスが当たるので必ず起きる**。
3285
+ // jsdom の .click() はフォーカスを当てないので、テストからは見えなかった。
3286
3286
  if (skipRefresh !== true && typeof refreshDataSources === "function") refreshDataSources();
3287
+ // 節ごと差し替わっていると元のノードは切り離されている。同じ id で引き直す
3288
+ var back = returnTo;
3289
+ if (back && back.id && !app.contains(back)) back = document.getElementById(back.id) || back;
3290
+ if (back && typeof back.focus === "function" && app.contains(back)) back.focus();
3287
3291
  }
3288
3292
  function onKey(e) { if (e.key === "Escape") close(); }
3289
3293
  document.addEventListener("keydown", onKey);
@@ -3301,13 +3305,33 @@ ${capabilityState.toString()}
3301
3305
  * もう一度 Enter を押しただけで、確認なしに設定ファイルが書き換わる。
3302
3306
  * 移す先は閉じるボタン——押しても何も壊れないものにする。
3303
3307
  */
3308
+ /**
3309
+ * モーダルの下地を触れなくする(解除は on=false)。
3310
+ *
3311
+ * **.datasources だけでは足りない。** タブ行・接続マップ・ヘッダのリンクが外に残り、
3312
+ * Tab で抜けられる。とくに「決定事項」タブに届くので、押すとモーダルを開いたまま
3313
+ * 画面が切り替わり、close() を通らないので keydown が1本残る。
3314
+ */
3315
+ function setBackdropInert(overlay, on) {
3316
+ var scopes = [app, document.body];
3317
+ for (var i = 0; i < scopes.length; i++) {
3318
+ var kids = scopes[i].children;
3319
+ for (var j = 0; j < kids.length; j++) {
3320
+ var n = kids[j];
3321
+ if (n === overlay || n.contains(overlay) || n.tagName === "SCRIPT" || n.tagName === "STYLE") continue;
3322
+ if (on) { n.setAttribute("inert", ""); n.setAttribute("aria-hidden", "true"); }
3323
+ else { n.removeAttribute("inert"); n.removeAttribute("aria-hidden"); }
3324
+ }
3325
+ }
3326
+ }
3327
+
3304
3328
  function showModal(overlay, modal) {
3305
- // **下地を触れなくする。** 無いと Tab がモーダルの外へ抜け、読み上げも
3306
- // 背後の一覧を読み続ける(モーダルを開いた意味が無くなる)
3307
- var behind = app.querySelector(".datasources");
3308
- if (behind) { behind.setAttribute("inert", ""); behind.setAttribute("aria-hidden", "true"); }
3309
3329
  app.appendChild(overlay);
3310
- var safe = modal.querySelector(".modal-actions button, .modal-cancel");
3330
+ setBackdropInert(overlay, true);
3331
+ // **✕ を先に探す。** 「閉じる」は一覧の最後尾にあり、focus() は対象まで
3332
+ // スクロールするので、開いた瞬間にモーダルが最下部まで飛ぶ(見出しも一覧の
3333
+ // 先頭も見えない)。✕ は見出し行=先頭で、押しても何も壊れない
3334
+ var safe = modal.querySelector(".modal-x, .modal-actions button, .modal-cancel");
3311
3335
  if (!safe) {
3312
3336
  // 閉じるボタンが無い形のモーダル用。見出しに載せて読み上げの起点にする
3313
3337
  modal.setAttribute("tabindex", "-1");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.60",
3
+ "version": "0.4.61",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,