@aiquants/daily-report 0.29.0 → 0.31.0
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 +96 -0
- package/README.md +119 -69
- package/dist/client.d.mts +30 -5
- package/dist/client.d.ts +30 -5
- package/dist/client.js +4 -4
- package/dist/client.mjs +4 -4
- package/dist/{comment-adapter-5bAtR4qb.d.ts → ids-stream-BR5RSj5u.d.ts} +22 -2
- package/dist/{comment-adapter-lV2ZB_vH.d.mts → ids-stream-DvB2h1dj.d.mts} +22 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/server.d.mts +52 -131
- package/dist/server.d.ts +52 -131
- package/dist/server.js +4 -4
- package/dist/server.mjs +4 -4
- package/dist/styles/daily-report.standalone.css +1 -1
- package/dist/{ids-stream-CWuIDrIO.d.mts → types-DkERw8NE.d.mts} +1 -22
- package/dist/{ids-stream-CWuIDrIO.d.ts → types-DkERw8NE.d.ts} +1 -22
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,102 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@aiquants/daily-report` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.31.0 (2026-10-06)
|
|
6
|
+
|
|
7
|
+
0.30.0 の続き: 編集中の入力が描画の窓の外や選択の移動を越えて残ること、要求の値 (営業日・ID・操作の時刻・フォーム) の厳格な解釈と作成した日報の営業日を UTC の 0 時で格納すること、原本の `Content-Length` を渡す本文から決めること、一覧の行を ids ストリームの変化だけで導くことと SSE の知らせの合体、合体窓を単調な時計で測ること、行の集合の大きさ (`aria-setsize`) と見出しの総件数を申告した総数で決めること、ホバーの浮き上がりの定義域を 1 から 3 までの 1/4 の倍数のすべてへ広げること、要求の隔離の結線を型で決めること。どれも README の該当の節が今の契約を記す。
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **編集中の入力は、行が描画の窓を外れても選択を移しても残る**: 編集の状態 (開いているか・自分で開いたか) と入力中の件名と本文は、行やペインの状態ではなく、アクションのプロバイダーが 1 つ持つ編集の置き場 (日報ごと。`src/client/contexts/daily-report-draft-store.ts`) にある。DetailList の行が仮想スクロールの描画の窓を外れて戻っても (ホイール・ドラッグ・スクロールバー・タップスクロール・別の行からのキー・ホストの選択)、List の側面ペインとモバイルのオーバーレイが別の日報を表示して戻っても、編集モードと入力中の値のまま描く。入力で描き直すのはフォームだけ (行・ペインの中身・一覧は描き直さない)。
|
|
12
|
+
同じ日報の SSE の更新は入力中の値を上書きせず、保存の成功は値を残し、キャンセルは値を捨てる。公開の成功と日報の削除 (利用者の削除・SSE の `report-delete`・読み込めない日報の除去) は日報の項目を捨て、サーバーが拒んだ削除は日報と一緒に項目も残す。置き場の寿命はプロバイダーと同じで、ページを離れる・再読み込み・利用者の切り替えで空になる。
|
|
13
|
+
以前は編集中かどうかを行の状態に、入力をフォームの状態に持ったので、行が窓を外れるか選択が移ると、入力中の件名と本文が消えた (下書きは保存済みの値で開き直し、公開済みの日報は表示に戻った)。
|
|
14
|
+
- **作成した日報の営業日は、どの時間帯のサーバーでもその日**: 作成の営業日はその日の UTC の 0 時として格納し、日報の `date` に正準のキー (`YYYY-MM-DD`) を返す。以前は送られた文字列を `new Date()` の自由な解釈へ渡したので、`2026/10/06` をサーバーのローカルの 0 時と読み、UTC より東の時間帯では前日 (`2026-10-05T15:00:00.000Z`) で格納した。`2026-02-30` は 2026-03-02、`1` は 2001-01-01 の日報になった。
|
|
15
|
+
- **要求の値は 1 つの厳格な解釈で読み、誤りはどのクエリよりも前に 400**: API の経路と action は、営業日を `YYYY-MM-DD` か `YYYY/MM/DD` (区切りは 2 か所とも同じ) の 0001-01-01 から 9999-12-31 までの暦にある日だけ (`parseBusinessDateKey`)、日報とコメントの ID を正の安全な整数の正準の 10 進の形だけ (`parseCanonicalPositiveId`。先頭に 0 を持たない数字で 1 から 2^53 − 1)、操作の時刻 (`operationTimestamp`) を 0 以上の安全な整数の正準の 10 進の形だけで読む。
|
|
16
|
+
`business-date` は暦にある日でも前後の空白・時刻付きの ISO 8601・日付の文章を 400 (`Invalid business date`) で答え、`report` は `12abc`・`1e3`・`1.9`・` 7 ` を 400 (`Invalid reportHubId`) で答える。action は送られた営業日をどの操作でも検証し (`Invalid businessDate`)、ID と時刻の誤りを `Invalid reportHubId`・`Invalid commentId`・`Invalid operationTimestamp` で答え、フォームとして読めない本文を error の行を残さない 400 (`Invalid form`) で答える。テキストを求める欄のファイルの部分は無い欄ではなく不正な値。action はフォームを丸ごと解釈してから内部ユーザー・可視集合・操作を解決する。
|
|
17
|
+
以前は `Number.parseInt` と `Number()` の寛容な解釈で読んだので、`report?reportHubId=12abc` が日報 12 を返し、action の `reportHubId=1e3` は日報 1000 に、`-3` はサービスまで届き、2^53 + 1 は隣の整数に丸まって別の日報を名指しえた。営業日は自由な日付の解釈を通り (`business-date` は `Tue Oct 06 2026` も受けた)、読めない本文は error の行 2 本の 500 になった。
|
|
18
|
+
- **原本の `Content-Length` は渡す本文から決める**: GET の `Content-Length` は渡すバイト列の長さで、読み取りポートが申告した `size` がそれと違えばポートの契約違反として 500 (`reason=port_contract code=size_mismatch`、error) で答え、本文を送らず実体の有無も記録しない。HEAD の `Content-Length` はポートが申告した `size` で、申告が無ければ付けない (RFC 9110 §8.6)。
|
|
19
|
+
以前は GET も申告した `size` を優先したので、大きさを別の呼び出しで測るポートの申告が本文と食い違うと、短い本文は読み手を待たせ続け、長い本文は切れた。申告の無い HEAD は本文のある原本に `Content-Length: 0` を名乗った。
|
|
20
|
+
- **行の集合の大きさは申告した総数**: 両ビューの行の `aria-setsize`、List のカードの読み上げる位置 (全 N 件中 M 件目) と見出しの総件数は、ビューの行が属する集合の大きさを読む (`DailyReportResolvedContent` が 1 か所で決める)。ids ストリームが一覧を届けている間はサーバーが最初の行で申告した総数 (見せている行の数より小さくはしない)、申告の前は分からない (`aria-setsize="-1"`、見出しは `labels.totalCountLoading`、位置は新しいキー `listRowPositionInUnknownTotal` の「M 件目」)、完走した後は見せている行の数。
|
|
21
|
+
以前は届いた行の数だったので、228,222 件の一覧の走査の途中で「全 4,200 件中 3 件目」と読み、チャンクが届くたびに集合の大きさと見出しの総件数が変わった。
|
|
22
|
+
- **ホバーの浮き上がりは 1 から 3 までの 1/4 の倍数のどの画素密度でも整数の装置の画素**: 浮き上がり L = ⌊2·dpr⌋ / dpr の上書きを、2·dpr が整数でない 1.25・1.75 に加えて 2.25 (16/9 px、4 装置画素) と 2.75 (20/11 px、5 装置画素) にも置く。以前の 2.25 と 2.75 では 2 px が 4.5 と 5.5 装置画素になり、ホバーした面が装置の画素の半分に乗った (1 px の枠線・輪・アウトラインが隣の画素の行へにじんだ)。
|
|
23
|
+
- **ids ストリームの publish の合体窓は単調な時計で測る**: 合体窓の経過は `performance.now()` で測る (完走の時刻 `completedAt` は時刻なので壁時計のまま)。以前は壁時計で測ったので、時刻合わせで時計が戻ると、戻った分だけ次の publish が遅れた (60 秒戻れば 60 秒)。
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **一覧の行は ids ストリームの変化だけを当てはめて導く**: ストリームのアイテムの publish は、一覧と一緒にその版 (`itemsRevision`。どのセッションの間でも重ならない) と、publish ごとの正味の変化 (入った・値が変わった・離れた日報) を版の鎖で運ぶ (`itemsChanges`。最新の 32 件)。アクションのプロバイダーは行を正準の順 (営業日の降順 → id の降順、営業日の無い日報は末尾) に保ち、最後に当てはめた版からの変化だけを、1 回の描画が何回の publish を受けても 1 つに畳んで当てはめる。
|
|
28
|
+
前の末尾の後ろへ入る行は 1 回の比較とネイティブの連結で済み (Δ 件を運ぶ publish が触る行は、ストリームのクライアントを含めて Δ + 1 まで)、順を外れて届いた行は二分探索で差し込み、値の変わった行はその場で置き換え (⌈log2 n⌉)、一覧全体を 1 回たどるのは削除だけ。一覧全体から導き直すのは、最初の描画・セッションの置き換わり・32 回より多い publish の遅れのときだけ。
|
|
29
|
+
以前は publish ごとに一覧を作り直したので、228,222 件の走査では publish のたびに届いた行の数に比例して触る行が増えた (4,000 件のチャンクの 2 回目で 8,000 行、以後も増え続けた)。
|
|
30
|
+
- **SSE の作成・公開・削除の知らせもチャンクと同じ合体窓を通る**: プロバイダーが常駐のストリームへ中継する変化 (SSE の `report-create`・`report-publish`・`report-delete` と、利用者自身の作成と削除) は、チャンクと同じ 50 ms の窓で 1 回の publish にまとまる (窓の外の最初の変化はすぐ、窓の中の変化は窓の終わりに 1 回、走査の完走は保留中の変化を待たずに運ぶ)。SSE の知らせが連なって届いても一覧は 1 回で変わり、行は最初の知らせから 50 ms 以内に現れる (以前は知らせごとにすぐ)。利用者自身の作成と削除は今までどおりすぐ見える (プロバイダーがその行を自分で足し、外す)。
|
|
31
|
+
- **自動で開く編集は表示中ユーザーの下書きだけ、キャンセルした下書きは開き直さない**: List の側面ペインも DetailList の行と同じ規則で、表示中ユーザーの下書きだけを編集モードで開く (以前の側面ペインはどの下書きも開いた)。キャンセルした下書きは、選択を移して戻っても、行が窓を外れて戻っても表示のまま (置き場が空になるまで)。
|
|
32
|
+
- **開発者向け**: 要求の隔離の結線を型で決める。経路の方針 (`RequestIsolationPolicy`) は拒否の記録の名前 (`route`) も持ち、包みは方針とハンドラーだけを受け取る (`isolated(policy, handler)`)。共通の土台 `NOT_NAVIGABLE` は `route` を持たないので、名前を書かない方針は型検査で落ちる。API の経路のエンドポイントの名前と答える本体の種類は `src/server/api-endpoint.ts` の表 (`API_ENDPOINT_BODY_KINDS`) にだけ書き、メソッド (`API_ENDPOINT_METHODS`) と API の経路のデータの要求の断り (`API_LOADER_ISOLATION_POLICY`) はそこから導く。action の方針は `ACTION_ISOLATION_POLICY` (記録の名前は `action`)。答えと記録の行は変わらない。
|
|
33
|
+
要求の値の解釈は `src/shared/business-date.ts` (`parseBusinessDateKey`・`isCanonicalBusinessDateKey`) と `src/server/wire-params.ts` (`parseCanonicalPositiveId`・`parseCanonicalNonNegativeInteger`・`isPositiveSafeInteger`・`formFieldText`) に 1 つずつある。ids のストリームの再開カーソルと添付のトークンの ID も同じ解釈で読む (カーソルの営業日は正準のキーだけ)。
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- client のラベルのキー `listRowPositionInUnknownTotal(position)`: 集合の大きさが分からない間の List のカードの位置 (en "Item 3"、ja 「3 件目」)。固有のキーは 85 (全体は 96) で、上書きは関数でなければならない。
|
|
38
|
+
- `DailyReportList` と `DailyReportDetailList` の prop `rowSetSize`: 行が属する集合の大きさ (分からない間は −1)。省けば渡した行が集合そのもの。`VirtualScroll` の行の数はいつも渡した行の数。
|
|
39
|
+
- `DailyReportIdsStreamClient` の `has(reportHubId)` (常駐の一覧がまだ publish していない変化を含めてその日報を持つか) と、合体窓の単調な時計を差し替える `now` オプション (既定は `performance.now()`)。`useDailyReportIdsStream` の状態の `itemsRevision` と `itemsChanges` (上の Changed)。
|
|
40
|
+
|
|
41
|
+
### Breaking
|
|
42
|
+
|
|
43
|
+
- shared の `normalizeBusinessDateKey` は文字列を厳格に読む: `YYYY-MM-DD` か `YYYY/MM/DD` で 0001-01-01 から 9999-12-31 までの暦にある日だけをキーにし、それ以外 (前後の空白・時刻付きの ISO 8601・日付の文章・暦に無い日・0 年) は `null`。`Date` は今までどおりローカルの暦日。以前は空白を削り、形の合う `YYYY-MM-DD` を暦を見ずに受け (`2026-02-30`)、ほかの文字列は `new Date()` の自由な解釈で読んだ。
|
|
44
|
+
Migration: 時刻付きの文字列は `Date` にしてから渡すか、日付の部分 (`YYYY-MM-DD`) を切り出して渡す。
|
|
45
|
+
- client の `DailyReportActionProvider` は `initialItems` を受け取らない: 行はモジュール常駐の ids ストリームのセッションから自分で導く。
|
|
46
|
+
Migration: `initialItems` を外し、プロバイダーを描く前にセッションを確立する (経路の `createDailyReportClientLoader`、またはマウントのときの `ensureDailyReportIdsStreamSession({ apiBasePath, userKey })`。`DailyReportPage` は自分で確立する)。利用者ごとにプロバイダーをマウントし直す (`key={userId}`)。
|
|
47
|
+
- API の経路と action は、寛容な解釈なら読めた値を 400 で答える (上の Fixed): 営業日は `YYYY-MM-DD` か `YYYY/MM/DD` の暦にある日だけ (action は作成以外の操作でも、送られた営業日を検証する)、ID は正準の 10 進の正の整数だけ、`operationTimestamp` は 0 以上の整数だけ。action が送り返す `operationTimestamp` は、送られなければ `null` (以前は 0)。
|
|
48
|
+
Migration: 営業日は `YYYY-MM-DD` で送る (時刻付きの値は日付の部分を切り出す)。ID と時刻は 10 進の整数の文字列で送り、時刻が無ければ欄ごと省く。
|
|
49
|
+
- server の `service.createDailyReport(userId, businessDate, clientTempId)` は正準のキー (`YYYY-MM-DD`) だけを受け、それ以外にはどのクエリよりも前に `RangeError` (`[daily-report] createDailyReport: businessDate must be a business-date key in the canonical form YYYY-MM-DD naming a day from 0001-01-01 to 9999-12-31; got "<値>"`) を投げる。格納するのはその日の UTC の 0 時。
|
|
50
|
+
Migration: 斜線の形は公開の `normalizeBusinessDateKey` (文字列は同じ厳格な解釈で読む) で正準のキーにしてから渡し、時刻付きの値は日付の部分を切り出してから渡す (action は自分で解釈してから渡す)。
|
|
51
|
+
- client の型 `DailyReportLabels` に必須のキー `listRowPositionInUnknownTotal(position)` が増えた (上の Added)。
|
|
52
|
+
Migration: `DailyReportLabels` を丸ごと組むホスト (試験の代役など) はこのキーも書く。上書き (`DailyReportLabelOverrides`) は部分のままでよい。
|
|
53
|
+
- 読み取りポートの `size` の契約: GET の読み取りで申告するなら `bytes.byteLength` と等しくなければならず、違えば 500 (上の Fixed)。HEAD で申告しなければ、HEAD の応答は `Content-Length` を持たない (以前は `0`)。
|
|
54
|
+
Migration: GET では `size` を省くか `bytes.byteLength` を返し、HEAD では実体の大きさを返す (README の Read port の例はどちらもそうしている)。
|
|
55
|
+
- ピアの `@aiquants/virtualscroll` の下限を 3.11.4 へ上げた (`peer-floors.json`)。両ビューが 3.11.2〜3.11.4 の変更に頼る所は無いが、この版の試験はすべて 3.11.4 の上で通したので、公開する範囲 (`^3.11.4`) と文書の下限をそれに合わせた。
|
|
56
|
+
Migration: `@aiquants/virtualscroll` を 3.11.4 以降へ上げる。
|
|
57
|
+
|
|
58
|
+
## 0.30.0 (2026-10-06)
|
|
59
|
+
|
|
60
|
+
0.29.0 の続き: 本体をストリームで返す 2 つの経路のフレームワークのデータの要求をパッケージが断ること (ホストの経路は薄いマウントに戻る)、原本の本文の 1 切れずつの受け渡しと無通信の締め切りと閲覧者ごとのスロットの上限、間隔を単調な時計で測ること、読み取りの予算切れの 504、暦に無い営業日の 400、行とカードのフォーカスのアウトラインをキーボードのフォーカスの属性の下だけで描くこと、整数の装置の画素のホバーの浮き上がり、List のカードの位置の読み上げ、キーの移動の `tabindex` をフォーカスの受け渡しで書くこと、ハンドラーの設定と戻り値の型の公開。どれも README の該当の節が今の契約を記す。
|
|
61
|
+
|
|
62
|
+
### Security
|
|
63
|
+
|
|
64
|
+
- **ストリームの経路へのフレームワークのデータの要求はパッケージが断る**: ハンドラー工場の要求の隔離の包みが、SSE の経路 (`sse.loader`) へのデータの要求はどれも、API の経路 (`api.loader`) へのものは ID 一覧の NDJSON の分 (`ids-stream.data`。カーソル付きと末尾の斜線の `ids-stream/_.data` も) だけを、GET も HEAD も、認証より前に 404 の JSON (`{"error":{"message":"Not Found"}}`、`Cache-Control: no-store`・`X-Content-Type-Options: nosniff`) で断る (経路の方針の `frameworkDataRefusal`: `SSE_ISOLATION_POLICY`・`API_LOADER_ISOLATION_POLICY`)。断った要求は認証・購読・タイマー・クエリのどれも始めず、拒否の記録にも書かない。JSON のエンドポイント (`report`・`business-date`) と action は今までどおりデータの要求を受ける。
|
|
65
|
+
以前はホストの経路が断る契約だったので、断りを置き忘れたホストでは `<経路>.data` の要求 1 つが、終わらない SSE の本体か ID 一覧の NDJSON の全量をサーバーのメモリに溜めた。どのホストも版を上げれば守られ、2 つの経路は薄いマウント (`(args) => dailyReportServer.sse.loader(args)` と `(args) => dailyReportServer.api.loader(args)`) でよい。
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
|
|
69
|
+
- **原本の本文は 1 切れずつ渡し、止まった読み手はスロットを握り続けない**: GET の原本の本文は、256 KiB の 1 切れの写しを、ホストの書き手が読むたびに 1 つずつ渡す (本文は書き手の先に何も積まない)。同時実行のスロットは原本を参照する間だけ保持し、最後の 1 切れを渡したとき・クライアントが本文を取り消したとき・書き手が 60 秒のあいだ次の 1 切れを求めなかったとき (無通信の締め切り。読みのたびに始め直す) に返す。締め切りでは本文を失敗で終え、原本の残りを捨てる。
|
|
70
|
+
1 人の閲覧者が同時に保持できる原本のスロットは枠の半分の切り上げ (⌈`attachmentConcurrency` / 2⌉。既定の 4 なら 2) で、それを超える要求は空きがあっても過負荷の 503 (`reason=concurrency`、`Retry-After`) になる。プロセスが溜めうるのは、転送が進む間は「同時実行 × 原本の上限」に応答ごとの渡し済みの 1 切れを足した分、無通信の締め切りを過ぎて止まった応答には 1 切れだけ (README の Attachments の Heap estimate)。
|
|
71
|
+
以前は原本全体を最初の読みで本文の待ち行列へ渡し、スロットは送り終えるか 120 秒のバックストップまで保持した。読み止めたクライアントはスロットを 120 秒握り、バックストップの後もバイト列は書き手の待ち行列に残ってヒープの見積りの外に溜まり、1 人の閲覧者が読み止めた転送を並べれば枠を全部握ってほかの閲覧者を 503 にできた。
|
|
72
|
+
- **間隔・締め切り・有効期限は単調な時計で測る**: サーバー層のレートのバケットの補充、SQL の結果のキャッシュの有効期限、縮小画像の段の締め切りを過ぎた決着と決着しない読み取りや描画の計時、ハンドラーとサービスの経過時間のログは、プロセスの単調な時計 (`performance.now()` の切り捨て) で測る。壁時計は意味が時刻のもの (記録の `since=`・一時的な ID) だけに使う。
|
|
73
|
+
以前は壁時計で測ったので、運用の時刻合わせで時計が戻ると、戻った分だけレートのバケットが補充されず (429 が `Retry-After` より長く続く)、キャッシュが有効期限を過ぎても新しいまま残った。
|
|
74
|
+
- **暦に無い営業日は 400**: API の `business-date` は、形の合う日付でも暦に無い日 (`2026-13-40`・`2026-02-29`・`2026/04/31`・月 0) を、クエリより前に 400 (`Invalid business date`) で答える。以前は形だけを見てクエリへ渡し、データベースの変換の失敗が 500 (サーバーの失敗の行) になった。
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- **読み取りの予算切れは 504**: 縮小画像の生成の読み取りの段の締め切り (`readMs`、30 秒) が先に来たときの答えは 504 (`reason=read_timeout`、文面は `Thumbnail storage timed out`) で、ポート自身の締め切り (`deadline`) と同じ状態になった。ストレージの読み取りの締め切りは、どちらが先に切れてもクライアントには同じ 504 で、ログの理由がどちらの締め切りかを残す (どちらも warn)。キャッシュにも実体消失にも書かないのは今までどおり。縮小の段の締め切りは 502 (`render_timeout`) のまま。以前は読み取りの予算切れも 502。
|
|
79
|
+
- **行とカードのフォーカスのアウトラインはキーボードのフォーカスの属性の下でだけ描く**: 行の枠の面と List のカードの面のアウトラインは、`:focus-visible` に加えて、ビューの根要素が `data-daily-report-keyboard-focus` を持つときだけ描く (`ROW_FRAME_STATE_CLASS_NAME`・`CARD_SURFACE_STATE_CLASS_NAME`。祖先は `:where()` で読むので、詳細度は (0,2,0) と (0,3,0) のまま)。アウトラインを描くなら属性があり、属性があればタップスクロールのサークルは隠れるので、2 つが一緒に出ることは作りから無い。操作部品 (ボタン・リンク・タブ・スイッチ・入力欄) の輪は今までどおり `:focus-visible` だけに依る。
|
|
80
|
+
以前は Chromium がポインターの押下の後の `Shift` や `CapsLock` だけの押下でも `:focus-visible` とするので、ビューがポインターの操作と見なしてサークルを描いている間に、行のアウトラインも描かれた。
|
|
81
|
+
- **ホバーの浮き上がりは整数の装置の画素**: カードのホバーの浮き上がり L は、画素密度 dpr で 2 CSS px 以下の最大の整数の装置の画素 (⌊2·dpr⌋ / dpr): 1・1.5・2・3 では 2 px、1.25 では 1.6 px (2 装置画素)、1.75 では 12/7 px (3 装置画素)。値はカード自身のカスタムプロパティ `--aqdr-hover-lift` に置き、2 つの画素密度だけを `resolution` の媒体条件で上書きし、浮き上がりの `translate` がそれを読む。G = 8 ≥ 輪 2 + 隙間 2 + アウトライン 2 + L は保たれる。
|
|
82
|
+
以前は常に 2 px で、1.25 と 1.75 ではホバーした面が装置の画素の半分に乗り (2.5 と 3.5 装置画素)、1 px の枠線・輪・アウトラインが隣の画素の行へにじんだ。
|
|
83
|
+
- **キーの移動の `tabindex` はフォーカスの受け渡しで書く**: 行カーソルは移動先の `tabindex="0"` を `focus()` の前ではなく、移動元のフォーカスが外れた所 (移動元の `focusout` の中。どの要素もフォーカスを持たない) で書く。Chromium の `focus()` は要素の間のフォーカスの移動のたびにスタイルを 2 回計算し直し (移動元が失った直後と移動先が得た直後)、書き込みはその 1 回目に相乗りする。
|
|
84
|
+
以前は `focus()` の前に書いたので、ホストの CSS が `[tabindex]` を見ると `focus()` の入口でもう 1 回計算し直した (Chromium 148 で 8 回のキーの移動が 24 回。今は 16 回)。
|
|
85
|
+
- **DEV の操作箱のアイコンのボタンの的は 24 × 24**: 再読み込みとキャッシュの消去のボタン (`showDevControls`) は、見た目の 16 px のまま、上下左右に 4 px はみ出す擬似要素で 24 × 24 の的を持ち (WCAG 2.5.8)、8 px 離れて並ぶ。以前は 16 × 16 の的が 4 px 離れて並んだ。
|
|
86
|
+
- **開発者向け**: ハンドラーの工場のモジュールを分けた。`src/server/handlers.ts` は設定・ロガー・可視集合の解決・index・JSON のエンドポイントの表・action・要求の隔離の包みを持ち、SSE の配信は `src/server/sse-delivery.ts`、ID 一覧の NDJSON の配信は `src/server/ids-stream-delivery.ts`、本体をストリームで返す 2 つの答えが共有する HEAD の規則は `src/server/stream-body.ts`、時計は `src/server/monotonic-clock.ts` にある。添付のレートのバケット (`createRateLimitBucket`) は制限・閲覧者ごとの拒否の記録・429 を 1 つに持ち、原本と縮小画像の配信が使う (行の書式は変わらない)。
|
|
87
|
+
docstring の歯止め (`scripts/lib/ratchet-docstrings.mjs`) は、関数が返す関数と、オブジェクトのリテラルの関数の値のプロパティも数え (呼び出し・`new`・JSX の属性へ渡すリテラルは数えない)、基準 (`docstring-baseline.json`) はこの規則で 1 回記録し直した。React Router の実物の要求の処理を通す spec は、断った `.data` の要求ごとに loader が 1 回呼ばれて認証が 0 回であること (経路の照合が外れた 404 ではないこと) を確かめ、添付の行は同じ URL の `.data` の無い要求が同じ処理で答えることも確かめる。
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- client のラベルのキー `listRowPosition(position, total)`: List のカードの主ボタンの最初の説明になる、一覧の中の位置 (en "3 of 40"、ja 「全 40 件中 3 件目」。数は UI の言語の桁区切り)。フォーカスを受ける主ボタンは `aria-posinset` を持てないので、行の枠の位置を言葉で伝える。窓より前への挿入・削除で描き直すのは行の枠とこの文言だけで、カードの本体は描き直さない。固有のキーは 84 (全体は 95) で、上書きは関数でなければならない。
|
|
92
|
+
- server の型 `DailyReportHandlersConfig`・`DailyReportHandlers` (`createDailyReportHandlers` の設定と戻り値) と `DailyReportServer` (`createDailyReportServer` の戻り値)。ホストと例は `Parameters<>` や `ReturnType<>` で引き直さずに読み込む。型だけの公開なので、バンドルは増えない。
|
|
93
|
+
|
|
94
|
+
### Breaking
|
|
95
|
+
|
|
96
|
+
- server の値 `DAILY_REPORT_IDS_STREAM_ENDPOINT` を公開しない: フレームワークのデータの要求の断りはパッケージの要求の隔離が決め (上の Security)、ホストの経路はエンドポイントの名前を比べない。
|
|
97
|
+
Migration: ホストの SSE の経路と API の経路から `.data` の断り (`<経路>.data` に 404 を投げる部品) と `DAILY_REPORT_IDS_STREAM_ENDPOINT` の読み込みを外し、`sse.loader` と `api.loader` をそのままマウントする。React Router の実物の要求の処理を通す経路の試験は、そのまま 404 を確かめられる。
|
|
98
|
+
- ピアの `@aiquants/virtualscroll` の下限を 3.11.1 へ上げた (`peer-floors.json`)。両ビューが 3.11.1 の変更に頼る所は無いが、この版の試験はすべて 3.11.1 の上で通したので、公開する範囲 (`^3.11.1`) と文書の下限をそれに合わせた。
|
|
99
|
+
Migration: `@aiquants/virtualscroll` を 3.11.1 以降へ上げる。
|
|
100
|
+
|
|
5
101
|
## 0.29.0 (2026-10-06)
|
|
6
102
|
|
|
7
103
|
0.28.0 の続き: 添付の経路のフレームワークのデータの要求 (`<token>.data`) の拒否、本体をストリームで返す 2 つの答え (SSE と ID 一覧) の HEAD、読み取りポートの失敗の理由 `busy` と `deadline`、窓の終わりに数を書く拒否と 429 の記録、行のサイズの裏付けの無い `too_large` をキャッシュしない縮小画像の生成、ポインターで押したフォーカスをキーボードのフォーカスと見なさない判定、枠を越えない折り返す文言と側面ペインのパネルの最小の幅、DetailList のカードの日付の `<time>`。どれも README の該当の節が今の契約を記す。
|