@aiquants/virtualscroll 3.11.0 → 3.11.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"residualQuantizer.d.ts","sourceRoot":"","sources":["../src/residualQuantizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACnC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACnC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B;;;;;;;;;;;;;OAaG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B;;;;;OAKG;IACH,WAAW,EAAE,MAAM,MAAM,CAAA;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,wBAAwB,KAAG,iBAmC3E,CAAA"}
1
+ {"version":3,"file":"residualQuantizer.d.ts","sourceRoot":"","sources":["../src/residualQuantizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACnC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACnC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B;;;;;;;;;;;;;OAaG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B;;;;;OAKG;IACH,WAAW,EAAE,MAAM,MAAM,CAAA;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,wBAAwB,KAAG,iBAiD3E,CAAA"}
@@ -17,6 +17,20 @@ type ValueUpdate = {
17
17
  index: number;
18
18
  value: number;
19
19
  };
20
+ /**
21
+ * The options of a tree read that only looks rows up and never materialises them (`prefixSum`, `get`, `getTotal`,
22
+ * `findIndexAtOrAfter`, `findIndexAtOrBefore`): the read leaves the stored values, the size and `revision` as they are. One
23
+ * frozen value that every lookup passes, so no caller spells the option out. Internal to the package (not in the barrel).
24
+ *
25
+ * 行を引くだけで具現化しない木の読み取り (`prefixSum`・`get`・`getTotal`・`findIndexAtOrAfter`・`findIndexAtOrBefore`) の選択肢。
26
+ * 読み取りは保持する値・要素数・`revision` をそのまま残す。どの引き当ても渡す凍結した 1 つの値で、呼び出し側は選択肢を書き下さない。
27
+ * パッケージの内部用 (バレル非公開)。
28
+ */
29
+ export declare const FENWICK_LOOKUP_ONLY: Readonly<{
30
+ materializeOption: Readonly<{
31
+ materialize: false;
32
+ }>;
33
+ }>;
20
34
  /**
21
35
  * @class FenwickTree
22
36
  * @classdesc Implements a Fenwick Tree (or Binary Indexed Tree).
@@ -513,4 +527,38 @@ export declare const useFenwickMapTree: (size: number, valueOrFn: number | ((ind
513
527
  resetOnValueFnChange?: boolean;
514
528
  baseValue?: number;
515
529
  }) => FenwickMapTree;
530
+ /**
531
+ * What `useFenwickTreeRevision` returns: the revision the memos that read one tree depend on, and the one way to change that
532
+ * tree outside render so that they see the change.
533
+ *
534
+ * `useFenwickTreeRevision` の戻り値。1 本の木を読む memo が依存する版数と、memo が変化に気付くように描画の外でその木を変える
535
+ * ただ 1 つの方法。
536
+ */
537
+ export type FenwickTreeRevision = {
538
+ /** Advances by one per change made through `change` that moved the tree's revision / `change` を通した変更が木の版を動かすたびに 1 つ進む数 */
539
+ readonly revision: number;
540
+ /** Runs one change of the tree made outside render and returns its result; advances `revision` only when the tree's revision moved / 描画の外で行う木の変更を 1 回実行してその結果を返し、木の版が動いたときだけ `revision` を進める処理 */
541
+ readonly change: <Result>(mutate: () => Result) => Result;
542
+ };
543
+ /**
544
+ * Ties the memos of a component to the contents of a Fenwick tree. The tree keeps its identity while its contents change
545
+ * (`useFenwickMapTree`), so a memo that derives anything from its prefix sums (row tops, a rendering range, the placed
546
+ * columns) cannot see a change through the tree itself, and the total is no signal either: a batch of changes that cancel out
547
+ * leaves it as it was. Every change made outside render goes through `change`, which advances `revision` exactly when the
548
+ * tree's own revision (`FenwickMapTree.revision`) moved, so the next commit recomputes the memos that depend on `revision`,
549
+ * and a change that stores the same values (an update to the value a row already has, a materialisation that finds the stored
550
+ * value) adds no commit. Changes made during render (a reset or a resize by `useFenwickMapTree`) come with new props, which the
551
+ * memos depend on already. Internal to the package (not in the barrel).
552
+ *
553
+ * コンポーネントの memo を Fenwick 木の中身に結び付けるフック。木は中身が変わっても同一性を保つ (`useFenwickMapTree`) ので、
554
+ * 接頭辞和から何か (行の上端・描画範囲・配置した列) を導く memo は木そのものからは変化に気付けず、総和も合図にならない (打ち消し合う
555
+ * 変更の組は総和を変えない)。描画の外の変更はすべて `change` を通し、`change` は木自身の版 (`FenwickMapTree.revision`) が動いたとき
556
+ * ちょうどに `revision` を進める。だから次の確定は `revision` に依存する memo を計算し直し、同じ値を保つ変更 (行が既に持つ値への更新・
557
+ * 保持する値と同じ値を見つけた具現化) は確定を足さない。描画中の変更 (`useFenwickMapTree` のリセットと大きさの変更) は新しい props と
558
+ * 一緒に来るので、memo は既にそれに依存している。パッケージの内部用 (バレル非公開)。
559
+ *
560
+ * @param tree - The tree whose changes the memos must see / memo が変化に気付くべき木
561
+ * @returns The revision and the change runner / 版数と変更の実行関数
562
+ */
563
+ export declare const useFenwickTreeRevision: (tree: FenwickMapTree) => FenwickTreeRevision;
516
564
  export {};
@@ -17,6 +17,20 @@ type ValueUpdate = {
17
17
  index: number;
18
18
  value: number;
19
19
  };
20
+ /**
21
+ * The options of a tree read that only looks rows up and never materialises them (`prefixSum`, `get`, `getTotal`,
22
+ * `findIndexAtOrAfter`, `findIndexAtOrBefore`): the read leaves the stored values, the size and `revision` as they are. One
23
+ * frozen value that every lookup passes, so no caller spells the option out. Internal to the package (not in the barrel).
24
+ *
25
+ * 行を引くだけで具現化しない木の読み取り (`prefixSum`・`get`・`getTotal`・`findIndexAtOrAfter`・`findIndexAtOrBefore`) の選択肢。
26
+ * 読み取りは保持する値・要素数・`revision` をそのまま残す。どの引き当ても渡す凍結した 1 つの値で、呼び出し側は選択肢を書き下さない。
27
+ * パッケージの内部用 (バレル非公開)。
28
+ */
29
+ export declare const FENWICK_LOOKUP_ONLY: Readonly<{
30
+ materializeOption: Readonly<{
31
+ materialize: false;
32
+ }>;
33
+ }>;
20
34
  /**
21
35
  * @class FenwickTree
22
36
  * @classdesc Implements a Fenwick Tree (or Binary Indexed Tree).
@@ -513,5 +527,39 @@ export declare const useFenwickMapTree: (size: number, valueOrFn: number | ((ind
513
527
  resetOnValueFnChange?: boolean;
514
528
  baseValue?: number;
515
529
  }) => FenwickMapTree;
530
+ /**
531
+ * What `useFenwickTreeRevision` returns: the revision the memos that read one tree depend on, and the one way to change that
532
+ * tree outside render so that they see the change.
533
+ *
534
+ * `useFenwickTreeRevision` の戻り値。1 本の木を読む memo が依存する版数と、memo が変化に気付くように描画の外でその木を変える
535
+ * ただ 1 つの方法。
536
+ */
537
+ export type FenwickTreeRevision = {
538
+ /** Advances by one per change made through `change` that moved the tree's revision / `change` を通した変更が木の版を動かすたびに 1 つ進む数 */
539
+ readonly revision: number;
540
+ /** Runs one change of the tree made outside render and returns its result; advances `revision` only when the tree's revision moved / 描画の外で行う木の変更を 1 回実行してその結果を返し、木の版が動いたときだけ `revision` を進める処理 */
541
+ readonly change: <Result>(mutate: () => Result) => Result;
542
+ };
543
+ /**
544
+ * Ties the memos of a component to the contents of a Fenwick tree. The tree keeps its identity while its contents change
545
+ * (`useFenwickMapTree`), so a memo that derives anything from its prefix sums (row tops, a rendering range, the placed
546
+ * columns) cannot see a change through the tree itself, and the total is no signal either: a batch of changes that cancel out
547
+ * leaves it as it was. Every change made outside render goes through `change`, which advances `revision` exactly when the
548
+ * tree's own revision (`FenwickMapTree.revision`) moved, so the next commit recomputes the memos that depend on `revision`,
549
+ * and a change that stores the same values (an update to the value a row already has, a materialisation that finds the stored
550
+ * value) adds no commit. Changes made during render (a reset or a resize by `useFenwickMapTree`) come with new props, which the
551
+ * memos depend on already. Internal to the package (not in the barrel).
552
+ *
553
+ * コンポーネントの memo を Fenwick 木の中身に結び付けるフック。木は中身が変わっても同一性を保つ (`useFenwickMapTree`) ので、
554
+ * 接頭辞和から何か (行の上端・描画範囲・配置した列) を導く memo は木そのものからは変化に気付けず、総和も合図にならない (打ち消し合う
555
+ * 変更の組は総和を変えない)。描画の外の変更はすべて `change` を通し、`change` は木自身の版 (`FenwickMapTree.revision`) が動いたとき
556
+ * ちょうどに `revision` を進める。だから次の確定は `revision` に依存する memo を計算し直し、同じ値を保つ変更 (行が既に持つ値への更新・
557
+ * 保持する値と同じ値を見つけた具現化) は確定を足さない。描画中の変更 (`useFenwickMapTree` のリセットと大きさの変更) は新しい props と
558
+ * 一緒に来るので、memo は既にそれに依存している。パッケージの内部用 (バレル非公開)。
559
+ *
560
+ * @param tree - The tree whose changes the memos must see / memo が変化に気付くべき木
561
+ * @returns The revision and the change runner / 版数と変更の実行関数
562
+ */
563
+ export declare const useFenwickTreeRevision: (tree: FenwickMapTree) => FenwickTreeRevision;
516
564
  export {};
517
565
  //# sourceMappingURL=useFenwickMapTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useFenwickMapTree.d.ts","sourceRoot":"","sources":["../src/useFenwickMapTree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFenwickMapTree.d.ts","sourceRoot":"","sources":["../src/useFenwickMapTree.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useGridTapScroll.d.ts","sourceRoot":"","sources":["../src/useGridTapScroll.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAA4B,KAAK,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAEvG,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAG5F;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAA;AAalD,4MAA4M;AAC5M,MAAM,MAAM,sBAAsB,GAAG;IACjC,uIAAuI;IACvI,OAAO,EAAE,OAAO,CAAA;IAChB,mGAAmG;IACnG,WAAW,EAAE,MAAM,CAAA;IACnB,gIAAgI;IAChI,YAAY,EAAE,wBAAwB,CAAA;IACtC,6IAA6I;IAC7I,YAAY,EAAE,wBAAwB,CAAA;IACtC,sHAAsH;IACtH,UAAU,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAA;IAC1D,gDAAgD;IAChD,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,mJAAmJ;IACnJ,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,oVAAoV;IACpV,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,8YAA8Y;IAC9Y,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,2HAA2H;IAC3H,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,mLAAmL;IACnL,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;IACzC,qKAAqK;IACrK,gBAAgB,EAAE,OAAO,CAAA;IACzB,4JAA4J;IAC5J,gBAAgB,EAAE,OAAO,CAAA;CAC5B,CAAA;AAED,+DAA+D;AAC/D,MAAM,MAAM,sBAAsB,GAAG;IACjC,4FAA4F;IAC5F,WAAW,EAAE,OAAO,CAAA;IACpB,qGAAqG;IACrG,yBAAyB,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAA;IACpE,4HAA4H;IAC5H,kBAAkB,EAAE,KAAK,CAAC,SAAS,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAA;CACpE,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,sBAAsB,KAAG,sBAuQjE,CAAA"}
1
+ {"version":3,"file":"useGridTapScroll.d.ts","sourceRoot":"","sources":["../src/useGridTapScroll.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAA4B,KAAK,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAEvG,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAG5F;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAA;AAalD,4MAA4M;AAC5M,MAAM,MAAM,sBAAsB,GAAG;IACjC,uIAAuI;IACvI,OAAO,EAAE,OAAO,CAAA;IAChB,mGAAmG;IACnG,WAAW,EAAE,MAAM,CAAA;IACnB,gIAAgI;IAChI,YAAY,EAAE,wBAAwB,CAAA;IACtC,6IAA6I;IAC7I,YAAY,EAAE,wBAAwB,CAAA;IACtC,sHAAsH;IACtH,UAAU,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAA;IAC1D,gDAAgD;IAChD,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,mJAAmJ;IACnJ,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,oVAAoV;IACpV,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,8YAA8Y;IAC9Y,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,2HAA2H;IAC3H,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,mLAAmL;IACnL,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;IACzC,qKAAqK;IACrK,gBAAgB,EAAE,OAAO,CAAA;IACzB,4JAA4J;IAC5J,gBAAgB,EAAE,OAAO,CAAA;CAC5B,CAAA;AAED,+DAA+D;AAC/D,MAAM,MAAM,sBAAsB,GAAG;IACjC,4FAA4F;IAC5F,WAAW,EAAE,OAAO,CAAA;IACpB,qGAAqG;IACrG,yBAAyB,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAA;IACpE,4HAA4H;IAC5H,kBAAkB,EAAE,KAAK,CAAC,SAAS,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAA;CACpE,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,sBAAsB,KAAG,sBAiSjE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useWheelBridge.d.ts","sourceRoot":"","sources":["../src/useWheelBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAA;AAE9F;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAA;CAC7C,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,EAAE,UAAU,kBAAkB,KAAG,WAAW,CAAC,WAAW,CA+DjI,CAAA"}
1
+ {"version":3,"file":"useWheelBridge.d.ts","sourceRoot":"","sources":["../src/useWheelBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAA;AAE9F;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAA;CAC7C,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,EAAE,UAAU,kBAAkB,KAAG,WAAW,CAAC,WAAW,CA6EjI,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/virtualscroll",
3
- "version": "3.11.0",
3
+ "version": "3.11.2",
4
4
  "description": "High-performance virtual scrolling component for React with variable item heights",
5
5
  "sideEffects": [
6
6
  "**/*.css"
@@ -29,6 +29,7 @@
29
29
  "src",
30
30
  "!src/**/*.spec.ts",
31
31
  "!src/**/*.spec.tsx",
32
+ "!src/test-helpers/**",
32
33
  "README.md",
33
34
  "CHANGELOG.md",
34
35
  "LICENSE"
@@ -103,6 +104,8 @@
103
104
  "check:coverage": "node scripts/ratchet-coverage.mjs",
104
105
  "coverage:ratchet": "node scripts/ratchet-coverage.mjs --write",
105
106
  "coverage:adopt": "node scripts/ratchet-coverage.mjs --adopt",
107
+ "check:docstrings": "node scripts/ratchet-docstrings.mjs",
108
+ "docstrings:ratchet": "node scripts/ratchet-docstrings.mjs --write",
106
109
  "lint": "biome check src tests",
107
110
  "lint:fix": "biome check --write src tests",
108
111
  "format": "biome format --write src tests",
package/src/ScrollBar.tsx CHANGED
@@ -263,6 +263,39 @@ export type ScrollBarProps = {
263
263
 
264
264
  /** The minimum size of the scrollbar thumb. / スクロールバーのつまみの最小サイズ。 */
265
265
  const MIN_THUMB_SIZE = 20
266
+
267
+ /**
268
+ * One whole percent: the precision of the value text the bar and its thumb announce (`maximumFractionDigits: 0`), and how far
269
+ * inside the two ends every position between them is held before it is rounded.
270
+ *
271
+ * 1 パーセント。バーとつまみが知らせる値の文字の精度 (`maximumFractionDigits: 0`) で、両端の間のどの位置も丸める前にこれだけ
272
+ * 端の内側へ留める幅。
273
+ */
274
+ const VALUE_TEXT_PERCENT = 0.01
275
+
276
+ /**
277
+ * Resolves the fraction of the scroll range the bar and its thumb announce as their value text (formatted as a whole
278
+ * percent): 0 at the top and for a bar with nothing to scroll, 1 at or past the maximum (a list that shrank before the pane
279
+ * clamped), and every position strictly between them held in [0.01, 0.99], so the rounding never announces an end the list
280
+ * has not reached ("99%" while 999 of 200,000 rows are still below the window, "1%" one pixel below the top).
281
+ *
282
+ * バーとつまみが値の文字として知らせるスクロール範囲の割合 (整数の百分率で書く) を決める処理。先頭とスクロールできないバーは 0、
283
+ * 最大位置とそれを越えた位置 (ペインがクランプする前に縮んだ一覧) は 1、その間のどの位置も [0.01, 0.99] に留めるので、丸めが
284
+ * まだ着いていない端を知らせることはない (200,000 行のうち 999 行が窓の下に残れば "99%"、先頭から 1 px 下なら "1%")。
285
+ *
286
+ * @param scrollPosition - Scroll position (px) / スクロール位置 (px)
287
+ * @param maxScrollPosition - Maximum scroll position (px; 0 when nothing scrolls) / 最大スクロール位置 (px。スクロールできなければ 0)
288
+ * @returns The fraction to format / 書式にかける割合
289
+ */
290
+ const resolveValueTextFraction = (scrollPosition: number, maxScrollPosition: number): number => {
291
+ if (maxScrollPosition <= 0 || scrollPosition <= 0) {
292
+ return 0
293
+ }
294
+ if (scrollPosition >= maxScrollPosition) {
295
+ return 1
296
+ }
297
+ return minmax(scrollPosition / maxScrollPosition, VALUE_TEXT_PERCENT, 1 - VALUE_TEXT_PERCENT)
298
+ }
266
299
  const ARROW_HOLD_DELAY = 250
267
300
  const ARROW_HOLD_INTERVAL = 60
268
301
  const MIN_ARROW_STEP = 20
@@ -346,7 +379,15 @@ const createOrientationConfig = (horizontal: boolean): OrientationConfig => {
346
379
  mainSizeKey: "width",
347
380
  crossSizeKey: "height",
348
381
  thumbTranslateFunction: "translateX",
382
+ /**
383
+ * Picks the component of a pointer drag along the horizontal bar.
384
+ * ポインタのドラッグの、横のバーに沿う成分を選ぶ処理。
385
+ */
349
386
  selectDelta: (deltaX: number, _deltaY: number) => deltaX,
387
+ /**
388
+ * Reads a pointer's coordinate along the horizontal bar.
389
+ * ポインタの、横のバーに沿う座標を読む処理。
390
+ */
350
391
  getPointerCoordinate: ({ clientX }) => clientX,
351
392
  arrowIcons: ["◀", "▶"],
352
393
  directionClass: "aqvs-scrollbar-horizontal",
@@ -358,7 +399,15 @@ const createOrientationConfig = (horizontal: boolean): OrientationConfig => {
358
399
  mainSizeKey: "height",
359
400
  crossSizeKey: "width",
360
401
  thumbTranslateFunction: "translateY",
402
+ /**
403
+ * Picks the component of a pointer drag along the vertical bar.
404
+ * ポインタのドラッグの、縦のバーに沿う成分を選ぶ処理。
405
+ */
361
406
  selectDelta: (_deltaX: number, deltaY: number) => deltaY,
407
+ /**
408
+ * Reads a pointer's coordinate along the vertical bar.
409
+ * ポインタの、縦のバーに沿う座標を読む処理。
410
+ */
362
411
  getPointerCoordinate: ({ clientY }) => clientY,
363
412
  arrowIcons: ["▲", "▼"],
364
413
  directionClass: "aqvs-scrollbar-vertical",
@@ -443,44 +492,55 @@ const useArrowAutoRepeat = ({ canUseArrowButtons, enableArrowButtons, keyboardOp
443
492
  }, [clearArrowTimers])
444
493
 
445
494
  const handleArrowPointerDown = useCallback(
446
- (direction: 1 | -1) => (event: React.PointerEvent<HTMLButtonElement>) => {
447
- if (!canUseArrowButtons) {
448
- return
449
- }
450
- if (event.cancelable) {
451
- event.preventDefault()
452
- }
453
- event.stopPropagation()
454
- resetTapScroll()
455
- clearArrowTimers()
456
- scrollByStep(direction)
457
- arrowHoldTimeoutRef.current = window.setTimeout(() => {
458
- arrowHoldIntervalRef.current = window.setInterval(() => {
459
- scrollByStep(direction)
460
- }, ARROW_HOLD_INTERVAL)
461
- }, ARROW_HOLD_DELAY)
462
- // ボタンが disabled 化 / ウィンドウ blur で pointerup を取りこぼしてもリピートを確実に止める保険。
463
- const release = () => clearArrowTimers()
464
- globalReleaseRef.current = release
465
- window.addEventListener("pointerup", release)
466
- window.addEventListener("pointercancel", release)
467
- window.addEventListener("blur", release)
468
- },
495
+ (direction: 1 | -1) =>
496
+ /**
497
+ * Handles a press on an arrow: one step at once, then a repeat while the press is held, ended by the release anywhere,
498
+ * a cancel or the window losing focus.
499
+ * 矢印の押下を扱う処理。すぐに 1 段進め、押している間は繰り返し、どこでの解放・取り消し・ウィンドウのフォーカスの喪失で止める。
500
+ */
501
+ (event: React.PointerEvent<HTMLButtonElement>) => {
502
+ if (!canUseArrowButtons) {
503
+ return
504
+ }
505
+ if (event.cancelable) {
506
+ event.preventDefault()
507
+ }
508
+ event.stopPropagation()
509
+ resetTapScroll()
510
+ clearArrowTimers()
511
+ scrollByStep(direction)
512
+ arrowHoldTimeoutRef.current = window.setTimeout(() => {
513
+ arrowHoldIntervalRef.current = window.setInterval(() => {
514
+ scrollByStep(direction)
515
+ }, ARROW_HOLD_INTERVAL)
516
+ }, ARROW_HOLD_DELAY)
517
+ // ボタンが disabled 化 / ウィンドウ blur で pointerup を取りこぼしてもリピートを確実に止める保険。
518
+ const release = () => clearArrowTimers()
519
+ globalReleaseRef.current = release
520
+ window.addEventListener("pointerup", release)
521
+ window.addEventListener("pointercancel", release)
522
+ window.addEventListener("blur", release)
523
+ },
469
524
  [canUseArrowButtons, clearArrowTimers, resetTapScroll, scrollByStep],
470
525
  )
471
526
 
472
527
  const handleArrowKeyDown = useCallback(
473
- (direction: 1 | -1) => (event: React.KeyboardEvent<HTMLButtonElement>) => {
474
- // ポインタ専用のバーは支援技術から隠れていて、キーボードのスクロールはホストが持つ。スクリプトがフォーカスした矢印でも
475
- // キーを受けると、隠れた部品がホストのキー操作と重なって一覧を動かす
476
- if (!(enableArrowButtons && keyboardOperable)) {
477
- return
478
- }
479
- if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
480
- event.preventDefault()
481
- scrollByStep(direction)
482
- }
483
- },
528
+ (direction: 1 | -1) =>
529
+ /**
530
+ * Handles Enter and Space on a focused arrow as one step, unless the bar is pointer-only or its arrows are disabled.
531
+ * フォーカスした矢印での Enter と Space を 1 段として扱う処理 (バーがポインタ専用か矢印が無効なら何もしない)。
532
+ */
533
+ (event: React.KeyboardEvent<HTMLButtonElement>) => {
534
+ // ポインタ専用のバーは支援技術から隠れていて、キーボードのスクロールはホストが持つ。スクリプトがフォーカスした矢印でも
535
+ // キーを受けると、隠れた部品がホストのキー操作と重なって一覧を動かす
536
+ if (!(enableArrowButtons && keyboardOperable)) {
537
+ return
538
+ }
539
+ if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
540
+ event.preventDefault()
541
+ scrollByStep(direction)
542
+ }
543
+ },
484
544
  [enableArrowButtons, keyboardOperable, scrollByStep],
485
545
  )
486
546
 
@@ -780,9 +840,8 @@ export const ScrollBar = ({
780
840
  // 負値が aria-valuemax へ露出して ARIA 違反 (valuemax < valuemin) になる。644 行の
781
841
  // getScrollBarMetrics と同一のクランプ規約)
782
842
  const maxScrollPosition = Math.max(contentSize - viewportSize, 0)
783
- // ポインタ専用のバーは支援技術から隠れるので値の文字を持たない。スクロールできないバーは 0 %、中身が縮んで一時的に最大位置を
784
- // 越えた位置は 100 %
785
- const valueText = pointerOnly ? undefined : valueTextFormat.format(maxScrollPosition > 0 ? minmax(scrollPosition / maxScrollPosition, 0, 1) : 0)
843
+ // ポインタ専用のバーは支援技術から隠れるので値の文字を持たない
844
+ const valueText = pointerOnly ? undefined : valueTextFormat.format(resolveValueTextFraction(scrollPosition, maxScrollPosition))
786
845
  const effectiveTrackLength = Math.max(trackLength - thumbSize, 0)
787
846
  // scrollPosition が範囲外 (コンテンツ縮小直後の未クランプ 1 フレームや iOS バウンス値) でも
788
847
  // サムがトラック外へはみ出さないよう、レンダー時に [0, effectiveTrackLength] へクランプする。
@@ -382,6 +382,44 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
382
382
  // 同一内容の警告を繰り返さないための最後の警告キー。
383
383
  const lastViewportWarningRef = useRef<string | null>(null)
384
384
 
385
+ // 0 の帯の警告が読む中身の寸法。自己計測の副作用の依存にすると、中身の寸法が変わるたびに監視を作り直して offsetHeight を
386
+ // 確定の中で読み直し (レイアウトを強いる)、長い一覧の追記のたびにその代価を払う
387
+ const contentSizeRef = useRef(contentSize)
388
+ // 最後の計測が、レイアウトされているのに高さ 0 の帯を見つけたか。中身が後から届いたときの警告は DOM を読まずにこれで決める
389
+ const isZeroBandMeasuredRef = useRef(false)
390
+
391
+ /**
392
+ * Warns once when the last measurement found the content band laid out yet 0 px high while there is content: the host
393
+ * gave the pane no height (the self-measurement's precondition). Reads the last measurement and the content size, never
394
+ * the DOM, so a change of the content size can run it without a forced layout.
395
+ *
396
+ * 最後の計測が、中身があるのにレイアウトされた高さ 0 の帯を見つけたとき、1 度だけ警告する処理 (ホストがペインに高さを与えて
397
+ * いない = 自己計測の前提破り)。最後の計測と中身の寸法だけを読み、DOM は読まないので、中身の寸法の変化から呼んでもレイアウトを
398
+ * 強いない。
399
+ */
400
+ const warnIfHostGivesNoHeight = useCallback(() => {
401
+ if (!isZeroBandMeasuredRef.current || contentSizeRef.current <= 0 || lastViewportWarningRef.current === "zero") {
402
+ return
403
+ }
404
+ lastViewportWarningRef.current = "zero"
405
+ Logger.warn("[ScrollPane] The self-measured viewport is 0px. Give the scroll pane's host element a definite height (e.g. h-full, flex-1 + min-h-0, an explicit px height), or pass viewportSize explicitly.")
406
+ }, [])
407
+
408
+ /**
409
+ * Keeps the content size the zero-band warning reads, and runs that warning when content arrives after a 0 px
410
+ * measurement (content that loads after the pane mounted in a host without a height).
411
+ * 0 の帯の警告が読む中身の寸法を保ち、0 px の計測の後に中身が届いたとき (高さの無いホストでペインの後に読み込まれた中身)
412
+ * にその警告を走らせる副作用。
413
+ *
414
+ * 目的: 中身の寸法を自己計測の依存にせずに警告へ届ける。
415
+ * 依存関係: [contentSize, warnIfHostGivesNoHeight]
416
+ * クリーンアップ: 不要。
417
+ */
418
+ useLayoutEffect(() => {
419
+ contentSizeRef.current = contentSize
420
+ warnIfHostGivesNoHeight()
421
+ }, [contentSize, warnIfHostGivesNoHeight])
422
+
385
423
  /**
386
424
  * Tracks the real height of the content band so the pane can size itself.
387
425
  * ペインが自分の帯の実高さを追跡し、自己サイズ決定できるようにする副作用。
@@ -391,14 +429,18 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
391
429
  * 「計測した数値を書き戻して自分のサイズを変える」フィードバックループが構造的に起こらない。
392
430
  * ルート要素を測ると、消費側がルートへ付けた padding の分だけ帯を過大評価してしまう。
393
431
  *
432
+ * 読み取りはマウントの 1 回だけが同期で (確定の中なのでレイアウトを 1 回強いる。最初の描画を実寸で出すため)、以後は
433
+ * ペインの生涯に 1 つの ResizeObserver の通知から読む (通知はレイアウトの後・描画の前に届くので強制リフローにならない)。
434
+ * 中身の寸法の変化はこの副作用を走らせない。
435
+ *
394
436
  * ❗ **0 の計測は採用しない。** `display: none` のタブに置かれている等でレイアウトされて
395
437
  * いないとき `offsetHeight` は 0 になる。0 を採ると `isScrollable` が偽になり、サイズ調整
396
438
  * エフェクト (§9) が `scrollTo(0)` を発行して**タブ切替でスクロール位置が失われる**。
397
439
  * 0 は「帯が 0」ではなく「まだ測れない」と解釈し、直前の値を保つ。
398
440
  *
399
441
  * 目的: 自己計測モードで帯の高さを State へ反映する。
400
- * 依存関係: [contentSize, isSelfMeasuringViewport]
401
- * クリーンアップ: ResizeObserver を切断する。
442
+ * 依存関係: [isSelfMeasuringViewport, warnIfHostGivesNoHeight]
443
+ * クリーンアップ: ResizeObserver を切断し、0 の帯の記録を消す。
402
444
  */
403
445
  useLayoutEffect(() => {
404
446
  if (!isSelfMeasuringViewport) {
@@ -408,31 +450,32 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
408
450
  if (!element) {
409
451
  return
410
452
  }
411
- // ResizeObserver の通知は layout の後・paint の前に届くため、ここでの読み取りは強制リフローにならない。
412
- // transform: scale(...) の下でもレイアウト px を得るため rect ではなく offsetHeight を使う (整数丸め)。
453
+ /**
454
+ * Reads the content band's height into the measured viewport size, or records a 0 px band for the warning.
455
+ * コンテンツの帯の高さを計測したビューポートの高さへ読み込み、0 px なら警告のために記録する処理。
456
+ */
413
457
  const applyMeasuredSize = () => {
458
+ // transform: scale(...) の下でもレイアウト px を得るため rect ではなく offsetHeight を使う (整数丸め)。
414
459
  const measured = element.offsetHeight
415
460
  if (measured > 0) {
461
+ isZeroBandMeasuredRef.current = false
416
462
  setMeasuredViewportSize((previous) => (previous === measured ? previous : measured))
417
463
  return
418
464
  }
419
465
  // offsetParent が null なら display: none 等で非表示 = 正常な未計測状態なので黙る。
420
466
  // レイアウトされているのに 0 の場合はホストが高さを確定させていない (自己計測の前提破り)。
421
- if (element.offsetParent !== null && contentSize > 0 && lastViewportWarningRef.current !== "zero") {
422
- lastViewportWarningRef.current = "zero"
423
- Logger.warn("[ScrollPane] The self-measured viewport is 0px. Give the scroll pane's host element a definite height (e.g. h-full, flex-1 + min-h-0, an explicit px height), or pass viewportSize explicitly.")
424
- }
467
+ isZeroBandMeasuredRef.current = element.offsetParent !== null
468
+ warnIfHostGivesNoHeight()
425
469
  }
426
470
  applyMeasuredSize()
427
- if (typeof ResizeObserver !== "function") {
428
- return
429
- }
430
- const observer = new ResizeObserver(applyMeasuredSize)
431
- observer.observe(element)
471
+ const observer = typeof ResizeObserver === "function" ? new ResizeObserver(applyMeasuredSize) : null
472
+ observer?.observe(element)
432
473
  return () => {
433
- observer.disconnect()
474
+ observer?.disconnect()
475
+ // 明示の viewportSize へ切り替えた後に中身が届いても、測っていない帯の警告を出さない
476
+ isZeroBandMeasuredRef.current = false
434
477
  }
435
- }, [contentSize, isSelfMeasuringViewport])
478
+ }, [isSelfMeasuringViewport, warnIfHostGivesNoHeight])
436
479
 
437
480
  /**
438
481
  * Publishes the self-measured viewport size to the owner.
@@ -1021,12 +1064,28 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
1021
1064
  useImperativeHandle(
1022
1065
  ref,
1023
1066
  () => ({
1067
+ /**
1068
+ * Stops any inertia, then jumps to a pane position (clamped); returns the applied position.
1069
+ * 慣性を止めてからペインの位置へ跳ぶ (クランプする) 処理。当てた位置を返す。
1070
+ */
1024
1071
  scrollTo: (pos, dimsOverride) => {
1025
1072
  stopInertia()
1026
1073
  return scrollTo(pos, dimsOverride)
1027
1074
  },
1075
+ /**
1076
+ * Reads the pane position (synchronously fresh, from the position ref).
1077
+ * ペインの位置を読む処理 (位置の ref から読むので同期で最新)。
1078
+ */
1028
1079
  getScrollPosition: () => scrollPositionRef.current,
1080
+ /**
1081
+ * Reads the content size the pane was given.
1082
+ * ペインが受け取った中身の寸法を読む処理。
1083
+ */
1029
1084
  getContentSize: () => contentSize,
1085
+ /**
1086
+ * Reads the viewport size the pane uses (given or measured).
1087
+ * ペインが使う表示域の寸法 (与えられたか測ったもの) を読む処理。
1088
+ */
1030
1089
  getViewportSize: () => viewportSize,
1031
1090
  applyWheel,
1032
1091
  }),
@@ -360,9 +360,17 @@ export const TapScrollCircle = memo(
360
360
  useImperativeHandle(
361
361
  ref,
362
362
  () => ({
363
+ /**
364
+ * Returns the circle to its resting state and reports it through `onDragChange`.
365
+ * サークルを静止の状態へ戻し、`onDragChange` で知らせる処理。
366
+ */
363
367
  reset: () => {
364
368
  resetState(true)
365
369
  },
370
+ /**
371
+ * Reads the circle's root element (null while it is not mounted).
372
+ * サークルのルートの要素を読む処理 (マウントしていない間は null)。
373
+ */
366
374
  getElement: () => rootRef.current,
367
375
  }),
368
376
  [resetState],