@aiquants/virtualscroll 3.9.2 → 3.10.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 +90 -0
- package/README.md +95 -29
- package/dist/ScrollBar.d.cts +41 -35
- package/dist/ScrollBar.d.ts +41 -35
- package/dist/ScrollBar.d.ts.map +1 -1
- package/dist/ScrollPane.d.cts +12 -14
- package/dist/ScrollPane.d.ts +12 -14
- package/dist/ScrollPane.d.ts.map +1 -1
- package/dist/VirtualGrid.d.cts +6 -6
- package/dist/VirtualGrid.d.ts +6 -6
- package/dist/VirtualGrid.d.ts.map +1 -1
- package/dist/VirtualScroll.d.cts +72 -23
- package/dist/VirtualScroll.d.ts +72 -23
- package/dist/VirtualScroll.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1970 -1950
- package/dist/labels.d.cts +38 -7
- package/dist/labels.d.ts +38 -7
- package/dist/labels.d.ts.map +1 -1
- package/dist/styles/virtualscroll.css +1 -1
- package/dist/styles/virtualscroll.standalone.css +1 -1
- package/dist/utils.d.cts +14 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/ScrollBar.tsx +91 -49
- package/src/ScrollPane.tsx +12 -14
- package/src/VirtualGrid.tsx +6 -6
- package/src/VirtualScroll.tsx +151 -92
- package/src/labels.ts +58 -7
- package/src/styles/virtualscroll.css +51 -3
- package/src/utils.ts +15 -0
package/dist/labels.d.cts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module labels
|
|
3
|
-
* @description Built-in UI chrome label catalog of the package. Covers exactly the
|
|
4
|
-
* the components render on their own: the ScrollBar
|
|
3
|
+
* @description Built-in UI chrome label catalog of the package. Covers exactly the eleven strings
|
|
4
|
+
* the components render on their own: the ScrollBar accessible names (per orientation, the two
|
|
5
|
+
* arrows, the `role="scrollbar"` bar and its `role="slider"` thumb), the VirtualScroll
|
|
5
6
|
* scroll-to-edge pill texts and the empty-state text. Live-region wording stays consumer-owned
|
|
6
7
|
* (`liveRegion.format` / `liveRegion.buildMessage`) and is not part of this catalog. The default
|
|
7
8
|
* locale is `"en"`; `"ja"` is the second locale. No language negotiation happens here: hosts map
|
|
8
9
|
* `navigator.language` (or anything else) to a supported locale themselves.
|
|
9
10
|
*
|
|
10
|
-
* @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する
|
|
11
|
-
* (ScrollBar
|
|
11
|
+
* @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する 11 文言
|
|
12
|
+
* (向きごとの ScrollBar のアクセシブルネーム — 矢印 2 個・`role="scrollbar"` のバー・その `role="slider"` の
|
|
13
|
+
* つまみ —、VirtualScroll の端スクロールピル文言、空状態文言) だけを対象とし、
|
|
12
14
|
* ライブリージョンの文言は利用側の所有 (`liveRegion.format` / `liveRegion.buildMessage`) で
|
|
13
15
|
* 本カタログの対象外。既定ロケールは `"en"`、第 2 ロケールは `"ja"`。言語ネゴシエーションは行わず、
|
|
14
16
|
* `navigator.language` 等から対応ロケールへの対応付けはホスト側の責務。
|
|
@@ -50,6 +52,30 @@ export type VirtualScrollLabels = {
|
|
|
50
52
|
* 横 ScrollBar 終端 (右) 矢印ボタンの aria-label。
|
|
51
53
|
*/
|
|
52
54
|
readonly scrollRight: string;
|
|
55
|
+
/**
|
|
56
|
+
* aria-label of the vertical ScrollBar root (`role="scrollbar"`). Assistive technology appends
|
|
57
|
+
* the role ("scroll bar") itself, so the name carries only what tells the two bars apart.
|
|
58
|
+
* 縦 ScrollBar のルート (`role="scrollbar"`) の aria-label。ロール名 (スクロールバー) は支援技術が
|
|
59
|
+
* 付け足すため、名前は 2 本のバーを区別する情報のみ。
|
|
60
|
+
*/
|
|
61
|
+
readonly verticalScrollBar: string;
|
|
62
|
+
/**
|
|
63
|
+
* aria-label of the horizontal ScrollBar root (`role="scrollbar"`).
|
|
64
|
+
* 横 ScrollBar のルート (`role="scrollbar"`) の aria-label。
|
|
65
|
+
*/
|
|
66
|
+
readonly horizontalScrollBar: string;
|
|
67
|
+
/**
|
|
68
|
+
* aria-label of the vertical ScrollBar thumb (`role="slider"`), whose value is the scroll
|
|
69
|
+
* position.
|
|
70
|
+
* 縦 ScrollBar のつまみ (`role="slider"`) の aria-label。値はスクロール位置。
|
|
71
|
+
*/
|
|
72
|
+
readonly verticalScrollThumb: string;
|
|
73
|
+
/**
|
|
74
|
+
* aria-label of the horizontal ScrollBar thumb (`role="slider"`), whose value is the scroll
|
|
75
|
+
* position.
|
|
76
|
+
* 横 ScrollBar のつまみ (`role="slider"`) の aria-label。値はスクロール位置。
|
|
77
|
+
*/
|
|
78
|
+
readonly horizontalScrollThumb: string;
|
|
53
79
|
/**
|
|
54
80
|
* Text of the VirtualScroll scroll-to-top pill, shown when
|
|
55
81
|
* `scrollBarOptions.enableScrollToTopBottomButtons` is on.
|
|
@@ -84,10 +110,15 @@ export type VirtualScrollLabelOverrides = {
|
|
|
84
110
|
* overrides are validated against.
|
|
85
111
|
* {@link VirtualScrollLabels} の全キー (カタログ順)。上書き検証に用いる閉じたキー集合。
|
|
86
112
|
*/
|
|
87
|
-
export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "scrollToTop", "scrollToBottom", "noItems"];
|
|
113
|
+
export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "verticalScrollBar", "horizontalScrollBar", "verticalScrollThumb", "horizontalScrollThumb", "scrollToTop", "scrollToBottom", "noItems"];
|
|
88
114
|
/**
|
|
89
|
-
* Frozen built-in catalogs per locale. `en`
|
|
90
|
-
*
|
|
115
|
+
* Frozen built-in catalogs per locale. The arrow, pill and empty-state values of `en` are the
|
|
116
|
+
* package's historical English wording. The bar names state only the orientation, because
|
|
117
|
+
* assistive technology already reads the role as "scroll bar"; the thumb names state what the
|
|
118
|
+
* value measures.
|
|
119
|
+
* ロケールごとの凍結済み内蔵カタログ。`en` の矢印・ピル・空状態の値はパッケージ従来の英語文言。
|
|
120
|
+
* バーの名前は向きのみ (支援技術がロールを既に「スクロールバー」と読むため)、つまみの名前は値が
|
|
121
|
+
* 表すもの。
|
|
91
122
|
*/
|
|
92
123
|
export declare const VIRTUAL_SCROLL_LABEL_CATALOGS: Readonly<Record<VirtualScrollLocale, VirtualScrollLabels>>;
|
|
93
124
|
/**
|
package/dist/labels.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module labels
|
|
3
|
-
* @description Built-in UI chrome label catalog of the package. Covers exactly the
|
|
4
|
-
* the components render on their own: the ScrollBar
|
|
3
|
+
* @description Built-in UI chrome label catalog of the package. Covers exactly the eleven strings
|
|
4
|
+
* the components render on their own: the ScrollBar accessible names (per orientation, the two
|
|
5
|
+
* arrows, the `role="scrollbar"` bar and its `role="slider"` thumb), the VirtualScroll
|
|
5
6
|
* scroll-to-edge pill texts and the empty-state text. Live-region wording stays consumer-owned
|
|
6
7
|
* (`liveRegion.format` / `liveRegion.buildMessage`) and is not part of this catalog. The default
|
|
7
8
|
* locale is `"en"`; `"ja"` is the second locale. No language negotiation happens here: hosts map
|
|
8
9
|
* `navigator.language` (or anything else) to a supported locale themselves.
|
|
9
10
|
*
|
|
10
|
-
* @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する
|
|
11
|
-
* (ScrollBar
|
|
11
|
+
* @description パッケージ内蔵の UI クローム文言カタログ。コンポーネント自身が描画する 11 文言
|
|
12
|
+
* (向きごとの ScrollBar のアクセシブルネーム — 矢印 2 個・`role="scrollbar"` のバー・その `role="slider"` の
|
|
13
|
+
* つまみ —、VirtualScroll の端スクロールピル文言、空状態文言) だけを対象とし、
|
|
12
14
|
* ライブリージョンの文言は利用側の所有 (`liveRegion.format` / `liveRegion.buildMessage`) で
|
|
13
15
|
* 本カタログの対象外。既定ロケールは `"en"`、第 2 ロケールは `"ja"`。言語ネゴシエーションは行わず、
|
|
14
16
|
* `navigator.language` 等から対応ロケールへの対応付けはホスト側の責務。
|
|
@@ -50,6 +52,30 @@ export type VirtualScrollLabels = {
|
|
|
50
52
|
* 横 ScrollBar 終端 (右) 矢印ボタンの aria-label。
|
|
51
53
|
*/
|
|
52
54
|
readonly scrollRight: string;
|
|
55
|
+
/**
|
|
56
|
+
* aria-label of the vertical ScrollBar root (`role="scrollbar"`). Assistive technology appends
|
|
57
|
+
* the role ("scroll bar") itself, so the name carries only what tells the two bars apart.
|
|
58
|
+
* 縦 ScrollBar のルート (`role="scrollbar"`) の aria-label。ロール名 (スクロールバー) は支援技術が
|
|
59
|
+
* 付け足すため、名前は 2 本のバーを区別する情報のみ。
|
|
60
|
+
*/
|
|
61
|
+
readonly verticalScrollBar: string;
|
|
62
|
+
/**
|
|
63
|
+
* aria-label of the horizontal ScrollBar root (`role="scrollbar"`).
|
|
64
|
+
* 横 ScrollBar のルート (`role="scrollbar"`) の aria-label。
|
|
65
|
+
*/
|
|
66
|
+
readonly horizontalScrollBar: string;
|
|
67
|
+
/**
|
|
68
|
+
* aria-label of the vertical ScrollBar thumb (`role="slider"`), whose value is the scroll
|
|
69
|
+
* position.
|
|
70
|
+
* 縦 ScrollBar のつまみ (`role="slider"`) の aria-label。値はスクロール位置。
|
|
71
|
+
*/
|
|
72
|
+
readonly verticalScrollThumb: string;
|
|
73
|
+
/**
|
|
74
|
+
* aria-label of the horizontal ScrollBar thumb (`role="slider"`), whose value is the scroll
|
|
75
|
+
* position.
|
|
76
|
+
* 横 ScrollBar のつまみ (`role="slider"`) の aria-label。値はスクロール位置。
|
|
77
|
+
*/
|
|
78
|
+
readonly horizontalScrollThumb: string;
|
|
53
79
|
/**
|
|
54
80
|
* Text of the VirtualScroll scroll-to-top pill, shown when
|
|
55
81
|
* `scrollBarOptions.enableScrollToTopBottomButtons` is on.
|
|
@@ -84,10 +110,15 @@ export type VirtualScrollLabelOverrides = {
|
|
|
84
110
|
* overrides are validated against.
|
|
85
111
|
* {@link VirtualScrollLabels} の全キー (カタログ順)。上書き検証に用いる閉じたキー集合。
|
|
86
112
|
*/
|
|
87
|
-
export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "scrollToTop", "scrollToBottom", "noItems"];
|
|
113
|
+
export declare const VIRTUAL_SCROLL_LABEL_KEYS: readonly ["scrollUp", "scrollDown", "scrollLeft", "scrollRight", "verticalScrollBar", "horizontalScrollBar", "verticalScrollThumb", "horizontalScrollThumb", "scrollToTop", "scrollToBottom", "noItems"];
|
|
88
114
|
/**
|
|
89
|
-
* Frozen built-in catalogs per locale. `en`
|
|
90
|
-
*
|
|
115
|
+
* Frozen built-in catalogs per locale. The arrow, pill and empty-state values of `en` are the
|
|
116
|
+
* package's historical English wording. The bar names state only the orientation, because
|
|
117
|
+
* assistive technology already reads the role as "scroll bar"; the thumb names state what the
|
|
118
|
+
* value measures.
|
|
119
|
+
* ロケールごとの凍結済み内蔵カタログ。`en` の矢印・ピル・空状態の値はパッケージ従来の英語文言。
|
|
120
|
+
* バーの名前は向きのみ (支援技術がロールを既に「スクロールバー」と読むため)、つまみの名前は値が
|
|
121
|
+
* 表すもの。
|
|
91
122
|
*/
|
|
92
123
|
export declare const VIRTUAL_SCROLL_LABEL_CATALOGS: Readonly<Record<VirtualScrollLocale, VirtualScrollLabels>>;
|
|
93
124
|
/**
|
package/dist/labels.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;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;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAA;IACtC;;;;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,0MAYqB,CAAA;AAM3D;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CA2BnG,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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer components{.aqvs-scroll-pane{display:flex;position:relative}.aqvs-scroll-pane[data-self-measured=true]{height:100%}.aqvs-scroll-pane-content{box-sizing:border-box;flex:1;height:100%;position:relative;overflow:hidden}.aqvs-tap-scroll-circle{touch-action:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;transition-property:transform;transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1);display:flex;position:relative}.aqvs-tap-scroll-circle-visual-outer{border-radius:9999px;position:absolute;inset:0}.aqvs-tap-scroll-circle-gradient{background:linear-gradient(to bottom right,#1d4ed899,#60a5fa8c,#bfdbfe66);border:1px solid #fff6;border-radius:9999px;position:absolute;inset:0;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-tap-scroll-circle-inner{border-radius:9999px;position:absolute;inset:18%}.aqvs-sample-visual-pupil{box-sizing:border-box;background-color:#ffffffd9;border:1px solid #ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-highlight{background-color:#fffc;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-rod{background-color:#ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-scrollbar{z-index:50;cursor:default;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:none;background-color:#fff;position:relative}.aqvs-scrollbar-horizontal{flex-direction:row;align-items:stretch;display:flex}.aqvs-scrollbar-vertical{flex-direction:column;align-items:stretch;display:flex}.aqvs-scrollbar[data-visible=false],.aqvs-scrollbar-thumb-wrapper[data-visible=false]{opacity:0;pointer-events:none}.aqvs-scrollbar-tap-circle-wrapper{pointer-events:auto;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);position:absolute}.aqvs-scrollbar-arrow-button{color:#313131;letter-spacing:normal;background-color:#e0e0e0;border:0 solid;justify-content:center;align-items:center;padding:0;font-family:system-ui,sans-serif;font-size:.75rem;font-weight:400;line-height:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:flex}.aqvs-scrollbar-arrow-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scrollbar-arrow-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scrollbar-arrow-button:disabled{cursor:not-allowed;opacity:.5}.aqvs-scrollbar-arrow-button:enabled:hover{background-color:#d4d4d4}.aqvs-scrollbar-track{background-color:#f5f5f5;flex:1;position:relative}.aqvs-scrollbar-overlay{pointer-events:none;position:absolute;inset:0}.aqvs-scrollbar-thumb-wrapper{touch-action:none;position:absolute}.aqvs-scrollbar-thumb{transform-origin:50%;background-color:#7f7f7f;transition:transform 80ms ease-out;position:absolute}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{transition:none;transform:none}.aqvs-scrollbar-thumb[data-thumb-state=hover]{background-color:#5f5f5f}.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:#4f4f4f;transition:transform 60ms ease-out}.aqvs-scrollbar-thumb-horizontal{inset:1.5px 0}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=hover]{top:-.5px;bottom:-.5px;transform:scaleY(1.06)}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=dragging]{top:-.5px;bottom:-.5px;transform:scaleY(1.12)}.aqvs-scrollbar-thumb-vertical{inset:0 1.5px}.aqvs-scrollbar-thumb-vertical[data-thumb-state=hover]{left:-.5px;right:-.5px;transform:scaleX(1.06)}.aqvs-scrollbar-thumb-vertical[data-thumb-state=dragging]{left:-.5px;right:-.5px;transform:scaleX(1.12)}.aqvs-scroll-to-edge-button{pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;color:#fff;text-transform:uppercase;letter-spacing:.05em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#1f2937cc;border:0 solid;border-radius:9999px;padding:.25rem 3rem;font-family:inherit;font-size:10px;font-weight:500;line-height:1.5;transition-property:transform,background-color;transition-duration:.15s;transform:none;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-scroll-to-edge-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scroll-to-edge-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scroll-to-edge-button:hover{background-color:#374151}.aqvs-scroll-to-edge-button:active{transform:scale(.95)}.aqvs-scroll-to-edge-overlay{pointer-events:none;z-index:10;transition-property:opacity;transition-duration:.5s;position:absolute;inset:0}.aqvs-scroll-to-edge-overlay[data-visible=true]{opacity:1}.aqvs-scroll-to-edge-overlay[data-visible=false]{opacity:0}.aqvs-scroll-to-edge-overlay[data-visible=false] .aqvs-scroll-to-edge-button{pointer-events:none}.aqvs-scroll-to-edge-button-container{justify-content:center;display:flex;position:absolute;left:0;right:0}.aqvs-scroll-to-edge-button-container-top{top:.5rem}.aqvs-scroll-to-edge-button-container-bottom{bottom:.5rem}.aqvs-no-items-container{width:100%;position:absolute;top:0}.aqvs-no-items-text{text-align:center;color:#6b7280}.aqvs-item-container,.aqvs-bottom-inset
|
|
2
|
+
@layer components{.aqvs-scroll-pane{display:flex;position:relative}.aqvs-scroll-pane[data-self-measured=true]{height:100%}.aqvs-scroll-pane-content{box-sizing:border-box;flex:1;height:100%;position:relative;overflow:hidden}.aqvs-tap-scroll-circle{touch-action:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;transition-property:transform;transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1);display:flex;position:relative}.aqvs-tap-scroll-circle-visual-outer{border-radius:9999px;position:absolute;inset:0}.aqvs-tap-scroll-circle-gradient{background:linear-gradient(to bottom right,#1d4ed899,#60a5fa8c,#bfdbfe66);border:1px solid #fff6;border-radius:9999px;position:absolute;inset:0;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-tap-scroll-circle-inner{border-radius:9999px;position:absolute;inset:18%}.aqvs-sample-visual-pupil{box-sizing:border-box;background-color:#ffffffd9;border:1px solid #ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-highlight{background-color:#fffc;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-rod{background-color:#ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-scrollbar{z-index:50;cursor:default;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:none;background-color:#fff;position:relative}.aqvs-scrollbar-horizontal{flex-direction:row;align-items:stretch;display:flex}.aqvs-scrollbar-vertical{flex-direction:column;align-items:stretch;display:flex}.aqvs-scrollbar[data-visible=false],.aqvs-scrollbar-thumb-wrapper[data-visible=false]{opacity:0;pointer-events:none}.aqvs-scrollbar-tap-circle-wrapper{pointer-events:auto;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);position:absolute}.aqvs-scrollbar-arrow-button{color:#313131;letter-spacing:normal;background-color:#e0e0e0;border:0 solid;justify-content:center;align-items:center;padding:0;font-family:system-ui,sans-serif;font-size:.75rem;font-weight:400;line-height:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:flex}.aqvs-scrollbar-arrow-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scrollbar-arrow-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scrollbar-arrow-button:disabled{cursor:not-allowed;opacity:.5}.aqvs-scrollbar-arrow-button:enabled:hover{background-color:#d4d4d4}.aqvs-scrollbar-track{background-color:#f5f5f5;flex:1;position:relative}.aqvs-scrollbar-overlay{pointer-events:none;position:absolute;inset:0}.aqvs-scrollbar-thumb-wrapper{touch-action:none;position:absolute}.aqvs-scrollbar-thumb{transform-origin:50%;background-color:#7f7f7f;transition:transform 80ms ease-out;position:absolute}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{transition:none;transform:none}.aqvs-scrollbar-thumb[data-thumb-state=hover]{background-color:#5f5f5f}.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:#4f4f4f;transition:transform 60ms ease-out}.aqvs-scrollbar-thumb-horizontal{inset:1.5px 0}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=hover]{top:-.5px;bottom:-.5px;transform:scaleY(1.06)}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=dragging]{top:-.5px;bottom:-.5px;transform:scaleY(1.12)}.aqvs-scrollbar-thumb-vertical{inset:0 1.5px}.aqvs-scrollbar-thumb-vertical[data-thumb-state=hover]{left:-.5px;right:-.5px;transform:scaleX(1.06)}.aqvs-scrollbar-thumb-vertical[data-thumb-state=dragging]{left:-.5px;right:-.5px;transform:scaleX(1.12)}.aqvs-scroll-to-edge-button{pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;color:#fff;text-transform:uppercase;letter-spacing:.05em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#1f2937cc;border:0 solid;border-radius:9999px;padding:.25rem 3rem;font-family:inherit;font-size:10px;font-weight:500;line-height:1.5;transition-property:transform,background-color;transition-duration:.15s;transform:none;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-scroll-to-edge-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scroll-to-edge-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scroll-to-edge-button:hover{background-color:#374151}.aqvs-scroll-to-edge-button:active{transform:scale(.95)}.aqvs-scroll-to-edge-overlay{pointer-events:none;z-index:10;transition-property:opacity;transition-duration:.5s;position:absolute;inset:0}.aqvs-scroll-to-edge-overlay[data-visible=true]{opacity:1}.aqvs-scroll-to-edge-overlay[data-visible=false]{opacity:0}.aqvs-scroll-to-edge-overlay[data-visible=false] .aqvs-scroll-to-edge-button{pointer-events:none}.aqvs-scroll-to-edge-button-container{justify-content:center;display:flex;position:absolute;left:0;right:0}.aqvs-scroll-to-edge-button-container-top{top:.5rem}.aqvs-scroll-to-edge-button-container-bottom{bottom:.5rem}.aqvs-no-items-container{width:100%;position:absolute;top:0}.aqvs-no-items-text{text-align:center;color:#6b7280}.aqvs-item-container,.aqvs-bottom-inset{width:100%;position:absolute}.aqvs-items-boundary{contain:size layout style;height:0;position:absolute;top:0;left:0;right:0}.aqvs-items-wrapper{width:100%;position:absolute}.aqvs-live-region{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.aqvs-grid{grid-template-rows:minmax(0,1fr) auto;width:100%;height:100%;display:grid;position:relative;overflow:hidden}.aqvs-grid-has-frozen-rows{grid-template-rows:auto minmax(0,1fr) auto}.aqvs-grid-has-trailing-rows{grid-template-rows:minmax(0,1fr) auto auto}.aqvs-grid-has-frozen-rows.aqvs-grid-has-trailing-rows{grid-template-rows:auto minmax(0,1fr) auto auto}.aqvs-grid-frozen-rows{min-width:0;position:relative;overflow:hidden}.aqvs-grid-frozen-band-row{position:absolute;left:0;overflow:hidden}.aqvs-grid-trailing-rows{min-width:0;position:relative;overflow:hidden}.aqvs-grid-trailing-rows-inner{position:absolute;bottom:0;left:0;right:0}.aqvs-grid-trailing-band-row{position:absolute;left:0;overflow:hidden}.aqvs-grid-main{min-width:0;min-height:0;position:relative}.aqvs-grid-row{width:100%;height:100%;transform:translateX(var(--aqvs-grid-hx-residual,0px));position:relative;overflow:visible}.aqvs-grid-cell{height:100%;position:absolute;top:0;overflow:hidden}.aqvs-grid-row.aqvs-grid-row-frozen-host{transform:none}.aqvs-grid-row-scroll{height:100%;top:0;left:var(--aqvs-grid-frozen-width,0px);right:var(--aqvs-grid-trailing-width,0px);position:absolute;overflow:hidden}.aqvs-grid-row-scroll-inner{width:100%;height:100%;transform:translateX(calc(var(--aqvs-grid-hx-residual,0px) - var(--aqvs-grid-frozen-width,0px)));position:absolute;top:0;left:0}.aqvs-grid-row-trailing{height:100%;top:0;left:max(var(--aqvs-grid-frozen-width,0px), calc(100% - var(--aqvs-grid-trailing-width,0px)));position:absolute;right:0;overflow:hidden}.aqvs-grid-row-trailing-inner{height:100%;width:var(--aqvs-grid-trailing-width,0px);position:absolute;top:0;right:0}.aqvs-grid-hbar-strip{min-width:0;padding-left:var(--aqvs-grid-frozen-width,0px);position:relative}.aqvs-grid-live-region{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.aqvs-grid-tap-circle-wrapper{z-index:50;pointer-events:auto;position:absolute}.aqvs-grid-tap-circle{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}@media (forced-colors:active){.aqvs-tap-scroll-circle{outline-offset:-1px;border-radius:50%;outline:1px solid canvastext}.aqvs-scrollbar,.aqvs-scrollbar-track{outline-offset:-1px;outline:1px solid graytext}.aqvs-scrollbar-thumb{forced-color-adjust:none;background-color:canvastext}.aqvs-scrollbar-thumb[data-thumb-state=hover],.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:highlight}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{background-color:graytext}.aqvs-sample-visual-highlight,.aqvs-sample-visual-rod{forced-color-adjust:none;background-color:canvastext}}@media (prefers-reduced-motion:reduce){.aqvs-tap-scroll-circle,.aqvs-tap-scroll-circle *,.aqvs-grid-tap-circle,.aqvs-scrollbar-tap-circle-wrapper,.aqvs-scrollbar-arrow-button,.aqvs-scrollbar-thumb,.aqvs-scroll-to-edge-button,.aqvs-scroll-to-edge-overlay{transition:none!important;animation:none!important}}}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
2
2
|
/*! @aiquants/virtualscroll standalone CSS — 非 Tailwind ホスト専用。ホストの Tailwind ビルドと混在させないこと */
|
|
3
|
-
@layer theme,base;@layer components{.aqvs-scroll-pane{display:flex;position:relative}.aqvs-scroll-pane[data-self-measured=true]{height:100%}.aqvs-scroll-pane-content{box-sizing:border-box;flex:1;height:100%;position:relative;overflow:hidden}.aqvs-tap-scroll-circle{touch-action:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;transition-property:transform;transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1);display:flex;position:relative}.aqvs-tap-scroll-circle-visual-outer{border-radius:9999px;position:absolute;inset:0}.aqvs-tap-scroll-circle-gradient{background:linear-gradient(to bottom right,#1d4ed899,#60a5fa8c,#bfdbfe66);border:1px solid #fff6;border-radius:9999px;position:absolute;inset:0;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-tap-scroll-circle-inner{border-radius:9999px;position:absolute;inset:18%}.aqvs-sample-visual-pupil{box-sizing:border-box;background-color:#ffffffd9;border:1px solid #ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-highlight{background-color:#fffc;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-rod{background-color:#ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-scrollbar{z-index:50;cursor:default;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:none;background-color:#fff;position:relative}.aqvs-scrollbar-horizontal{flex-direction:row;align-items:stretch;display:flex}.aqvs-scrollbar-vertical{flex-direction:column;align-items:stretch;display:flex}.aqvs-scrollbar[data-visible=false],.aqvs-scrollbar-thumb-wrapper[data-visible=false]{opacity:0;pointer-events:none}.aqvs-scrollbar-tap-circle-wrapper{pointer-events:auto;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);position:absolute}.aqvs-scrollbar-arrow-button{color:#313131;letter-spacing:normal;background-color:#e0e0e0;border:0 solid;justify-content:center;align-items:center;padding:0;font-family:system-ui,sans-serif;font-size:.75rem;font-weight:400;line-height:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:flex}.aqvs-scrollbar-arrow-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scrollbar-arrow-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scrollbar-arrow-button:disabled{cursor:not-allowed;opacity:.5}.aqvs-scrollbar-arrow-button:enabled:hover{background-color:#d4d4d4}.aqvs-scrollbar-track{background-color:#f5f5f5;flex:1;position:relative}.aqvs-scrollbar-overlay{pointer-events:none;position:absolute;inset:0}.aqvs-scrollbar-thumb-wrapper{touch-action:none;position:absolute}.aqvs-scrollbar-thumb{transform-origin:50%;background-color:#7f7f7f;transition:transform 80ms ease-out;position:absolute}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{transition:none;transform:none}.aqvs-scrollbar-thumb[data-thumb-state=hover]{background-color:#5f5f5f}.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:#4f4f4f;transition:transform 60ms ease-out}.aqvs-scrollbar-thumb-horizontal{inset:1.5px 0}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=hover]{top:-.5px;bottom:-.5px;transform:scaleY(1.06)}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=dragging]{top:-.5px;bottom:-.5px;transform:scaleY(1.12)}.aqvs-scrollbar-thumb-vertical{inset:0 1.5px}.aqvs-scrollbar-thumb-vertical[data-thumb-state=hover]{left:-.5px;right:-.5px;transform:scaleX(1.06)}.aqvs-scrollbar-thumb-vertical[data-thumb-state=dragging]{left:-.5px;right:-.5px;transform:scaleX(1.12)}.aqvs-scroll-to-edge-button{pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;color:#fff;text-transform:uppercase;letter-spacing:.05em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#1f2937cc;border:0 solid;border-radius:9999px;padding:.25rem 3rem;font-family:inherit;font-size:10px;font-weight:500;line-height:1.5;transition-property:transform,background-color;transition-duration:.15s;transform:none;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-scroll-to-edge-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scroll-to-edge-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scroll-to-edge-button:hover{background-color:#374151}.aqvs-scroll-to-edge-button:active{transform:scale(.95)}.aqvs-scroll-to-edge-overlay{pointer-events:none;z-index:10;transition-property:opacity;transition-duration:.5s;position:absolute;inset:0}.aqvs-scroll-to-edge-overlay[data-visible=true]{opacity:1}.aqvs-scroll-to-edge-overlay[data-visible=false]{opacity:0}.aqvs-scroll-to-edge-overlay[data-visible=false] .aqvs-scroll-to-edge-button{pointer-events:none}.aqvs-scroll-to-edge-button-container{justify-content:center;display:flex;position:absolute;left:0;right:0}.aqvs-scroll-to-edge-button-container-top{top:.5rem}.aqvs-scroll-to-edge-button-container-bottom{bottom:.5rem}.aqvs-no-items-container{width:100%;position:absolute;top:0}.aqvs-no-items-text{text-align:center;color:#6b7280}.aqvs-item-container,.aqvs-bottom-inset
|
|
3
|
+
@layer theme,base;@layer components{.aqvs-scroll-pane{display:flex;position:relative}.aqvs-scroll-pane[data-self-measured=true]{height:100%}.aqvs-scroll-pane-content{box-sizing:border-box;flex:1;height:100%;position:relative;overflow:hidden}.aqvs-tap-scroll-circle{touch-action:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;transition-property:transform;transition-duration:.1s;transition-timing-function:cubic-bezier(0,0,.2,1);display:flex;position:relative}.aqvs-tap-scroll-circle-visual-outer{border-radius:9999px;position:absolute;inset:0}.aqvs-tap-scroll-circle-gradient{background:linear-gradient(to bottom right,#1d4ed899,#60a5fa8c,#bfdbfe66);border:1px solid #fff6;border-radius:9999px;position:absolute;inset:0;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-tap-scroll-circle-inner{border-radius:9999px;position:absolute;inset:18%}.aqvs-sample-visual-pupil{box-sizing:border-box;background-color:#ffffffd9;border:1px solid #ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-highlight{background-color:#fffc;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-sample-visual-rod{background-color:#ffffff80;border-radius:9999px;position:absolute;top:50%;left:50%}.aqvs-scrollbar{z-index:50;cursor:default;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:none;background-color:#fff;position:relative}.aqvs-scrollbar-horizontal{flex-direction:row;align-items:stretch;display:flex}.aqvs-scrollbar-vertical{flex-direction:column;align-items:stretch;display:flex}.aqvs-scrollbar[data-visible=false],.aqvs-scrollbar-thumb-wrapper[data-visible=false]{opacity:0;pointer-events:none}.aqvs-scrollbar-tap-circle-wrapper{pointer-events:auto;transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);position:absolute}.aqvs-scrollbar-arrow-button{color:#313131;letter-spacing:normal;background-color:#e0e0e0;border:0 solid;justify-content:center;align-items:center;padding:0;font-family:system-ui,sans-serif;font-size:.75rem;font-weight:400;line-height:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:flex}.aqvs-scrollbar-arrow-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scrollbar-arrow-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scrollbar-arrow-button:disabled{cursor:not-allowed;opacity:.5}.aqvs-scrollbar-arrow-button:enabled:hover{background-color:#d4d4d4}.aqvs-scrollbar-track{background-color:#f5f5f5;flex:1;position:relative}.aqvs-scrollbar-overlay{pointer-events:none;position:absolute;inset:0}.aqvs-scrollbar-thumb-wrapper{touch-action:none;position:absolute}.aqvs-scrollbar-thumb{transform-origin:50%;background-color:#7f7f7f;transition:transform 80ms ease-out;position:absolute}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{transition:none;transform:none}.aqvs-scrollbar-thumb[data-thumb-state=hover]{background-color:#5f5f5f}.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:#4f4f4f;transition:transform 60ms ease-out}.aqvs-scrollbar-thumb-horizontal{inset:1.5px 0}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=hover]{top:-.5px;bottom:-.5px;transform:scaleY(1.06)}.aqvs-scrollbar-thumb-horizontal[data-thumb-state=dragging]{top:-.5px;bottom:-.5px;transform:scaleY(1.12)}.aqvs-scrollbar-thumb-vertical{inset:0 1.5px}.aqvs-scrollbar-thumb-vertical[data-thumb-state=hover]{left:-.5px;right:-.5px;transform:scaleX(1.06)}.aqvs-scrollbar-thumb-vertical[data-thumb-state=dragging]{left:-.5px;right:-.5px;transform:scaleX(1.12)}.aqvs-scroll-to-edge-button{pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;color:#fff;text-transform:uppercase;letter-spacing:.05em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#1f2937cc;border:0 solid;border-radius:9999px;padding:.25rem 3rem;font-family:inherit;font-size:10px;font-weight:500;line-height:1.5;transition-property:transform,background-color;transition-duration:.15s;transform:none;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.aqvs-scroll-to-edge-button:focus{outline-offset:2px;outline:2px solid #0000}.aqvs-scroll-to-edge-button:focus-visible{outline-offset:1px;outline:2px solid #60a5fa}.aqvs-scroll-to-edge-button:hover{background-color:#374151}.aqvs-scroll-to-edge-button:active{transform:scale(.95)}.aqvs-scroll-to-edge-overlay{pointer-events:none;z-index:10;transition-property:opacity;transition-duration:.5s;position:absolute;inset:0}.aqvs-scroll-to-edge-overlay[data-visible=true]{opacity:1}.aqvs-scroll-to-edge-overlay[data-visible=false]{opacity:0}.aqvs-scroll-to-edge-overlay[data-visible=false] .aqvs-scroll-to-edge-button{pointer-events:none}.aqvs-scroll-to-edge-button-container{justify-content:center;display:flex;position:absolute;left:0;right:0}.aqvs-scroll-to-edge-button-container-top{top:.5rem}.aqvs-scroll-to-edge-button-container-bottom{bottom:.5rem}.aqvs-no-items-container{width:100%;position:absolute;top:0}.aqvs-no-items-text{text-align:center;color:#6b7280}.aqvs-item-container,.aqvs-bottom-inset{width:100%;position:absolute}.aqvs-items-boundary{contain:size layout style;height:0;position:absolute;top:0;left:0;right:0}.aqvs-items-wrapper{width:100%;position:absolute}.aqvs-live-region{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.aqvs-grid{grid-template-rows:minmax(0,1fr) auto;width:100%;height:100%;display:grid;position:relative;overflow:hidden}.aqvs-grid-has-frozen-rows{grid-template-rows:auto minmax(0,1fr) auto}.aqvs-grid-has-trailing-rows{grid-template-rows:minmax(0,1fr) auto auto}.aqvs-grid-has-frozen-rows.aqvs-grid-has-trailing-rows{grid-template-rows:auto minmax(0,1fr) auto auto}.aqvs-grid-frozen-rows{min-width:0;position:relative;overflow:hidden}.aqvs-grid-frozen-band-row{position:absolute;left:0;overflow:hidden}.aqvs-grid-trailing-rows{min-width:0;position:relative;overflow:hidden}.aqvs-grid-trailing-rows-inner{position:absolute;bottom:0;left:0;right:0}.aqvs-grid-trailing-band-row{position:absolute;left:0;overflow:hidden}.aqvs-grid-main{min-width:0;min-height:0;position:relative}.aqvs-grid-row{width:100%;height:100%;transform:translateX(var(--aqvs-grid-hx-residual,0px));position:relative;overflow:visible}.aqvs-grid-cell{height:100%;position:absolute;top:0;overflow:hidden}.aqvs-grid-row.aqvs-grid-row-frozen-host{transform:none}.aqvs-grid-row-scroll{height:100%;top:0;left:var(--aqvs-grid-frozen-width,0px);right:var(--aqvs-grid-trailing-width,0px);position:absolute;overflow:hidden}.aqvs-grid-row-scroll-inner{width:100%;height:100%;transform:translateX(calc(var(--aqvs-grid-hx-residual,0px) - var(--aqvs-grid-frozen-width,0px)));position:absolute;top:0;left:0}.aqvs-grid-row-trailing{height:100%;top:0;left:max(var(--aqvs-grid-frozen-width,0px), calc(100% - var(--aqvs-grid-trailing-width,0px)));position:absolute;right:0;overflow:hidden}.aqvs-grid-row-trailing-inner{height:100%;width:var(--aqvs-grid-trailing-width,0px);position:absolute;top:0;right:0}.aqvs-grid-hbar-strip{min-width:0;padding-left:var(--aqvs-grid-frozen-width,0px);position:relative}.aqvs-grid-live-region{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.aqvs-grid-tap-circle-wrapper{z-index:50;pointer-events:auto;position:absolute}.aqvs-grid-tap-circle{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}@media (forced-colors:active){.aqvs-tap-scroll-circle{outline-offset:-1px;border-radius:50%;outline:1px solid canvastext}.aqvs-scrollbar,.aqvs-scrollbar-track{outline-offset:-1px;outline:1px solid graytext}.aqvs-scrollbar-thumb{forced-color-adjust:none;background-color:canvastext}.aqvs-scrollbar-thumb[data-thumb-state=hover],.aqvs-scrollbar-thumb[data-thumb-state=dragging]{background-color:highlight}.aqvs-scrollbar-thumb[data-thumb-state=disabled]{background-color:graytext}.aqvs-sample-visual-highlight,.aqvs-sample-visual-rod{forced-color-adjust:none;background-color:canvastext}}@media (prefers-reduced-motion:reduce){.aqvs-tap-scroll-circle,.aqvs-tap-scroll-circle *,.aqvs-grid-tap-circle,.aqvs-scrollbar-tap-circle-wrapper,.aqvs-scrollbar-arrow-button,.aqvs-scrollbar-thumb,.aqvs-scroll-to-edge-button,.aqvs-scroll-to-edge-overlay{transition:none!important;animation:none!important}}}@layer utilities;
|
package/dist/utils.d.cts
CHANGED
|
@@ -27,3 +27,17 @@ export declare const minmax: (value: number, min: number, max: number) => number
|
|
|
27
27
|
* @returns The visual/layout scale ratio (1 when unmeasurable). / 視覚/レイアウト比 (計測不能時 1)。
|
|
28
28
|
*/
|
|
29
29
|
export declare const getAxisScale: (element: HTMLElement, axis: "x" | "y") => number;
|
|
30
|
+
/**
|
|
31
|
+
* Pointer-down handler of pointer-only scroll chrome (the scrollbar and the scroll-to-edge pills of a host that scrolls by
|
|
32
|
+
* keyboard itself): cancels the press's default action, so the press never moves focus — neither onto a part of the chrome
|
|
33
|
+
* nor away from where the host put it — while the press itself, its pointer events and its click still reach the part.
|
|
34
|
+
*
|
|
35
|
+
* ポインタ専用のスクロールの部品 (キーボードのスクロールを自分で持つホストのスクロールバーと端へ戻るピル) の pointerdown の
|
|
36
|
+
* 処理。押下の既定動作を取り消すので、押下はフォーカスを動かさない — 部品の上へも、ホストが置いた場所の外へも — が、押下
|
|
37
|
+
* そのもの (ポインタのイベントと click) は部品へ届く。
|
|
38
|
+
*
|
|
39
|
+
* @param event - The pointer-down event (only its default action is read) / pointerdown のイベント (既定動作だけを扱う)
|
|
40
|
+
*/
|
|
41
|
+
export declare const keepFocusOnPress: (event: {
|
|
42
|
+
readonly preventDefault: () => void;
|
|
43
|
+
}) => void;
|
package/dist/utils.d.ts
CHANGED
|
@@ -27,4 +27,18 @@ export declare const minmax: (value: number, min: number, max: number) => number
|
|
|
27
27
|
* @returns The visual/layout scale ratio (1 when unmeasurable). / 視覚/レイアウト比 (計測不能時 1)。
|
|
28
28
|
*/
|
|
29
29
|
export declare const getAxisScale: (element: HTMLElement, axis: "x" | "y") => number;
|
|
30
|
+
/**
|
|
31
|
+
* Pointer-down handler of pointer-only scroll chrome (the scrollbar and the scroll-to-edge pills of a host that scrolls by
|
|
32
|
+
* keyboard itself): cancels the press's default action, so the press never moves focus — neither onto a part of the chrome
|
|
33
|
+
* nor away from where the host put it — while the press itself, its pointer events and its click still reach the part.
|
|
34
|
+
*
|
|
35
|
+
* ポインタ専用のスクロールの部品 (キーボードのスクロールを自分で持つホストのスクロールバーと端へ戻るピル) の pointerdown の
|
|
36
|
+
* 処理。押下の既定動作を取り消すので、押下はフォーカスを動かさない — 部品の上へも、ホストが置いた場所の外へも — が、押下
|
|
37
|
+
* そのもの (ポインタのイベントと click) は部品へ届く。
|
|
38
|
+
*
|
|
39
|
+
* @param event - The pointer-down event (only its default action is read) / pointerdown のイベント (既定動作だけを扱う)
|
|
40
|
+
*/
|
|
41
|
+
export declare const keepFocusOnPress: (event: {
|
|
42
|
+
readonly preventDefault: () => void;
|
|
43
|
+
}) => void;
|
|
30
44
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAEhE,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,WAAW,EAAE,MAAM,GAAG,GAAG,GAAG,KAAG,MA0BpE,CAAA"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAEhE,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,WAAW,EAAE,MAAM,GAAG,GAAG,GAAG,KAAG,MA0BpE,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO;IAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAA;CAAE,KAAG,IAEjF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiquants/virtualscroll",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "High-performance virtual scrolling component for React with variable item heights",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -99,7 +99,10 @@
|
|
|
99
99
|
"test:e2e": "playwright test --repeat-each 1",
|
|
100
100
|
"test:e2e:headed": "playwright test --headed",
|
|
101
101
|
"test:watch": "vitest --watch",
|
|
102
|
-
"test:coverage": "vitest --coverage",
|
|
102
|
+
"test:coverage": "vitest run --coverage && node scripts/ratchet-coverage.mjs",
|
|
103
|
+
"check:coverage": "node scripts/ratchet-coverage.mjs",
|
|
104
|
+
"coverage:ratchet": "node scripts/ratchet-coverage.mjs --write",
|
|
105
|
+
"coverage:adopt": "node scripts/ratchet-coverage.mjs --adopt",
|
|
103
106
|
"lint": "biome check src tests",
|
|
104
107
|
"lint:fix": "biome check --write src tests",
|
|
105
108
|
"format": "biome format --write src tests",
|
package/src/ScrollBar.tsx
CHANGED
|
@@ -7,11 +7,11 @@ 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
9
|
import { snapToDevicePixelGrid, usePaintingDevicePixelRatio } from "./devicePixelGrid.ts"
|
|
10
|
-
import { resolveVirtualScrollLabels, type VirtualScrollLabelOverrides, type VirtualScrollLocale } from "./labels.ts"
|
|
10
|
+
import { resolveVirtualScrollLabels, type VirtualScrollLabelOverrides, type VirtualScrollLabels, type VirtualScrollLocale } from "./labels.ts"
|
|
11
11
|
import { Logger } from "./logger.ts"
|
|
12
12
|
import { capturePointer, releaseCapturedPointer } from "./pointerCapture.ts"
|
|
13
13
|
import { TapScrollCircle, type TapScrollCircleDragState, type TapScrollCircleHandle, type TapScrollCircleRenderProps } from "./TapScrollCircle.tsx"
|
|
14
|
-
import { getAxisScale, minmax } from "./utils.ts"
|
|
14
|
+
import { getAxisScale, keepFocusOnPress, minmax } from "./utils.ts"
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Configuration for scrollbar orientation (vertical or horizontal).
|
|
@@ -163,37 +163,41 @@ export type ScrollBarProps = {
|
|
|
163
163
|
/** Whether arrow buttons control the scroll position. / 矢印ボタンによるスクロール操作を許可するかどうか。 */
|
|
164
164
|
enableArrowButtons?: boolean
|
|
165
165
|
/**
|
|
166
|
-
* Whether the
|
|
166
|
+
* Whether the bar is the keyboard user's scrolling control (default `true`), or a pointer-only control because the host
|
|
167
|
+
* scrolls this viewport by keyboard itself (`false`).
|
|
167
168
|
*
|
|
168
|
-
* `
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* scrolling of this viewport (roving row focus with Arrow / Page / Home / End, a grid keyboard
|
|
175
|
-
* model): the arrows then duplicate that path and cost every keyboard user two extra Tab presses
|
|
176
|
-
* per bar — native scrollbars are never Tab stops either. The default stays `true` because
|
|
177
|
-
* without such a host model the arrows are the only scrolling control a keyboard user can reach
|
|
178
|
-
* with Tab: `ScrollPane` / `VirtualScroll` move their content by transform, so there is no native
|
|
179
|
-
* scroller the browser could make focusable, and their rows are not Tab stops. No effect while
|
|
180
|
-
* the arrows are disabled (`enableArrowButtons: false`, or nothing to scroll) — a disabled button
|
|
181
|
-
* is never focusable.
|
|
169
|
+
* `true`: the bar is exposed to assistive technology as a named `role="scrollbar"` (`labels.verticalScrollBar` /
|
|
170
|
+
* `labels.horizontalScrollBar`) holding a named `role="slider"` thumb (`labels.verticalScrollThumb` /
|
|
171
|
+
* `labels.horizontalScrollThumb`), and its two arrow buttons are Tab stops: `ScrollPane` / `VirtualScroll` move their
|
|
172
|
+
* content by transform, so there is no native scroller the browser could make focusable, and their rows are not Tab
|
|
173
|
+
* stops — without a host keyboard model the arrows are the only scrolling control Tab reaches. Focus an arrow and
|
|
174
|
+
* Enter / Space scrolls one step.
|
|
182
175
|
*
|
|
183
|
-
*
|
|
176
|
+
* `false` declares that the host owns keyboard scrolling of this viewport (roving row focus with Arrow / Page / Home /
|
|
177
|
+
* End, a grid keyboard model), so the bar only duplicates that path. The bar then becomes what a native scrollbar is:
|
|
178
|
+
* a pointer-only control. The bar carries `aria-hidden="true"`; its arrows get `tabIndex={-1}`, and the bar root and
|
|
179
|
+
* the thumb wrapper are not focusable; a press anywhere on the bar cancels its default action, so it never moves
|
|
180
|
+
* focus — neither onto a part of the bar (an arrow, also a disabled one) nor away from where the host put it — while
|
|
181
|
+
* the press itself still reaches the part. Pointer scrolling is unchanged: the arrows (with press-and-hold repeat),
|
|
182
|
+
* the track, the thumb and the tap circle work exactly as with `true`. The same signal reaches the scroll-to-edge pills
|
|
183
|
+
* of `VirtualScroll` (`VirtualScrollScrollBarOptions["enableArrowButtonTabStops"]`).
|
|
184
184
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* (
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
185
|
+
* バーがキーボード利用者のスクロール操作部品か (既定 `true`)、ホストがこのビューポートのキーボードスクロールを自分で
|
|
186
|
+
* 持つためポインタ専用の部品か (`false`) の指定。
|
|
187
|
+
*
|
|
188
|
+
* `true`: バーは名前付きの `role="scrollbar"` (`labels.verticalScrollBar` / `labels.horizontalScrollBar`) として
|
|
189
|
+
* 支援技術へ見え、名前付きの `role="slider"` のつまみ (`labels.verticalScrollThumb` / `labels.horizontalScrollThumb`) を
|
|
190
|
+
* 持ち、矢印ボタン 2 個は Tab の止まり先。`ScrollPane` / `VirtualScroll` はコンテンツを transform で動かすため、
|
|
191
|
+
* ブラウザがフォーカス可能にできるネイティブのスクロール領域が無く、行も Tab の止まり先ではない — ホストのキーボード
|
|
192
|
+
* モデルが無ければ、矢印が Tab で届く唯一のスクロール操作部品。矢印にフォーカスして Enter / Space で 1 ステップ移動。
|
|
193
|
+
*
|
|
194
|
+
* `false` は、ホストがこのビューポートのキーボードスクロールを持つ (行のロービングフォーカスと矢印 / Page / Home / End、
|
|
195
|
+
* グリッドのキーボードモデル) ことの宣言で、バーはその経路の重複にすぎない。バーはネイティブのスクロールバーと同じく
|
|
196
|
+
* ポインタ専用の部品になる。バーは `aria-hidden="true"` を持ち、矢印は `tabIndex={-1}`、バーのルートとつまみの器は
|
|
197
|
+
* フォーカス不能。バーのどこを押しても押下の既定動作を取り消すので、押下はフォーカスを動かさない — バーの部品
|
|
198
|
+
* (矢印。無効の矢印も) へも、ホストが置いた場所の外へも — が、押下そのものは部品へ届く。ポインタのスクロールは
|
|
199
|
+
* 変わらない: 矢印 (長押しの連続を含む)・トラック・つまみ・タップのサークルは `true` と同じに動く。同じ合図は
|
|
200
|
+
* `VirtualScroll` の端へ戻るピルにも届く (`VirtualScrollScrollBarOptions["enableArrowButtonTabStops"]`)。
|
|
197
201
|
*/
|
|
198
202
|
enableArrowButtonTabStops?: boolean
|
|
199
203
|
/** Whether the scrollbar is horizontal. / スクロールバーが水平かどうか。 */
|
|
@@ -231,18 +235,20 @@ export type ScrollBarProps = {
|
|
|
231
235
|
/** The index of the last visible item. / 最後の可視アイテムのインデックス。 */
|
|
232
236
|
visibleEndIndex?: number
|
|
233
237
|
/**
|
|
234
|
-
* UI chrome locale of the built-in
|
|
235
|
-
* throws a RangeError at render; no language negotiation happens.
|
|
236
|
-
*
|
|
238
|
+
* UI chrome locale of the built-in accessible names of the bar, its thumb and its arrows (default `"en"`). An
|
|
239
|
+
* unsupported value throws a RangeError at render; no language negotiation happens.
|
|
240
|
+
* バー・つまみ・矢印の内蔵アクセシブルネームの UI クロームロケール (既定 `"en"`)。非対応値は描画時に RangeError、
|
|
237
241
|
* 言語ネゴシエーションなし。
|
|
238
242
|
*/
|
|
239
243
|
locale?: VirtualScrollLocale
|
|
240
244
|
/**
|
|
241
|
-
* Per-key overrides laid over the catalog of `locale`.
|
|
242
|
-
*
|
|
245
|
+
* Per-key overrides laid over the catalog of `locale`. A vertical bar reads `verticalScrollBar`,
|
|
246
|
+
* `verticalScrollThumb`, `scrollUp` and `scrollDown`; a horizontal bar reads `horizontalScrollBar`,
|
|
247
|
+
* `horizontalScrollThumb`, `scrollLeft` and `scrollRight`. Unknown keys and blank values throw a
|
|
243
248
|
* RangeError at render.
|
|
244
|
-
* `locale`
|
|
245
|
-
*
|
|
249
|
+
* `locale` のカタログへ重ねるキー単位の上書き。縦のバーが読むのは `verticalScrollBar`・`verticalScrollThumb`・
|
|
250
|
+
* `scrollUp`・`scrollDown`、横のバーは `horizontalScrollBar`・`horizontalScrollThumb`・`scrollLeft`・`scrollRight`。
|
|
251
|
+
* 未知キーと空白値は描画時に RangeError。
|
|
246
252
|
*/
|
|
247
253
|
labels?: VirtualScrollLabelOverrides
|
|
248
254
|
}
|
|
@@ -294,6 +300,33 @@ export const DEFAULT_TAP_SCROLL_CIRCLE_OPTIONS: ResolvedTapScrollCircleOptions =
|
|
|
294
300
|
maxSpeedCurve: undefined,
|
|
295
301
|
}
|
|
296
302
|
|
|
303
|
+
/**
|
|
304
|
+
* The accessible names one bar renders: the bar (`role="scrollbar"`), its thumb (`role="slider"`) and its two arrows
|
|
305
|
+
* (start, end).
|
|
306
|
+
*
|
|
307
|
+
* バー 1 本が描くアクセシブルネーム (バー `role="scrollbar"`・つまみ `role="slider"`・始端と終端の矢印)。
|
|
308
|
+
*/
|
|
309
|
+
type ScrollBarNames = {
|
|
310
|
+
/** Name of the bar / バーの名前 */
|
|
311
|
+
readonly bar: string
|
|
312
|
+
/** Name of the thumb / つまみの名前 */
|
|
313
|
+
readonly thumb: string
|
|
314
|
+
/** Names of the start and the end arrow / 始端と終端の矢印の名前 */
|
|
315
|
+
readonly arrows: readonly [string, string]
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Picks the names of one bar from the resolved labels by its orientation.
|
|
320
|
+
*
|
|
321
|
+
* 解決済みのラベルから、向きに応じてバー 1 本の名前を選ぶ処理。
|
|
322
|
+
*
|
|
323
|
+
* @param labels - Resolved labels / 解決済みのラベル
|
|
324
|
+
* @param horizontal - Whether the bar is horizontal / 横のバーか
|
|
325
|
+
* @returns The bar's names / バーの名前
|
|
326
|
+
*/
|
|
327
|
+
const pickScrollBarNames = (labels: VirtualScrollLabels, horizontal: boolean): ScrollBarNames =>
|
|
328
|
+
horizontal ? { bar: labels.horizontalScrollBar, thumb: labels.horizontalScrollThumb, arrows: [labels.scrollLeft, labels.scrollRight] } : { bar: labels.verticalScrollBar, thumb: labels.verticalScrollThumb, arrows: [labels.scrollUp, labels.scrollDown] }
|
|
329
|
+
|
|
297
330
|
/**
|
|
298
331
|
* Creates the orientation dependent configuration for the scrollbar.
|
|
299
332
|
*
|
|
@@ -695,7 +728,9 @@ export const ScrollBar = ({
|
|
|
695
728
|
const resolvedTapScrollOptions = useMemo<ResolvedTapScrollCircleOptions>(() => resolveTapScrollCircleOptions(tapScrollCircleOptions, itemCount), [itemCount, tapScrollCircleOptions])
|
|
696
729
|
const orientationConfig = useMemo(() => createOrientationConfig(horizontal), [horizontal])
|
|
697
730
|
const resolvedLabels = useMemo(() => resolveVirtualScrollLabels(locale, labels), [locale, labels])
|
|
698
|
-
const
|
|
731
|
+
const names = pickScrollBarNames(resolvedLabels, horizontal)
|
|
732
|
+
// ホストがキーボードのスクロールを持つと、バーはその経路の重複になる。支援技術にもキーボードにも同じ操作を 2 度見せない
|
|
733
|
+
const pointerOnly = !enableArrowButtonTabStops
|
|
699
734
|
const {
|
|
700
735
|
enabled: tapCircleEnabled,
|
|
701
736
|
size: tapCircleSize,
|
|
@@ -1484,13 +1519,14 @@ export const ScrollBar = ({
|
|
|
1484
1519
|
}, [tapCircleOffsetX, tapCircleOffsetY, tapCircleSize])
|
|
1485
1520
|
|
|
1486
1521
|
/**
|
|
1487
|
-
* Renders one arrow button of the bar
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1522
|
+
* Renders one arrow button of the bar: a named Tab stop (`tabIndex=0`) on which Enter / Space scrolls one step, or,
|
|
1523
|
+
* on a pointer-only bar (`enableArrowButtonTabStops={false}`), a pointer target out of the Tab order (`tabIndex=-1`)
|
|
1524
|
+
* inside the bar's `aria-hidden` subtree, whose presses never move focus. Pointer presses and press-and-hold repeat
|
|
1525
|
+
* work the same either way.
|
|
1490
1526
|
*
|
|
1491
|
-
* バーの矢印ボタン 1
|
|
1492
|
-
*
|
|
1493
|
-
*
|
|
1527
|
+
* バーの矢印ボタン 1 個の描画。名前付きの Tab の止まり先 (`tabIndex=0`) で Enter / Space により 1 ステップ移動するか、
|
|
1528
|
+
* ポインタ専用のバー (`enableArrowButtonTabStops={false}`) では Tab 順の外のポインタの的 (`tabIndex=-1`) で、
|
|
1529
|
+
* バーの `aria-hidden` の部分木の中にあり押下はフォーカスを動かさない。ポインタの押下と長押しの連続はどちらも同じ。
|
|
1494
1530
|
*
|
|
1495
1531
|
* @param direction - Step direction (-1 = toward the start, 1 = toward the end) / ステップ方向 (-1 = 始端側、1 = 終端側)
|
|
1496
1532
|
* @param label - Accessible name / アクセシブルネーム
|
|
@@ -1502,7 +1538,7 @@ export const ScrollBar = ({
|
|
|
1502
1538
|
<button
|
|
1503
1539
|
key={key}
|
|
1504
1540
|
type="button"
|
|
1505
|
-
tabIndex={
|
|
1541
|
+
tabIndex={pointerOnly ? -1 : 0}
|
|
1506
1542
|
className="aqvs-scrollbar-arrow-button"
|
|
1507
1543
|
style={{
|
|
1508
1544
|
[mainSizeKey]: scrollBarWidth,
|
|
@@ -1552,7 +1588,12 @@ export const ScrollBar = ({
|
|
|
1552
1588
|
// components-only アーティファクトには同梱されず、ホストのビルド内容任せになる
|
|
1553
1589
|
data-visible={scrollBarVisible ? "true" : "false"}
|
|
1554
1590
|
role="scrollbar"
|
|
1555
|
-
|
|
1591
|
+
aria-label={names.bar}
|
|
1592
|
+
aria-hidden={pointerOnly ? true : undefined}
|
|
1593
|
+
// ポインタ専用のバーはフォーカスを受ける部品を持たない。押下の既定動作も取り消す: Chromium は無効の矢印の押下でも
|
|
1594
|
+
// pointerdown を届けたうえで、最も近いフォーカス可能な祖先へフォーカスを移す (取り消すとどこへも移さない)
|
|
1595
|
+
tabIndex={pointerOnly ? undefined : -1}
|
|
1596
|
+
onPointerDown={pointerOnly ? keepFocusOnPress : undefined}
|
|
1556
1597
|
aria-controls={ariaControls}
|
|
1557
1598
|
aria-valuenow={scrollPosition}
|
|
1558
1599
|
aria-valuemin={0}
|
|
@@ -1572,7 +1613,7 @@ export const ScrollBar = ({
|
|
|
1572
1613
|
onDragChange={handleTapCircleDragChange}
|
|
1573
1614
|
/>
|
|
1574
1615
|
)}
|
|
1575
|
-
{renderArrowButton(-1,
|
|
1616
|
+
{renderArrowButton(-1, names.arrows[0], arrowIcons[0], "arrow-start")}
|
|
1576
1617
|
<div
|
|
1577
1618
|
key="track"
|
|
1578
1619
|
className="aqvs-scrollbar-track"
|
|
@@ -1607,12 +1648,13 @@ export const ScrollBar = ({
|
|
|
1607
1648
|
data-visible={scrollBarVisible || isDragging ? "true" : "false"}
|
|
1608
1649
|
onPointerDown={handlePointerDownOnThumb}
|
|
1609
1650
|
role="slider"
|
|
1651
|
+
aria-label={names.thumb}
|
|
1610
1652
|
aria-orientation={horizontal ? "horizontal" : "vertical"}
|
|
1611
1653
|
aria-valuenow={scrollPosition}
|
|
1612
1654
|
aria-valuemin={0}
|
|
1613
1655
|
aria-valuemax={maxScrollPosition}
|
|
1614
1656
|
aria-disabled={!enableThumbDrag}
|
|
1615
|
-
tabIndex={-1}>
|
|
1657
|
+
tabIndex={pointerOnly ? undefined : -1}>
|
|
1616
1658
|
{/* スクロールバーのつまみ(可視部分) */}
|
|
1617
1659
|
{/* biome-ignore lint/a11y/noStaticElementInteractions: スクロールバーのつまみは必要なインタラクションです */}
|
|
1618
1660
|
<div
|
|
@@ -1639,7 +1681,7 @@ export const ScrollBar = ({
|
|
|
1639
1681
|
/>
|
|
1640
1682
|
</div>
|
|
1641
1683
|
</div>
|
|
1642
|
-
{renderArrowButton(1,
|
|
1684
|
+
{renderArrowButton(1, names.arrows[1], arrowIcons[1], "arrow-end")}
|
|
1643
1685
|
</div>
|
|
1644
1686
|
)
|
|
1645
1687
|
}
|
package/src/ScrollPane.tsx
CHANGED
|
@@ -80,18 +80,16 @@ export type ScrollPaneProps = {
|
|
|
80
80
|
/** Whether arrow buttons control the scroll position. / 矢印ボタンのスクロール操作を許可するかどうか。 */
|
|
81
81
|
enableArrowButtons?: boolean
|
|
82
82
|
/**
|
|
83
|
-
* Whether the
|
|
84
|
-
* pane
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* 既定が `true` なのは、それ以外ではペインで Tab の届く唯一のスクロール操作部品だから。契約の全文は
|
|
94
|
-
* `ScrollBarProps["enableArrowButtonTabStops"]`。
|
|
83
|
+
* Whether the pane's scrollbar is the keyboard user's scrolling control (default `true`) or a pointer-only control
|
|
84
|
+
* because the host scrolls this pane by keyboard itself (`false`), forwarded to the pane's ScrollBar. With `false`
|
|
85
|
+
* the bar carries `aria-hidden="true"`, has no Tab stop and no focusable part, and a press on it never moves focus;
|
|
86
|
+
* pointer scrolling is unchanged. The default stays `true` because otherwise the arrows are the pane's only scrolling
|
|
87
|
+
* control that Tab reaches. Full contract: `ScrollBarProps["enableArrowButtonTabStops"]`.
|
|
88
|
+
* ペインのスクロールバーがキーボード利用者のスクロール操作部品か (既定 `true`)、ホストがこのペインのキーボード
|
|
89
|
+
* スクロールを自分で持つためポインタ専用の部品か (`false`) の指定。ペインの ScrollBar へ転送。`false` ではバーが
|
|
90
|
+
* `aria-hidden="true"` を持ち、Tab の止まり先もフォーカス可能な部品も無く、押下はフォーカスを動かさない。ポインタの
|
|
91
|
+
* スクロールは変わらない。既定が `true` なのは、それ以外ではペインで Tab の届く唯一のスクロール操作部品だから。
|
|
92
|
+
* 契約の全文は `ScrollBarProps["enableArrowButtonTabStops"]`。
|
|
95
93
|
*/
|
|
96
94
|
enableArrowButtonTabStops?: boolean
|
|
97
95
|
/** Whether dragging the content area scrolls the pane. / コンテンツ領域のドラッグでスクロールさせるかどうか。 */
|
|
@@ -185,9 +183,9 @@ export type ScrollPaneProps = {
|
|
|
185
183
|
*/
|
|
186
184
|
contentProps?: React.AriaAttributes & { id?: string; role?: React.AriaRole }
|
|
187
185
|
/**
|
|
188
|
-
* UI chrome locale forwarded to the pane's ScrollBar (
|
|
186
|
+
* UI chrome locale forwarded to the pane's ScrollBar (the names of the bar, its thumb and its arrows; default `"en"`).
|
|
189
187
|
* An unsupported value throws a RangeError at render.
|
|
190
|
-
* ペインの ScrollBar へ転送する UI クロームロケール (
|
|
188
|
+
* ペインの ScrollBar へ転送する UI クロームロケール (バー・つまみ・矢印の名前、既定 `"en"`)。
|
|
191
189
|
* 非対応値は描画時に RangeError。
|
|
192
190
|
*/
|
|
193
191
|
locale?: VirtualScrollLocale
|