@aiquants/virtualscroll 3.6.1 → 3.7.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.
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @module labels
3
+ * @description Built-in UI chrome label catalog of the package. Covers exactly the seven strings
4
+ * the components render on their own: the ScrollBar arrow aria-labels, the VirtualScroll
5
+ * scroll-to-edge pill texts and the empty-state text. Live-region wording stays consumer-owned
6
+ * (`liveRegion.format` / `liveRegion.buildMessage`) and is not part of this catalog. The default
7
+ * locale is `"en"`; `"ja"` is the second locale. No language negotiation happens here: hosts map
8
+ * `navigator.language` (or anything else) to a supported locale themselves.
9
+ *
10
+ * @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する 7 文言
11
+ * (ScrollBar 矢印の aria-label、VirtualScroll の端スクロールピル文言、空状態文言) だけを対象とし、
12
+ * ライブリージョンの文言は利用側の所有 (`liveRegion.format` / `liveRegion.buildMessage`) で
13
+ * 本カタログの対象外。既定ロケールは `"en"`、第 2 ロケールは `"ja"`。言語ネゴシエーションは行わず、
14
+ * `navigator.language` 等から対応ロケールへの対応付けはホスト側の責務。
15
+ */
16
+ /**
17
+ * Supported UI chrome locales, in declaration order. The first entry is NOT implicitly the
18
+ * default — the default lives only in {@link resolveVirtualScrollLocale}.
19
+ * 対応する UI クロームロケールの一覧 (宣言順)。先頭要素が暗黙の既定値になるわけではなく、
20
+ * 既定値は {@link resolveVirtualScrollLocale} にのみ存在。
21
+ */
22
+ export declare const VIRTUAL_SCROLL_LOCALES: readonly ["en", "ja"];
23
+ /**
24
+ * A supported UI chrome locale (`"en"` | `"ja"`).
25
+ * 対応 UI クロームロケール (`"en"` | `"ja"`)。
26
+ */
27
+ export type VirtualScrollLocale = (typeof VIRTUAL_SCROLL_LOCALES)[number];
28
+ /**
29
+ * The complete set of built-in chrome strings, one value per rendered surface.
30
+ * 内蔵クローム文言の完全な集合 (描画面ごとに 1 値)。
31
+ */
32
+ export type VirtualScrollLabels = {
33
+ /**
34
+ * aria-label of the vertical ScrollBar start (up) arrow button.
35
+ * 縦 ScrollBar 始端 (上) 矢印ボタンの aria-label。
36
+ */
37
+ readonly scrollUp: string;
38
+ /**
39
+ * aria-label of the vertical ScrollBar end (down) arrow button.
40
+ * 縦 ScrollBar 終端 (下) 矢印ボタンの aria-label。
41
+ */
42
+ readonly scrollDown: string;
43
+ /**
44
+ * aria-label of the horizontal ScrollBar start (left) arrow button.
45
+ * 横 ScrollBar 始端 (左) 矢印ボタンの aria-label。
46
+ */
47
+ readonly scrollLeft: string;
48
+ /**
49
+ * aria-label of the horizontal ScrollBar end (right) arrow button.
50
+ * 横 ScrollBar 終端 (右) 矢印ボタンの aria-label。
51
+ */
52
+ readonly scrollRight: string;
53
+ /**
54
+ * Text of the VirtualScroll scroll-to-top pill, shown when
55
+ * `scrollBarOptions.enableScrollToTopBottomButtons` is on.
56
+ * `scrollBarOptions.enableScrollToTopBottomButtons` 有効時に表示される VirtualScroll 先頭移動ピルの文言。
57
+ */
58
+ readonly scrollToTop: string;
59
+ /**
60
+ * Text of the VirtualScroll scroll-to-bottom pill, shown when
61
+ * `scrollBarOptions.enableScrollToTopBottomButtons` is on.
62
+ * `scrollBarOptions.enableScrollToTopBottomButtons` 有効時に表示される VirtualScroll 末尾移動ピルの文言。
63
+ */
64
+ readonly scrollToBottom: string;
65
+ /**
66
+ * VirtualScroll empty-state text shown when `itemCount === 0`. VirtualGrid shows it too, for
67
+ * 0 rows, an all-frozen row set and degenerate bands (its embedded VirtualScroll gets 0 items).
68
+ * `itemCount === 0` 時の VirtualScroll 空状態文言。VirtualGrid も 0 行・全行固定・退化帯で表示
69
+ * (内蔵 VirtualScroll の項目数が 0 になるため)。
70
+ */
71
+ readonly noItems: string;
72
+ };
73
+ /**
74
+ * Partial per-key overrides laid over the catalog of the chosen locale. An `undefined` value keeps
75
+ * the catalog value; any present value must be a string with non-whitespace content.
76
+ * 選択ロケールのカタログへ重ねるキー単位の部分上書き。`undefined` 値はカタログ値を維持し、
77
+ * 値を与える場合は空白以外の文字を含む文字列であることが必須。
78
+ */
79
+ export type VirtualScrollLabelOverrides = {
80
+ readonly [K in keyof VirtualScrollLabels]?: VirtualScrollLabels[K];
81
+ };
82
+ /**
83
+ * Every key of {@link VirtualScrollLabels}, in catalog order. This is the closed key set that
84
+ * overrides are validated against.
85
+ * {@link VirtualScrollLabels} の全キー (カタログ順)。上書き検証に用いる閉じたキー集合。
86
+ */
87
+ export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "scrollToTop", "scrollToBottom", "noItems"];
88
+ /**
89
+ * Frozen built-in catalogs per locale. `en` is the package's historical English wording.
90
+ * ロケールごとの凍結済み内蔵カタログ。`en` はパッケージ従来の英語文言。
91
+ */
92
+ export declare const VIRTUAL_SCROLL_LABEL_CATALOGS: Readonly<Record<VirtualScrollLocale, VirtualScrollLabels>>;
93
+ /**
94
+ * Resolves the UI chrome locale. `undefined` (an absent prop) maps to the default `"en"`; a member
95
+ * of {@link VIRTUAL_SCROLL_LOCALES} is returned as-is. This is the single place the default lives.
96
+ * UI クロームロケールの解決。`undefined` (prop 未指定) は既定の `"en"`、
97
+ * {@link VIRTUAL_SCROLL_LOCALES} の要素はそのまま返却。既定値を持つ唯一の場所。
98
+ *
99
+ * @param locale - Requested locale, or `undefined` for the default / 要求ロケール (`undefined` で既定)
100
+ * @returns The resolved supported locale / 解決済みの対応ロケール
101
+ * @throws {RangeError} When `locale` is neither `undefined` nor a supported locale (`null`, `""`,
102
+ * `"EN"`, `"ja-JP"`, `"fr"`, numbers, ...) — no language negotiation /
103
+ * `undefined` でも対応ロケールでもない場合 (`null`、`""`、`"EN"`、`"ja-JP"`、`"fr"`、数値など)。言語ネゴシエーションなし
104
+ */
105
+ export declare const resolveVirtualScrollLocale: (locale: VirtualScrollLocale | undefined) => VirtualScrollLocale;
106
+ /**
107
+ * Resolves the effective labels: the catalog of the resolved locale overlaid by `overrides`.
108
+ * Returns the frozen catalog itself (same identity) when `overrides` is `undefined`, otherwise a
109
+ * new frozen object. Inputs are never mutated.
110
+ * 実効ラベルの解決。解決済みロケールのカタログへ `overrides` を重ねた結果。`overrides` が
111
+ * `undefined` なら凍結カタログそのもの (同一参照)、それ以外は新しい凍結オブジェクトを返却。入力は不変。
112
+ *
113
+ * @param locale - Requested locale, or `undefined` for the default / 要求ロケール (`undefined` で既定)
114
+ * @param overrides - Per-key overrides, or `undefined` for none / キー単位の上書き (`undefined` で上書きなし)
115
+ * @returns The resolved, frozen labels / 解決済みの凍結ラベル
116
+ * @throws {RangeError} When the locale is unsupported, `overrides` is `null` or not an object,
117
+ * `overrides` is not a plain object (its prototype is neither `Object.prototype` nor `null`, e.g.
118
+ * an array or a class instance), an own key is not a label key, or a present own value is not a
119
+ * string with non-whitespace content. Only own properties are read /
120
+ * ロケールが非対応、`overrides` が `null` または非オブジェクト、`overrides` が素のオブジェクトでない
121
+ * (プロトタイプが `Object.prototype` でも `null` でもない。配列やクラスインスタンスなど)、自身のキーが
122
+ * ラベルキー外、または与えられた自身の値が空白以外の文字を含む文字列でない場合。読むのは自身の
123
+ * プロパティのみ
124
+ */
125
+ export declare const resolveVirtualScrollLabels: (locale: VirtualScrollLocale | undefined, overrides: VirtualScrollLabelOverrides | undefined) => VirtualScrollLabels;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @module labels
3
+ * @description Built-in UI chrome label catalog of the package. Covers exactly the seven strings
4
+ * the components render on their own: the ScrollBar arrow aria-labels, the VirtualScroll
5
+ * scroll-to-edge pill texts and the empty-state text. Live-region wording stays consumer-owned
6
+ * (`liveRegion.format` / `liveRegion.buildMessage`) and is not part of this catalog. The default
7
+ * locale is `"en"`; `"ja"` is the second locale. No language negotiation happens here: hosts map
8
+ * `navigator.language` (or anything else) to a supported locale themselves.
9
+ *
10
+ * @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する 7 文言
11
+ * (ScrollBar 矢印の aria-label、VirtualScroll の端スクロールピル文言、空状態文言) だけを対象とし、
12
+ * ライブリージョンの文言は利用側の所有 (`liveRegion.format` / `liveRegion.buildMessage`) で
13
+ * 本カタログの対象外。既定ロケールは `"en"`、第 2 ロケールは `"ja"`。言語ネゴシエーションは行わず、
14
+ * `navigator.language` 等から対応ロケールへの対応付けはホスト側の責務。
15
+ */
16
+ /**
17
+ * Supported UI chrome locales, in declaration order. The first entry is NOT implicitly the
18
+ * default — the default lives only in {@link resolveVirtualScrollLocale}.
19
+ * 対応する UI クロームロケールの一覧 (宣言順)。先頭要素が暗黙の既定値になるわけではなく、
20
+ * 既定値は {@link resolveVirtualScrollLocale} にのみ存在。
21
+ */
22
+ export declare const VIRTUAL_SCROLL_LOCALES: readonly ["en", "ja"];
23
+ /**
24
+ * A supported UI chrome locale (`"en"` | `"ja"`).
25
+ * 対応 UI クロームロケール (`"en"` | `"ja"`)。
26
+ */
27
+ export type VirtualScrollLocale = (typeof VIRTUAL_SCROLL_LOCALES)[number];
28
+ /**
29
+ * The complete set of built-in chrome strings, one value per rendered surface.
30
+ * 内蔵クローム文言の完全な集合 (描画面ごとに 1 値)。
31
+ */
32
+ export type VirtualScrollLabels = {
33
+ /**
34
+ * aria-label of the vertical ScrollBar start (up) arrow button.
35
+ * 縦 ScrollBar 始端 (上) 矢印ボタンの aria-label。
36
+ */
37
+ readonly scrollUp: string;
38
+ /**
39
+ * aria-label of the vertical ScrollBar end (down) arrow button.
40
+ * 縦 ScrollBar 終端 (下) 矢印ボタンの aria-label。
41
+ */
42
+ readonly scrollDown: string;
43
+ /**
44
+ * aria-label of the horizontal ScrollBar start (left) arrow button.
45
+ * 横 ScrollBar 始端 (左) 矢印ボタンの aria-label。
46
+ */
47
+ readonly scrollLeft: string;
48
+ /**
49
+ * aria-label of the horizontal ScrollBar end (right) arrow button.
50
+ * 横 ScrollBar 終端 (右) 矢印ボタンの aria-label。
51
+ */
52
+ readonly scrollRight: string;
53
+ /**
54
+ * Text of the VirtualScroll scroll-to-top pill, shown when
55
+ * `scrollBarOptions.enableScrollToTopBottomButtons` is on.
56
+ * `scrollBarOptions.enableScrollToTopBottomButtons` 有効時に表示される VirtualScroll 先頭移動ピルの文言。
57
+ */
58
+ readonly scrollToTop: string;
59
+ /**
60
+ * Text of the VirtualScroll scroll-to-bottom pill, shown when
61
+ * `scrollBarOptions.enableScrollToTopBottomButtons` is on.
62
+ * `scrollBarOptions.enableScrollToTopBottomButtons` 有効時に表示される VirtualScroll 末尾移動ピルの文言。
63
+ */
64
+ readonly scrollToBottom: string;
65
+ /**
66
+ * VirtualScroll empty-state text shown when `itemCount === 0`. VirtualGrid shows it too, for
67
+ * 0 rows, an all-frozen row set and degenerate bands (its embedded VirtualScroll gets 0 items).
68
+ * `itemCount === 0` 時の VirtualScroll 空状態文言。VirtualGrid も 0 行・全行固定・退化帯で表示
69
+ * (内蔵 VirtualScroll の項目数が 0 になるため)。
70
+ */
71
+ readonly noItems: string;
72
+ };
73
+ /**
74
+ * Partial per-key overrides laid over the catalog of the chosen locale. An `undefined` value keeps
75
+ * the catalog value; any present value must be a string with non-whitespace content.
76
+ * 選択ロケールのカタログへ重ねるキー単位の部分上書き。`undefined` 値はカタログ値を維持し、
77
+ * 値を与える場合は空白以外の文字を含む文字列であることが必須。
78
+ */
79
+ export type VirtualScrollLabelOverrides = {
80
+ readonly [K in keyof VirtualScrollLabels]?: VirtualScrollLabels[K];
81
+ };
82
+ /**
83
+ * Every key of {@link VirtualScrollLabels}, in catalog order. This is the closed key set that
84
+ * overrides are validated against.
85
+ * {@link VirtualScrollLabels} の全キー (カタログ順)。上書き検証に用いる閉じたキー集合。
86
+ */
87
+ export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "scrollToTop", "scrollToBottom", "noItems"];
88
+ /**
89
+ * Frozen built-in catalogs per locale. `en` is the package's historical English wording.
90
+ * ロケールごとの凍結済み内蔵カタログ。`en` はパッケージ従来の英語文言。
91
+ */
92
+ export declare const VIRTUAL_SCROLL_LABEL_CATALOGS: Readonly<Record<VirtualScrollLocale, VirtualScrollLabels>>;
93
+ /**
94
+ * Resolves the UI chrome locale. `undefined` (an absent prop) maps to the default `"en"`; a member
95
+ * of {@link VIRTUAL_SCROLL_LOCALES} is returned as-is. This is the single place the default lives.
96
+ * UI クロームロケールの解決。`undefined` (prop 未指定) は既定の `"en"`、
97
+ * {@link VIRTUAL_SCROLL_LOCALES} の要素はそのまま返却。既定値を持つ唯一の場所。
98
+ *
99
+ * @param locale - Requested locale, or `undefined` for the default / 要求ロケール (`undefined` で既定)
100
+ * @returns The resolved supported locale / 解決済みの対応ロケール
101
+ * @throws {RangeError} When `locale` is neither `undefined` nor a supported locale (`null`, `""`,
102
+ * `"EN"`, `"ja-JP"`, `"fr"`, numbers, ...) — no language negotiation /
103
+ * `undefined` でも対応ロケールでもない場合 (`null`、`""`、`"EN"`、`"ja-JP"`、`"fr"`、数値など)。言語ネゴシエーションなし
104
+ */
105
+ export declare const resolveVirtualScrollLocale: (locale: VirtualScrollLocale | undefined) => VirtualScrollLocale;
106
+ /**
107
+ * Resolves the effective labels: the catalog of the resolved locale overlaid by `overrides`.
108
+ * Returns the frozen catalog itself (same identity) when `overrides` is `undefined`, otherwise a
109
+ * new frozen object. Inputs are never mutated.
110
+ * 実効ラベルの解決。解決済みロケールのカタログへ `overrides` を重ねた結果。`overrides` が
111
+ * `undefined` なら凍結カタログそのもの (同一参照)、それ以外は新しい凍結オブジェクトを返却。入力は不変。
112
+ *
113
+ * @param locale - Requested locale, or `undefined` for the default / 要求ロケール (`undefined` で既定)
114
+ * @param overrides - Per-key overrides, or `undefined` for none / キー単位の上書き (`undefined` で上書きなし)
115
+ * @returns The resolved, frozen labels / 解決済みの凍結ラベル
116
+ * @throws {RangeError} When the locale is unsupported, `overrides` is `null` or not an object,
117
+ * `overrides` is not a plain object (its prototype is neither `Object.prototype` nor `null`, e.g.
118
+ * an array or a class instance), an own key is not a label key, or a present own value is not a
119
+ * string with non-whitespace content. Only own properties are read /
120
+ * ロケールが非対応、`overrides` が `null` または非オブジェクト、`overrides` が素のオブジェクトでない
121
+ * (プロトタイプが `Object.prototype` でも `null` でもない。配列やクラスインスタンスなど)、自身のキーが
122
+ * ラベルキー外、または与えられた自身の値が空白以外の文字を含む文字列でない場合。読むのは自身の
123
+ * プロパティのみ
124
+ */
125
+ export declare const resolveVirtualScrollLabels: (locale: VirtualScrollLocale | undefined, overrides: VirtualScrollLabelOverrides | undefined) => VirtualScrollLabels;
126
+ //# sourceMappingURL=labels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,uBAAwB,CAAA;AAE3D;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,mBAAmB,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC;CAAE,CAAA;AAEhH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,8GAAgK,CAAA;AAMtM;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAmBnG,CAAA;AAiCF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,mBAAmB,GAAG,SAAS,KAAG,mBASpF,CAAA;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,mBAAmB,GAAG,SAAS,EAAE,WAAW,2BAA2B,GAAG,SAAS,KAAG,mBAiCxI,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/virtualscroll",
3
- "version": "3.6.1",
3
+ "version": "3.7.0",
4
4
  "description": "High-performance virtual scrolling component for React with variable item heights",
5
5
  "sideEffects": [
6
6
  "**/*.css"
package/src/ScrollBar.tsx CHANGED
@@ -6,6 +6,7 @@
6
6
  import type { CSSProperties, ReactNode } from "react"
7
7
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"
8
8
  import { twMerge } from "tailwind-merge"
9
+ import { resolveVirtualScrollLabels, type VirtualScrollLabelOverrides, type VirtualScrollLocale } from "./labels.ts"
9
10
  import { Logger } from "./logger.ts"
10
11
  import { TapScrollCircle, type TapScrollCircleDragState, type TapScrollCircleHandle, type TapScrollCircleRenderProps } from "./TapScrollCircle.tsx"
11
12
  import { getAxisScale, minmax } from "./utils.ts"
@@ -21,7 +22,6 @@ type OrientationConfig = {
21
22
  positionKey: "left" | "top"
22
23
  selectDelta: (deltaX: number, deltaY: number) => number
23
24
  getPointerCoordinate: (point: { clientX: number; clientY: number }) => number
24
- arrowLabels: [string, string]
25
25
  arrowIcons: [string, string]
26
26
  directionClass: string
27
27
  orientation: "vertical" | "horizontal"
@@ -193,6 +193,21 @@ export type ScrollBarProps = {
193
193
  visibleStartIndex?: number
194
194
  /** The index of the last visible item. / 最後の可視アイテムのインデックス。 */
195
195
  visibleEndIndex?: number
196
+ /**
197
+ * UI chrome locale of the built-in arrow aria-labels (default `"en"`). An unsupported value
198
+ * throws a RangeError at render; no language negotiation happens.
199
+ * 内蔵矢印 aria-label の UI クロームロケール (既定 `"en"`)。非対応値は描画時に RangeError、
200
+ * 言語ネゴシエーションなし。
201
+ */
202
+ locale?: VirtualScrollLocale
203
+ /**
204
+ * Per-key overrides laid over the catalog of `locale`. This bar reads `scrollUp` / `scrollDown`
205
+ * (vertical) or `scrollLeft` / `scrollRight` (horizontal); unknown keys and blank values throw a
206
+ * RangeError at render.
207
+ * `locale` のカタログへ重ねるキー単位の上書き。本バーが読むのは縦なら `scrollUp` / `scrollDown`、
208
+ * 横なら `scrollLeft` / `scrollRight`。未知キーと空白値は描画時に RangeError。
209
+ */
210
+ labels?: VirtualScrollLabelOverrides
196
211
  }
197
212
 
198
213
  /** The minimum size of the scrollbar thumb. / スクロールバーのつまみの最小サイズ。 */
@@ -255,7 +270,6 @@ const createOrientationConfig = (horizontal: boolean): OrientationConfig => {
255
270
  positionKey: "left",
256
271
  selectDelta: (deltaX: number, _deltaY: number) => deltaX,
257
272
  getPointerCoordinate: ({ clientX }) => clientX,
258
- arrowLabels: ["Scroll left", "Scroll right"],
259
273
  arrowIcons: ["◀", "▶"],
260
274
  directionClass: "aqvs-scrollbar-horizontal",
261
275
  orientation: "horizontal",
@@ -268,7 +282,6 @@ const createOrientationConfig = (horizontal: boolean): OrientationConfig => {
268
282
  positionKey: "top",
269
283
  selectDelta: (_deltaX: number, deltaY: number) => deltaY,
270
284
  getPointerCoordinate: ({ clientY }) => clientY,
271
- arrowLabels: ["Scroll up", "Scroll down"],
272
285
  arrowIcons: ["▲", "▼"],
273
286
  directionClass: "aqvs-scrollbar-vertical",
274
287
  orientation: "vertical",
@@ -608,6 +621,8 @@ export const ScrollBar = ({
608
621
  renderThumbOverlay,
609
622
  visibleStartIndex,
610
623
  visibleEndIndex,
624
+ locale,
625
+ labels,
611
626
  }: ScrollBarProps) => {
612
627
  const [isDragging, setIsDragging] = useState(false)
613
628
  const [isThumbHovered, setIsThumbHovered] = useState(false)
@@ -635,6 +650,8 @@ export const ScrollBar = ({
635
650
  const autoScrollDirectionRef = useRef<0 | 1 | -1>(0)
636
651
  const resolvedTapScrollOptions = useMemo<ResolvedTapScrollCircleOptions>(() => resolveTapScrollCircleOptions(tapScrollCircleOptions, itemCount), [itemCount, tapScrollCircleOptions])
637
652
  const orientationConfig = useMemo(() => createOrientationConfig(horizontal), [horizontal])
653
+ const resolvedLabels = useMemo(() => resolveVirtualScrollLabels(locale, labels), [locale, labels])
654
+ const arrowLabels = horizontal ? ([resolvedLabels.scrollLeft, resolvedLabels.scrollRight] as const) : ([resolvedLabels.scrollUp, resolvedLabels.scrollDown] as const)
638
655
  const {
639
656
  enabled: tapCircleEnabled,
640
657
  size: tapCircleSize,
@@ -661,7 +678,7 @@ export const ScrollBar = ({
661
678
  onScroll,
662
679
  scrollPosition,
663
680
  })
664
- const { mainSizeKey, crossSizeKey, positionKey, selectDelta, getPointerCoordinate, arrowLabels, arrowIcons, directionClass, orientation } = orientationConfig
681
+ const { mainSizeKey, crossSizeKey, positionKey, selectDelta, getPointerCoordinate, arrowIcons, directionClass, orientation } = orientationConfig
665
682
  const effectiveTapMaxDistance = Math.max(tapCircleMaxDistance, 1)
666
683
  // 表示領域に対するコンテンツの比率
667
684
  const scrollRatio = viewportSize / contentSize
@@ -1,5 +1,6 @@
1
1
  import { forwardRef, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react"
2
2
  import { twMerge } from "tailwind-merge"
3
+ import type { VirtualScrollLabelOverrides, VirtualScrollLocale } from "./labels.ts"
3
4
  import { Logger } from "./logger.ts"
4
5
  import { ScrollBar, type ScrollBarTapCircleOptions, type ScrollBarThumbOverlayRenderProps, TAP_SCROLL_CANCEL_EVENT } from "./ScrollBar.tsx"
5
6
  import { getAxisScale, minmax } from "./utils.ts"
@@ -167,6 +168,20 @@ export type ScrollPaneProps = {
167
168
  * `className` / `style` / `ref` を表現できない型にしてあり、この口からレイアウトを壊せない。
168
169
  */
169
170
  contentProps?: React.AriaAttributes & { id?: string; role?: React.AriaRole }
171
+ /**
172
+ * UI chrome locale forwarded to the pane's ScrollBar (arrow aria-labels; default `"en"`).
173
+ * An unsupported value throws a RangeError at render.
174
+ * ペインの ScrollBar へ転送する UI クロームロケール (矢印の aria-label、既定 `"en"`)。
175
+ * 非対応値は描画時に RangeError。
176
+ */
177
+ locale?: VirtualScrollLocale
178
+ /**
179
+ * Per-key label overrides forwarded to the pane's ScrollBar, laid over the catalog of `locale`.
180
+ * Unknown keys and blank values throw a RangeError at render.
181
+ * ペインの ScrollBar へ転送するキー単位のラベル上書き (`locale` のカタログへ重ねる)。
182
+ * 未知キーと空白値は描画時に RangeError。
183
+ */
184
+ labels?: VirtualScrollLabelOverrides
170
185
  }
171
186
 
172
187
  export type ScrollPaneInertiaOptions = {
@@ -332,6 +347,8 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
332
347
  renderOverlay,
333
348
  initialScrollPosition = 0,
334
349
  contentProps,
350
+ locale,
351
+ labels,
335
352
  },
336
353
  ref,
337
354
  ) => {
@@ -1638,6 +1655,8 @@ export const ScrollPane = forwardRef<ScrollPaneHandle, ScrollPaneProps>(
1638
1655
  renderThumbOverlay={renderThumbOverlay}
1639
1656
  visibleStartIndex={visibleStartIndex}
1640
1657
  visibleEndIndex={visibleEndIndex}
1658
+ locale={locale}
1659
+ labels={labels}
1641
1660
  />
1642
1661
  {renderOverlay?.()}
1643
1662
  </div>
@@ -24,6 +24,7 @@
24
24
  import { type CSSProperties, forwardRef, type HTMLAttributes, type ReactNode, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react"
25
25
  import { twMerge } from "tailwind-merge"
26
26
  import type { TapScrollAxisSpeedParams } from "./computeTapScrollVelocity.ts"
27
+ import type { VirtualScrollLabelOverrides, VirtualScrollLocale } from "./labels.ts"
27
28
  import { Logger } from "./logger.ts"
28
29
  import { resolveTapScrollCircleOptions, ScrollBar, type ScrollBarTapCircleOptions } from "./ScrollBar.tsx"
29
30
  import type { ScrollPaneProps } from "./ScrollPane.tsx"
@@ -216,7 +217,7 @@ export type VirtualGridRange = {
216
217
  totalHeight: number
217
218
  }
218
219
 
219
- /** Live-region options: the consumer owns wording/locale (no built-in strings — row-parity). / liveRegion オプション: 文言とロケールは消費側所有 (内蔵文字列なし — 行側と同一方針)。 */
220
+ /** Live-region options: the consumer owns announcement wording/locale; the built-in catalog (`locale` / `labels`) covers only the seven chrome strings (arrows, pills, empty state) — row-parity. / liveRegion オプション: 読み上げの文言とロケールは消費側所有。内蔵カタログ (`locale` / `labels`) はクローム 7 文言 (矢印・ピル・空状態) のみ対象 — 行側と同一方針。 */
220
221
  export type VirtualGridLiveRegionOptions = {
221
222
  /** Builds the announcement (same string = no re-announce, "" clears). / 読み上げ文言の組み立て (同一文字列 = 再読み上げなし、"" でクリア)。 */
222
223
  buildMessage: (range: VirtualGridRange) => string
@@ -392,6 +393,21 @@ export type VirtualGridProps<T> = {
392
393
  behaviorOptions?: VirtualGridBehaviorOptions
393
394
  scrollBarOptions?: VirtualScrollScrollBarOptions
394
395
  liveRegion?: VirtualGridLiveRegionOptions
396
+ /**
397
+ * UI chrome locale (default `"en"`), forwarded to the embedded vertical VirtualScroll (its
398
+ * arrows and the 0-row / all-frozen / degenerate-band empty state) and the horizontal bar
399
+ * arrows. An unsupported value throws a RangeError at render.
400
+ * UI クロームロケール (既定 `"en"`)。内蔵の縦 VirtualScroll (矢印と 0 行・全行固定・退化帯の
401
+ * 空状態) と横バーの矢印へ転送。非対応値は描画時に RangeError。
402
+ */
403
+ locale?: VirtualScrollLocale
404
+ /**
405
+ * Per-key label overrides laid over the catalog of `locale`, forwarded to the same two
406
+ * surfaces as `locale`. Unknown keys and blank values throw a RangeError at render.
407
+ * `locale` のカタログへ重ねるキー単位のラベル上書き (`locale` と同じ 2 面へ転送)。
408
+ * 未知キーと空白値は描画時に RangeError。
409
+ */
410
+ labels?: VirtualScrollLabelOverrides
395
411
  className?: string
396
412
  testId?: string
397
413
  }
@@ -749,6 +765,8 @@ const VirtualGridInner = <T,>(
749
765
  behaviorOptions,
750
766
  scrollBarOptions,
751
767
  liveRegion,
768
+ locale,
769
+ labels,
752
770
  className,
753
771
  testId,
754
772
  }: VirtualGridProps<T>,
@@ -1910,6 +1928,8 @@ const VirtualGridInner = <T,>(
1910
1928
  onRangeChange={handleRangeChangeWithLive}
1911
1929
  onWheelHorizontal={consumeHorizontalDelta}
1912
1930
  onPanHorizontal={consumeHorizontalDelta}
1931
+ locale={locale}
1932
+ labels={labels}
1913
1933
  testId={testId ? `${testId}-rows` : undefined}>
1914
1934
  {renderRow}
1915
1935
  </VirtualScroll>
@@ -1951,6 +1971,8 @@ const VirtualGridInner = <T,>(
1951
1971
  return applyHxRef.current(typeof request === "function" ? request(previous ?? hxRef.current) : request)
1952
1972
  }}
1953
1973
  scrollBarWidth={scrollBarWidth}
1974
+ locale={locale}
1975
+ labels={labels}
1954
1976
  />
1955
1977
  </div>
1956
1978
  {tapCircleEnabled && gridScrollable && (
@@ -1,4 +1,5 @@
1
1
  import React, { forwardRef, type ReactNode, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react"
2
+ import { resolveVirtualScrollLabels, type VirtualScrollLabelOverrides, type VirtualScrollLocale } from "./labels.ts"
2
3
  import { Logger } from "./logger.ts"
3
4
  import { ScrollPane, type ScrollPaneContentInsets, type ScrollPaneHandle, type ScrollPaneProps } from "./ScrollPane.tsx"
4
5
  import { useFenwickMapTree } from "./useFenwickMapTree.ts"
@@ -224,12 +225,13 @@ export type VirtualScrollLiveRegionOptions = {
224
225
  /**
225
226
  * Formats the announcement text. Called after the visible range settles; returning the same
226
227
  * string as last time leaves the DOM untouched (no re-announcement), returning `""` clears
227
- * the region. The package ships NO built-in strings — wording and language are the
228
- * consumer's (a generic package must not hardcode a locale).
228
+ * the region. The live-region wording and its language are consumer-owned: the package's
229
+ * built-in catalog (`locale` / `labels`) covers only the seven chrome strings (scrollbar arrow
230
+ * aria-labels, the scroll-to-edge pills and the empty state), never announcements.
229
231
  * 読み上げ文言を組み立てる。可視範囲が静定した後に呼ばれ、前回と同じ文字列なら DOM を
230
- * 触らない (再読み上げしない)。`""` を返すとリージョンを空にする。パッケージは文言を
231
- * 一切内蔵しない — 言語と文面は消費側の所有物 (汎用パッケージはロケールをハードコード
232
- * できない)。
232
+ * 触らない (再読み上げしない)。`""` を返すとリージョンを空にする。読み上げの文面と言語は
233
+ * 消費側の所有物 — パッケージの内蔵カタログ (`locale` / `labels`) が扱うのはクローム 7 文言
234
+ * (スクロールバー矢印の aria-label、端スクロールピル、空状態) だけで、読み上げは対象外。
233
235
  *
234
236
  * @param range - The settled visible range / 静定した可視範囲
235
237
  * @returns Announcement text / 読み上げ文言
@@ -310,6 +312,23 @@ export type VirtualScrollProps<T> = {
310
312
  * その場合は `onRangeChange` から自前のリージョンを更新する従来手段を使う。
311
313
  */
312
314
  liveRegion?: VirtualScrollLiveRegionOptions
315
+ /**
316
+ * UI chrome locale of the built-in strings (default `"en"`): the scrollbar arrow aria-labels,
317
+ * the scroll-to-edge pills and the empty-state text. Live-region wording is not affected (see
318
+ * {@link VirtualScrollLiveRegionOptions.format}). An unsupported value throws a RangeError at
319
+ * render; no language negotiation happens.
320
+ * 内蔵文言 (スクロールバー矢印の aria-label、端スクロールピル、空状態文言) の UI クロームロケール
321
+ * (既定 `"en"`)。ライブリージョンの文言には影響しない ({@link VirtualScrollLiveRegionOptions.format}
322
+ * 参照)。非対応値は描画時に RangeError、言語ネゴシエーションなし。
323
+ */
324
+ locale?: VirtualScrollLocale
325
+ /**
326
+ * Per-key overrides laid over the catalog of `locale`; forwarded to the pane's scrollbar as-is.
327
+ * Unknown keys and blank values throw a RangeError at render.
328
+ * `locale` のカタログへ重ねるキー単位の上書き。ペインのスクロールバーへもそのまま転送。
329
+ * 未知キーと空白値は描画時に RangeError。
330
+ */
331
+ labels?: VirtualScrollLabelOverrides
313
332
  background?: ReactNode
314
333
  children: (item: T, index: number) => ReactNode
315
334
  initialScrollIndex?: number
@@ -1023,10 +1042,13 @@ const VirtualScrollInner = <T,>(
1023
1042
  horizontalKeyStep = DEFAULT_HORIZONTAL_KEY_STEP,
1024
1043
  contentProps,
1025
1044
  liveRegion,
1045
+ locale,
1046
+ labels,
1026
1047
  }: VirtualScrollProps<T>,
1027
1048
  ref: React.Ref<VirtualScrollHandle>,
1028
1049
  ) => {
1029
1050
  const { width: scrollBarWidth, enableThumbDrag, enableTrackClick, enableArrowButtons, enableScrollToTopBottomButtons, renderThumbOverlay, tapScrollCircleOptions } = scrollBarOptions ?? {}
1051
+ const resolvedLabels = useMemo(() => resolveVirtualScrollLabels(locale, labels), [locale, labels])
1030
1052
 
1031
1053
  const { enablePointerDrag, pointerDragInputs, enableKeyboardNavigation = true, enableEscapeRowReturn = false, wheelSpeedMultiplier, inertiaOptions, overscrollBehavior, clipItemHeight = false, resetOnGetItemHeightChange = false } = behaviorOptions ?? {}
1032
1054
 
@@ -2168,9 +2190,11 @@ const VirtualScrollInner = <T,>(
2168
2190
  }, [contentSize, renderingEndIndex, renderingStartIndex, resolvedInsets.top, scheduleRangeEffect, scrollPosition, visibleEndIndex, visibleStartIndex])
2169
2191
 
2170
2192
  /**
2171
- * Renders the auto-hiding Top/Bottom pill overlay, neutralized while hidden.
2193
+ * Renders the auto-hiding top/bottom pill overlay (texts from the resolved `scrollToTop` /
2194
+ * `scrollToBottom` labels), neutralized while hidden.
2172
2195
  *
2173
- * 自動非表示の Top/Bottom ピルのオーバーレイを描画し、非表示中は無効化する処理。
2196
+ * 自動非表示の先頭/末尾ピルのオーバーレイ (文言は解決済みラベルの `scrollToTop` /
2197
+ * `scrollToBottom`) を描画し、非表示中は無効化する処理。
2174
2198
  *
2175
2199
  * ❗ 非表示は `opacity: 0` で表現するため、要素は DOM に残り続ける (フェードのために
2176
2200
  * アンマウントしない)。`opacity` はフォーカス可能性に影響せず、CSS の `pointer-events: none`
@@ -2213,7 +2237,7 @@ const VirtualScrollInner = <T,>(
2213
2237
  scrollToIndex(0)
2214
2238
  setShowScrollButtons(false)
2215
2239
  }}>
2216
- Top
2240
+ {resolvedLabels.scrollToTop}
2217
2241
  </button>
2218
2242
  </div>
2219
2243
  ) : (
@@ -2229,13 +2253,13 @@ const VirtualScrollInner = <T,>(
2229
2253
  scrollToIndex(itemCount - 1)
2230
2254
  setShowScrollButtons(false)
2231
2255
  }}>
2232
- Bottom
2256
+ {resolvedLabels.scrollToBottom}
2233
2257
  </button>
2234
2258
  </div>
2235
2259
  )}
2236
2260
  </div>
2237
2261
  )
2238
- }, [enableScrollToTopBottomButtons, showScrollButtons, scrollDirection, scrollToIndex, itemCount])
2262
+ }, [enableScrollToTopBottomButtons, showScrollButtons, scrollDirection, scrollToIndex, itemCount, resolvedLabels])
2239
2263
 
2240
2264
  // 量子化アンカー (fix: LayoutUnit/f32 精度対策)。行 top はコンテンツ絶対座標そのままではなく
2241
2265
  // 「絶対座標 - アンカー」で描画し、ラッパー側 translateY にアンカーを足し戻す。
@@ -2258,7 +2282,7 @@ const VirtualScrollInner = <T,>(
2258
2282
  return {
2259
2283
  visibleItems: (
2260
2284
  <div className="aqvs-no-items-container">
2261
- <div className="aqvs-no-items-text">No items</div>
2285
+ <div className="aqvs-no-items-text">{resolvedLabels.noItems}</div>
2262
2286
  </div>
2263
2287
  ),
2264
2288
  renderAnchor: 0,
@@ -2397,6 +2421,7 @@ const VirtualScrollInner = <T,>(
2397
2421
  registerItemRef,
2398
2422
  renderingEndIndex,
2399
2423
  renderingStartIndex,
2424
+ resolvedLabels,
2400
2425
  updateScrollPositionImmediate,
2401
2426
  visibleStartIndex,
2402
2427
  ])
@@ -2588,7 +2613,9 @@ const VirtualScrollInner = <T,>(
2588
2613
  visibleStartIndex={visibleStartIndex}
2589
2614
  visibleEndIndex={visibleEndIndex}
2590
2615
  renderOverlay={renderOverlay}
2591
- initialScrollPosition={initialValues.position}>
2616
+ initialScrollPosition={initialValues.position}
2617
+ locale={locale}
2618
+ labels={labels}>
2592
2619
  {renderVisibleItems}
2593
2620
  </ScrollPane>
2594
2621
  )
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  export { computeTapScrollVelocity, type TapScrollAxisSpeedParams, type TapScrollVelocityInput } from "./computeTapScrollVelocity.ts"
9
+ export { resolveVirtualScrollLabels, resolveVirtualScrollLocale, VIRTUAL_SCROLL_LABEL_CATALOGS, VIRTUAL_SCROLL_LABEL_KEYS, VIRTUAL_SCROLL_LOCALES, type VirtualScrollLabelOverrides, type VirtualScrollLabels, type VirtualScrollLocale } from "./labels.ts"
9
10
  export { createResidualQuantizer, type ResidualQuantizer, type ResidualQuantizerOptions } from "./residualQuantizer.ts"
10
11
  export { computeAutoTapScrollMaxSpeedMultiplier, computeTapScrollSpeed, ScrollBar, type ScrollBarProps, type ScrollBarTapCircleOptions, type ScrollBarThumbOverlayRenderProps, TAP_SCROLL_SPEED_DEFAULTS, type TapScrollSpeedInput } from "./ScrollBar.tsx"
11
12
  export { ScrollPane, type ScrollPaneContentInsets, type ScrollPaneHandle, type ScrollPaneInertiaOptions, type ScrollPaneProps } from "./ScrollPane.tsx"