@onekeyfe/react-native-native-list 3.0.113 → 3.0.115
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/android/build.gradle +1 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +8 -2
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +378 -88
- package/ios/NativeListCell.swift +2 -0
- package/ios/RNCNativeListView.swift +186 -35
- package/lib/module/web/NativeListWebEngine.js +104 -46
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +11 -2
- package/package.json +4 -2
- package/src/web/NativeListWebEngine.ts +190 -89
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
const SECTION_INDEX_CONTENT_INSET = 16;
|
|
50
50
|
const SECTION_INDEX_RAIL_WIDTH = 32;
|
|
51
51
|
const SECTION_INDEX_EDGE_PADDING = 8;
|
|
52
|
-
const
|
|
52
|
+
const SECTION_INDEX_LABEL_SPACING = 16;
|
|
53
53
|
const SECTION_INDEX_MIN_HEIGHT = 120;
|
|
54
54
|
const DEFAULT_VIEWPORT_WIDTH = 320;
|
|
55
55
|
const DEFAULT_VIEWPORT_HEIGHT = 640;
|
|
@@ -772,6 +772,32 @@ export function visibleWebLayoutItems(
|
|
|
772
772
|
return visible;
|
|
773
773
|
}
|
|
774
774
|
|
|
775
|
+
export type WebCollapsiblePagerScrollMetrics = Readonly<{
|
|
776
|
+
offset: number;
|
|
777
|
+
viewportLength: number;
|
|
778
|
+
}>;
|
|
779
|
+
|
|
780
|
+
export function resolveWebCollapsiblePagerScrollMetrics(
|
|
781
|
+
rawOffset: number,
|
|
782
|
+
rawViewportLength: number,
|
|
783
|
+
headerInset: number,
|
|
784
|
+
stickyInset: number
|
|
785
|
+
): WebCollapsiblePagerScrollMetrics {
|
|
786
|
+
const header = Math.max(0, headerInset);
|
|
787
|
+
const sticky = Math.max(0, stickyInset);
|
|
788
|
+
return {
|
|
789
|
+
offset: Math.max(0, rawOffset - header),
|
|
790
|
+
viewportLength: Math.max(0, rawViewportLength - sticky),
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
export function resolveWebCollapsiblePagerRawOffset(
|
|
795
|
+
logicalOffset: number,
|
|
796
|
+
headerInset: number
|
|
797
|
+
): number {
|
|
798
|
+
return Math.max(0, logicalOffset) + Math.max(0, headerInset);
|
|
799
|
+
}
|
|
800
|
+
|
|
775
801
|
export function webLayoutItemsForMount(
|
|
776
802
|
layout: WebListLayout,
|
|
777
803
|
offset: number,
|
|
@@ -896,6 +922,11 @@ export const WEB_LIST_CSS = `
|
|
|
896
922
|
.ok-native-list-subtitle-segments{display:flex;align-items:center;min-width:0;max-width:100%;height:20px}.ok-native-list-subtitle-segments>.ok-native-list-secondary{flex:0 1 auto;min-width:0}.ok-native-list-subtitle-dot{flex:0 0 4px;width:4px;height:4px;margin:0 6px;border-radius:50%;background:var(--nl-disabled)}.ok-native-list-wallet-row>.ok-native-list-flex{flex:0 1 auto;width:100%;align-items:center}.ok-native-list-wallet-badges{display:flex;gap:4px;justify-content:center;margin-top:4px;height:20px;max-width:100%}.ok-native-list-wallet-badges>.ok-native-list-badge{background:var(--nl-strong);color:var(--nl-secondary);font-size:12px;line-height:16px;height:20px;box-sizing:border-box;padding:2px 4px}.ok-native-list-visual-overlay{position:absolute;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border-radius:50%;overflow:hidden;line-height:1;font-size:10px}.ok-native-list-visual-overlay img,.ok-native-list-visual-overlay svg{width:100%;height:100%;object-fit:contain}
|
|
897
923
|
.ok-native-list-row.ok-native-list-market-skeleton{padding:12px 20px;gap:0}.ok-native-list-skeleton-left{display:flex;align-items:center;gap:12px;flex:1}.ok-native-list-skeleton-text{display:flex;flex-direction:column;gap:4px}.ok-native-list-skeleton-right{display:flex;align-items:center;gap:8px}.ok-native-list-skeleton-mark{display:block;flex-shrink:0;border-radius:8px;animation:ok-native-list-skeleton 1.5s linear infinite alternate}@keyframes ok-native-list-skeleton{from{background-color:var(--nl-skeleton-base)}to{background-color:var(--nl-skeleton-highlight)}}.ok-native-list-market-spinner{display:block;width:20px;height:20px;flex-shrink:0;color:var(--nl-icon);animation:ok-native-list-spin .75s linear infinite}
|
|
898
924
|
@media (prefers-reduced-motion:reduce){.ok-native-list-index-preview,.ok-native-list-refresh{transition:none}.ok-native-list-spinner,.ok-native-list-market-spinner{animation:none}.ok-native-list-skeleton-mark{animation:none;background:var(--nl-skeleton-base)}}
|
|
925
|
+
.ok-native-list-footer{flex:0 0 auto;min-height:0}.ok-native-list-sticky{position:absolute;z-index:4;left:0;right:0;top:0;pointer-events:auto;box-shadow:0 1px 0 var(--nl-separator)}.ok-native-list-viewport-frame:has(>.ok-native-list-index-rail:not([hidden]))>.ok-native-list-viewport{scrollbar-width:none}.ok-native-list-viewport-frame:has(>.ok-native-list-index-rail:not([hidden]))>.ok-native-list-viewport::-webkit-scrollbar{display:none}.ok-native-list-index-rail{position:absolute;z-index:6;top:0;right:0;bottom:0;width:${SECTION_INDEX_RAIL_WIDTH}px;touch-action:none;cursor:pointer}.ok-native-list-index-rail[hidden]{display:none}.ok-native-list-index-button{appearance:none;position:absolute;left:15px;display:flex;width:14px;height:14px;align-items:center;justify-content:center;padding:0;transform:translateY(-50%);border:0;border-radius:7px;background:transparent;color:var(--nl-disabled);font-family:inherit;font-size:10px;font-weight:400;line-height:1;cursor:pointer}.ok-native-list-index-button[data-active="true"]{background:var(--nl-positive);color:var(--nl-inverse-text);font-weight:500}.ok-native-list-index-button:focus-visible{outline:2px solid var(--nl-positive);outline-offset:1px}
|
|
926
|
+
.ok-native-list-refresh{position:absolute;z-index:7;left:50%;top:8px;display:flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;background:var(--nl-inverse);color:var(--nl-inverse-text);font-size:12px;opacity:0;transform:translate(-50%,-16px);transition:opacity .15s ease,transform .15s ease;pointer-events:none}.ok-native-list-refresh[data-visible="true"]{opacity:1;transform:translate(-50%,0)}
|
|
927
|
+
.ok-native-list-warning{height:auto;display:flex;flex-direction:column;align-items:stretch;gap:4px;padding:14px 12px;border-top:1px solid;border-bottom:1px solid;box-sizing:border-box;cursor:default}.ok-native-list-warning-title,.ok-native-list-warning-message{font-size:14px;line-height:20px;white-space:normal;overflow-wrap:anywhere}.ok-native-list-warning-title{font-weight:500;color:var(--nl-primary)}.ok-native-list-warning-message{font-weight:400;color:var(--nl-secondary)}
|
|
928
|
+
.ok-native-list-subtitle-segments{display:flex;align-items:center;min-width:0;max-width:100%;height:20px}.ok-native-list-subtitle-segments>.ok-native-list-secondary{flex:0 1 auto;min-width:0}.ok-native-list-subtitle-dot{flex:0 0 4px;width:4px;height:4px;margin:0 6px;border-radius:50%;background:var(--nl-disabled)}.ok-native-list-wallet-row>.ok-native-list-flex{flex:0 1 auto;width:100%;align-items:center}.ok-native-list-wallet-badges{display:flex;gap:4px;justify-content:center;margin-top:4px;height:20px;max-width:100%}.ok-native-list-wallet-badges>.ok-native-list-badge{background:var(--nl-strong);color:var(--nl-secondary);font-size:12px;line-height:16px;height:20px;box-sizing:border-box;padding:2px 4px}.ok-native-list-visual-overlay{position:absolute;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border-radius:50%;overflow:hidden;line-height:1;font-size:10px}.ok-native-list-visual-overlay img,.ok-native-list-visual-overlay svg{width:100%;height:100%;object-fit:contain}
|
|
929
|
+
@media (prefers-reduced-motion:reduce){.ok-native-list-refresh{transition:none}.ok-native-list-spinner{animation:none}}
|
|
899
930
|
/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
900
931
|
.ok-native-list-checkbox[data-selector="networkSelector"]{padding:0;border-radius:4px;border-color:var(--nl-checkbox-border,var(--nl-separator));background:var(--nl-checkbox-icon,var(--nl-inverse-text))}
|
|
901
932
|
.ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
|
|
@@ -3100,7 +3131,8 @@ function createMarketRow(context: RenderContext, row: MarketRow): HTMLElement {
|
|
|
3100
3131
|
visual.style.height = String(height) + 'px';
|
|
3101
3132
|
visual.style.flexBasis = String(width) + 'px';
|
|
3102
3133
|
visual.style.borderRadius = String(layoutStyle.imageCornerRadius) + 'px';
|
|
3103
|
-
const borderColor =
|
|
3134
|
+
const borderColor =
|
|
3135
|
+
'borderColor' in row.leading ? row.leading.borderColor : undefined;
|
|
3104
3136
|
if (borderColor) {
|
|
3105
3137
|
visual.style.border = '1px solid ' + borderColor;
|
|
3106
3138
|
visual.style.boxSizing = 'border-box';
|
|
@@ -3111,7 +3143,8 @@ function createMarketRow(context: RenderContext, row: MarketRow): HTMLElement {
|
|
|
3111
3143
|
image.style.height = '100%';
|
|
3112
3144
|
if (borderColor) {
|
|
3113
3145
|
image.style.borderRadius = '0';
|
|
3114
|
-
image.style.clipPath =
|
|
3146
|
+
image.style.clipPath =
|
|
3147
|
+
'inset(-1px round ' + String(layoutStyle.imageCornerRadius) + 'px)';
|
|
3115
3148
|
}
|
|
3116
3149
|
image.style.objectFit =
|
|
3117
3150
|
style?.image?.contentFit ?? image.style.objectFit;
|
|
@@ -3277,7 +3310,6 @@ export class NativeListWebEngine {
|
|
|
3277
3310
|
private readonly footer: HTMLElement;
|
|
3278
3311
|
private readonly sticky: HTMLElement;
|
|
3279
3312
|
private readonly indexRail: HTMLElement;
|
|
3280
|
-
private readonly indexPreview: HTMLElement;
|
|
3281
3313
|
private readonly refreshIndicator: HTMLElement;
|
|
3282
3314
|
private readonly reorderPreview: HTMLElement;
|
|
3283
3315
|
private readonly previousHostPosition: string;
|
|
@@ -3303,7 +3335,6 @@ export class NativeListWebEngine {
|
|
|
3303
3335
|
private avatarDirection = 1;
|
|
3304
3336
|
private reachedGeneration: number | undefined;
|
|
3305
3337
|
private stickyKey: string | undefined;
|
|
3306
|
-
private previewTimer: number | undefined;
|
|
3307
3338
|
private sectionIndexEntries: readonly Readonly<{
|
|
3308
3339
|
key: string;
|
|
3309
3340
|
title: string;
|
|
@@ -3392,12 +3423,6 @@ export class NativeListWebEngine {
|
|
|
3392
3423
|
this.indexRail.setAttribute('role', 'navigation');
|
|
3393
3424
|
this.indexRail.setAttribute('aria-label', 'Section index');
|
|
3394
3425
|
this.indexRail.hidden = true;
|
|
3395
|
-
this.indexPreview = createElement(
|
|
3396
|
-
this.document,
|
|
3397
|
-
'div',
|
|
3398
|
-
'ok-native-list-index-preview'
|
|
3399
|
-
);
|
|
3400
|
-
this.indexPreview.setAttribute('aria-live', 'polite');
|
|
3401
3426
|
this.refreshIndicator = createElement(
|
|
3402
3427
|
this.document,
|
|
3403
3428
|
'div',
|
|
@@ -3418,7 +3443,6 @@ export class NativeListWebEngine {
|
|
|
3418
3443
|
this.viewport,
|
|
3419
3444
|
this.sticky,
|
|
3420
3445
|
this.indexRail,
|
|
3421
|
-
this.indexPreview,
|
|
3422
3446
|
this.refreshIndicator
|
|
3423
3447
|
);
|
|
3424
3448
|
this.root.append(style, this.viewportFrame, this.footer);
|
|
@@ -3427,6 +3451,10 @@ export class NativeListWebEngine {
|
|
|
3427
3451
|
this.viewport.addEventListener('scroll', this.handleScroll, {
|
|
3428
3452
|
passive: true,
|
|
3429
3453
|
});
|
|
3454
|
+
this.viewport.addEventListener(
|
|
3455
|
+
'ok-collapsible-pager-insets-changed',
|
|
3456
|
+
this.handleCollapsiblePagerInsetsChanged
|
|
3457
|
+
);
|
|
3430
3458
|
this.root.addEventListener('click', this.handleClick);
|
|
3431
3459
|
this.root.addEventListener('pointerdown', this.handleMarketPointerDown);
|
|
3432
3460
|
this.root.addEventListener('pointermove', this.handleMarketPointerMove);
|
|
@@ -3463,6 +3491,11 @@ export class NativeListWebEngine {
|
|
|
3463
3491
|
);
|
|
3464
3492
|
this.indexRail.addEventListener('pointerdown', this.handleIndexPointer);
|
|
3465
3493
|
this.indexRail.addEventListener('pointermove', this.handleIndexPointer);
|
|
3494
|
+
this.indexRail.addEventListener('pointerup', this.handleIndexPointerEnd);
|
|
3495
|
+
this.indexRail.addEventListener(
|
|
3496
|
+
'pointercancel',
|
|
3497
|
+
this.handleIndexPointerEnd
|
|
3498
|
+
);
|
|
3466
3499
|
this.indexRail.addEventListener('click', this.handleIndexClick);
|
|
3467
3500
|
this.viewport.addEventListener('pointerdown', this.handlePullStart, {
|
|
3468
3501
|
passive: true,
|
|
@@ -3664,8 +3697,6 @@ export class NativeListWebEngine {
|
|
|
3664
3697
|
this.invalidateActionAnchor('destroy');
|
|
3665
3698
|
this.destroyed = true;
|
|
3666
3699
|
if (this.frameHandle !== undefined) this.cancelFrame(this.frameHandle);
|
|
3667
|
-
if (this.previewTimer !== undefined)
|
|
3668
|
-
this.document.defaultView?.clearTimeout(this.previewTimer);
|
|
3669
3700
|
if (this.reorderMovementTimer !== undefined)
|
|
3670
3701
|
this.document.defaultView?.clearTimeout(this.reorderMovementTimer);
|
|
3671
3702
|
this.resizeObserver?.disconnect();
|
|
@@ -3674,6 +3705,10 @@ export class NativeListWebEngine {
|
|
|
3674
3705
|
this.handleWindowResize
|
|
3675
3706
|
);
|
|
3676
3707
|
this.viewport.removeEventListener('scroll', this.handleScroll);
|
|
3708
|
+
this.viewport.removeEventListener(
|
|
3709
|
+
'ok-collapsible-pager-insets-changed',
|
|
3710
|
+
this.handleCollapsiblePagerInsetsChanged
|
|
3711
|
+
);
|
|
3677
3712
|
this.root.removeEventListener('click', this.handleClick);
|
|
3678
3713
|
this.cancelMarketPointer();
|
|
3679
3714
|
this.root.removeEventListener('pointerdown', this.handleMarketPointerDown);
|
|
@@ -3708,6 +3743,11 @@ export class NativeListWebEngine {
|
|
|
3708
3743
|
);
|
|
3709
3744
|
this.indexRail.removeEventListener('pointerdown', this.handleIndexPointer);
|
|
3710
3745
|
this.indexRail.removeEventListener('pointermove', this.handleIndexPointer);
|
|
3746
|
+
this.indexRail.removeEventListener('pointerup', this.handleIndexPointerEnd);
|
|
3747
|
+
this.indexRail.removeEventListener(
|
|
3748
|
+
'pointercancel',
|
|
3749
|
+
this.handleIndexPointerEnd
|
|
3750
|
+
);
|
|
3711
3751
|
this.indexRail.removeEventListener('click', this.handleIndexClick);
|
|
3712
3752
|
this.viewport.removeEventListener('pointerdown', this.handlePullStart);
|
|
3713
3753
|
this.viewport.removeEventListener('pointermove', this.handlePullMove);
|
|
@@ -3782,7 +3822,20 @@ export class NativeListWebEngine {
|
|
|
3782
3822
|
private recomputeLayout = () => {
|
|
3783
3823
|
if (this.destroyed) return;
|
|
3784
3824
|
const viewportWidth = this.viewport.clientWidth;
|
|
3785
|
-
const viewportHeight =
|
|
3825
|
+
const viewportHeight =
|
|
3826
|
+
this.snapshot.layout.orientation === 'horizontal'
|
|
3827
|
+
? this.viewport.clientHeight
|
|
3828
|
+
: this.verticalScrollMetrics().viewportLength;
|
|
3829
|
+
if (this.snapshot.layout.orientation !== 'horizontal') {
|
|
3830
|
+
const stickyInset = this.collapsiblePagerInsets().sticky;
|
|
3831
|
+
this.sticky.style.top = String(stickyInset) + 'px';
|
|
3832
|
+
this.indexRail.style.top = String(stickyInset) + 'px';
|
|
3833
|
+
this.refreshIndicator.style.top = String(stickyInset + 8) + 'px';
|
|
3834
|
+
} else {
|
|
3835
|
+
this.sticky.style.top = '0px';
|
|
3836
|
+
this.indexRail.style.top = '0px';
|
|
3837
|
+
this.refreshIndicator.style.top = '8px';
|
|
3838
|
+
}
|
|
3786
3839
|
if (
|
|
3787
3840
|
this.lastViewportWidth >= 0 &&
|
|
3788
3841
|
(viewportWidth !== this.lastViewportWidth ||
|
|
@@ -3813,7 +3866,11 @@ export class NativeListWebEngine {
|
|
|
3813
3866
|
);
|
|
3814
3867
|
this.content.style.width = String(this.layout.contentWidth) + 'px';
|
|
3815
3868
|
this.content.style.height = String(this.layout.contentHeight) + 'px';
|
|
3816
|
-
this.renderSectionIndex(
|
|
3869
|
+
this.renderSectionIndex(
|
|
3870
|
+
this.viewport.clientHeight <= 0
|
|
3871
|
+
? DEFAULT_VIEWPORT_HEIGHT
|
|
3872
|
+
: Math.max(1, viewportHeight)
|
|
3873
|
+
);
|
|
3817
3874
|
if (previousHorizontal !== this.layout.horizontal) {
|
|
3818
3875
|
this.viewport.scrollLeft = 0;
|
|
3819
3876
|
this.viewport.scrollTop = 0;
|
|
@@ -4121,17 +4178,15 @@ export class NativeListWebEngine {
|
|
|
4121
4178
|
): readonly number[] {
|
|
4122
4179
|
const entryCount = this.sectionIndexEntries.length;
|
|
4123
4180
|
if (entryCount <= 1) return entryCount ? [0] : [];
|
|
4124
|
-
const
|
|
4125
|
-
0,
|
|
4126
|
-
viewportHeight - SECTION_INDEX_EDGE_PADDING * 2
|
|
4127
|
-
);
|
|
4181
|
+
const { trackHeight } = this.sectionIndexMetrics(viewportHeight);
|
|
4128
4182
|
const maxVisible = Math.max(
|
|
4129
|
-
|
|
4130
|
-
Math.floor(
|
|
4183
|
+
1,
|
|
4184
|
+
Math.floor(trackHeight / SECTION_INDEX_LABEL_SPACING)
|
|
4131
4185
|
);
|
|
4132
4186
|
if (entryCount <= maxVisible) {
|
|
4133
4187
|
return Array.from({ length: entryCount }, (_, index) => index);
|
|
4134
4188
|
}
|
|
4189
|
+
if (maxVisible === 1) return [0];
|
|
4135
4190
|
const result = new Set<number>();
|
|
4136
4191
|
for (let slot = 0; slot < maxVisible; slot += 1) {
|
|
4137
4192
|
result.add(Math.round((slot * (entryCount - 1)) / (maxVisible - 1)));
|
|
@@ -4139,6 +4194,21 @@ export class NativeListWebEngine {
|
|
|
4139
4194
|
return [...result].sort((left, right) => left - right);
|
|
4140
4195
|
}
|
|
4141
4196
|
|
|
4197
|
+
private sectionIndexMetrics(viewportHeight: number) {
|
|
4198
|
+
const availableHeight = Math.max(
|
|
4199
|
+
0,
|
|
4200
|
+
viewportHeight - SECTION_INDEX_EDGE_PADDING * 2
|
|
4201
|
+
);
|
|
4202
|
+
const trackHeight = Math.min(
|
|
4203
|
+
availableHeight,
|
|
4204
|
+
SECTION_INDEX_LABEL_SPACING * this.sectionIndexEntries.length
|
|
4205
|
+
);
|
|
4206
|
+
return {
|
|
4207
|
+
originY: (viewportHeight - trackHeight) / 2,
|
|
4208
|
+
trackHeight,
|
|
4209
|
+
};
|
|
4210
|
+
}
|
|
4211
|
+
|
|
4142
4212
|
private renderSectionIndex(viewportHeight: number) {
|
|
4143
4213
|
this.indexRail.replaceChildren();
|
|
4144
4214
|
if (!sectionIndexEnabled(this.snapshot)) {
|
|
@@ -4165,8 +4235,15 @@ export class NativeListWebEngine {
|
|
|
4165
4235
|
'compact',
|
|
4166
4236
|
visibleEntryIndices.length < this.sectionIndexEntries.length
|
|
4167
4237
|
);
|
|
4238
|
+
const metrics = this.sectionIndexMetrics(viewportHeight);
|
|
4239
|
+
const visibleTrackHeight = Math.min(
|
|
4240
|
+
metrics.trackHeight,
|
|
4241
|
+
SECTION_INDEX_LABEL_SPACING * visibleEntryIndices.length
|
|
4242
|
+
);
|
|
4243
|
+
const visibleOriginY =
|
|
4244
|
+
metrics.originY + (metrics.trackHeight - visibleTrackHeight) / 2;
|
|
4168
4245
|
const fragment = this.document.createDocumentFragment();
|
|
4169
|
-
visibleEntryIndices.forEach((entryIndex) => {
|
|
4246
|
+
visibleEntryIndices.forEach((entryIndex, visibleIndex) => {
|
|
4170
4247
|
const entry = this.sectionIndexEntries[entryIndex];
|
|
4171
4248
|
if (!entry) return;
|
|
4172
4249
|
const button = createElement(
|
|
@@ -4180,14 +4257,11 @@ export class NativeListWebEngine {
|
|
|
4180
4257
|
setData(button, 'sectionEntryIndex', entryIndex);
|
|
4181
4258
|
setData(button, 'sectionPosition', entry.position);
|
|
4182
4259
|
setData(button, 'sectionKey', entry.key);
|
|
4183
|
-
const progress =
|
|
4184
|
-
this.sectionIndexEntries.length === 1
|
|
4185
|
-
? 0.5
|
|
4186
|
-
: entryIndex / (this.sectionIndexEntries.length - 1);
|
|
4187
4260
|
button.style.top =
|
|
4188
4261
|
String(
|
|
4189
|
-
|
|
4190
|
-
|
|
4262
|
+
visibleOriginY +
|
|
4263
|
+
(visibleTrackHeight * (visibleIndex + 0.5)) /
|
|
4264
|
+
visibleEntryIndices.length
|
|
4191
4265
|
) + 'px';
|
|
4192
4266
|
fragment.appendChild(button);
|
|
4193
4267
|
});
|
|
@@ -4323,7 +4397,7 @@ export class NativeListWebEngine {
|
|
|
4323
4397
|
}
|
|
4324
4398
|
const next = this.layout.items[nextIndex];
|
|
4325
4399
|
const translate = next
|
|
4326
|
-
? Math.min(0, next.y - this.
|
|
4400
|
+
? Math.min(0, next.y - this.currentOffset() - item.height)
|
|
4327
4401
|
: 0;
|
|
4328
4402
|
this.sticky.style.transform =
|
|
4329
4403
|
'translate3d(0,' + String(translate) + 'px,0)';
|
|
@@ -4399,9 +4473,11 @@ export class NativeListWebEngine {
|
|
|
4399
4473
|
}
|
|
4400
4474
|
|
|
4401
4475
|
private viewportLength(): number {
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4476
|
+
if (this.layout.horizontal) {
|
|
4477
|
+
return this.viewport.clientWidth || DEFAULT_VIEWPORT_WIDTH;
|
|
4478
|
+
}
|
|
4479
|
+
if (this.viewport.clientHeight <= 0) return DEFAULT_VIEWPORT_HEIGHT;
|
|
4480
|
+
return Math.max(1, this.verticalScrollMetrics().viewportLength);
|
|
4405
4481
|
}
|
|
4406
4482
|
|
|
4407
4483
|
private contentLength(): number {
|
|
@@ -4413,18 +4489,54 @@ export class NativeListWebEngine {
|
|
|
4413
4489
|
private currentOffset(): number {
|
|
4414
4490
|
return this.layout.horizontal
|
|
4415
4491
|
? this.viewport.scrollLeft
|
|
4416
|
-
: this.
|
|
4492
|
+
: this.verticalScrollMetrics().offset;
|
|
4493
|
+
}
|
|
4494
|
+
|
|
4495
|
+
private collapsiblePagerInsets(): Readonly<{
|
|
4496
|
+
header: number;
|
|
4497
|
+
sticky: number;
|
|
4498
|
+
}> {
|
|
4499
|
+
const readInset = (name: string) => {
|
|
4500
|
+
const parsed = Number.parseFloat(
|
|
4501
|
+
this.viewport.style.getPropertyValue(name)
|
|
4502
|
+
);
|
|
4503
|
+
return Number.isFinite(parsed) ? Math.max(0, parsed) : 0;
|
|
4504
|
+
};
|
|
4505
|
+
return {
|
|
4506
|
+
header: readInset('--ok-collapsible-pager-header-inset'),
|
|
4507
|
+
sticky: readInset('--ok-collapsible-pager-sticky-inset'),
|
|
4508
|
+
};
|
|
4417
4509
|
}
|
|
4418
4510
|
|
|
4511
|
+
private verticalScrollMetrics(): WebCollapsiblePagerScrollMetrics {
|
|
4512
|
+
const insets = this.collapsiblePagerInsets();
|
|
4513
|
+
return resolveWebCollapsiblePagerScrollMetrics(
|
|
4514
|
+
this.viewport.scrollTop,
|
|
4515
|
+
this.viewport.clientHeight,
|
|
4516
|
+
insets.header,
|
|
4517
|
+
insets.sticky
|
|
4518
|
+
);
|
|
4519
|
+
}
|
|
4520
|
+
|
|
4521
|
+
private handleCollapsiblePagerInsetsChanged = () => {
|
|
4522
|
+
this.recomputeLayout();
|
|
4523
|
+
};
|
|
4524
|
+
|
|
4419
4525
|
private scrollToAbsoluteOffset(offset: number, animated: boolean) {
|
|
4420
4526
|
const resolved = Math.min(
|
|
4421
4527
|
Math.max(0, offset),
|
|
4422
4528
|
Math.max(0, this.contentLength() - this.viewportLength())
|
|
4423
4529
|
);
|
|
4530
|
+
const rawOffset = this.layout.horizontal
|
|
4531
|
+
? resolved
|
|
4532
|
+
: resolveWebCollapsiblePagerRawOffset(
|
|
4533
|
+
resolved,
|
|
4534
|
+
this.collapsiblePagerInsets().header
|
|
4535
|
+
);
|
|
4424
4536
|
this.viewport.scrollTo(
|
|
4425
4537
|
this.layout.horizontal
|
|
4426
|
-
? { left:
|
|
4427
|
-
: { left: 0, top:
|
|
4538
|
+
? { left: rawOffset, top: 0, behavior: animated ? 'smooth' : 'auto' }
|
|
4539
|
+
: { left: 0, top: rawOffset, behavior: animated ? 'smooth' : 'auto' }
|
|
4428
4540
|
);
|
|
4429
4541
|
this.scheduleFrame();
|
|
4430
4542
|
}
|
|
@@ -4949,78 +5061,62 @@ export class NativeListWebEngine {
|
|
|
4949
5061
|
else view?.clearTimeout(handle);
|
|
4950
5062
|
}
|
|
4951
5063
|
|
|
4952
|
-
private selectIndexPosition(
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
5064
|
+
private selectIndexPosition(position: number) {
|
|
5065
|
+
const activeKey = this.sectionIndexEntries.find(
|
|
5066
|
+
(entry) => entry.position === position
|
|
5067
|
+
)?.key;
|
|
5068
|
+
this.indexRail
|
|
5069
|
+
.querySelectorAll<HTMLElement>('[data-section-key]')
|
|
5070
|
+
.forEach((button) =>
|
|
5071
|
+
setData(button, 'active', button.dataset.sectionKey === activeKey)
|
|
5072
|
+
);
|
|
4957
5073
|
this.scrollToIndex(position, {
|
|
4958
5074
|
animated: false,
|
|
4959
5075
|
alignment: 'start',
|
|
4960
5076
|
viewPosition: 0,
|
|
4961
5077
|
viewOffset: 0,
|
|
4962
5078
|
});
|
|
4963
|
-
const frame = this.viewportFrame.getBoundingClientRect();
|
|
4964
|
-
if (previewClientY !== undefined && frame.height > 0) {
|
|
4965
|
-
const previewY = Math.min(
|
|
4966
|
-
frame.height - 24,
|
|
4967
|
-
Math.max(24, previewClientY - frame.top)
|
|
4968
|
-
);
|
|
4969
|
-
this.indexPreview.style.top = String(previewY) + 'px';
|
|
4970
|
-
} else {
|
|
4971
|
-
this.indexPreview.style.top = '50%';
|
|
4972
|
-
}
|
|
4973
|
-
this.indexPreview.textContent = title;
|
|
4974
|
-
setData(this.indexPreview, 'visible', true);
|
|
4975
|
-
if (this.previewTimer !== undefined)
|
|
4976
|
-
this.document.defaultView?.clearTimeout(this.previewTimer);
|
|
4977
|
-
this.previewTimer = this.document.defaultView?.setTimeout(() => {
|
|
4978
|
-
setData(this.indexPreview, 'visible', false);
|
|
4979
|
-
}, 180);
|
|
4980
5079
|
}
|
|
4981
5080
|
|
|
4982
|
-
private sectionIndexEntryAtEvent(
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
previewClientY: number;
|
|
4986
|
-
}>
|
|
4987
|
-
| undefined {
|
|
5081
|
+
private sectionIndexEntryAtEvent(
|
|
5082
|
+
event: PointerEvent
|
|
5083
|
+
): NativeListWebEngine['sectionIndexEntries'][number] | undefined {
|
|
4988
5084
|
const rail = this.indexRail.getBoundingClientRect();
|
|
4989
5085
|
if (this.sectionIndexEntries.length === 0 || rail.height <= 0) {
|
|
4990
5086
|
return undefined;
|
|
4991
5087
|
}
|
|
4992
|
-
const
|
|
4993
|
-
|
|
4994
|
-
rail.height - SECTION_INDEX_EDGE_PADDING * 2
|
|
4995
|
-
);
|
|
5088
|
+
const metrics = this.sectionIndexMetrics(rail.height);
|
|
5089
|
+
if (metrics.trackHeight <= 0) return undefined;
|
|
4996
5090
|
const progress = Math.min(
|
|
4997
5091
|
1,
|
|
4998
5092
|
Math.max(
|
|
4999
5093
|
0,
|
|
5000
|
-
(event.clientY - rail.top -
|
|
5001
|
-
availableHeight
|
|
5094
|
+
(event.clientY - rail.top - metrics.originY) / metrics.trackHeight
|
|
5002
5095
|
)
|
|
5003
5096
|
);
|
|
5004
|
-
const entryIndex = Math.
|
|
5005
|
-
|
|
5097
|
+
const entryIndex = Math.min(
|
|
5098
|
+
this.sectionIndexEntries.length - 1,
|
|
5099
|
+
Math.floor(progress * this.sectionIndexEntries.length)
|
|
5006
5100
|
);
|
|
5007
|
-
|
|
5008
|
-
return entry ? { entry, previewClientY: event.clientY } : undefined;
|
|
5101
|
+
return this.sectionIndexEntries[entryIndex];
|
|
5009
5102
|
}
|
|
5010
5103
|
|
|
5011
5104
|
private handleIndexPointer = (event: PointerEvent) => {
|
|
5012
5105
|
if (event.type === 'pointermove' && event.buttons === 0) return;
|
|
5013
|
-
const
|
|
5014
|
-
if (!
|
|
5106
|
+
const entry = this.sectionIndexEntryAtEvent(event);
|
|
5107
|
+
if (!entry) return;
|
|
5015
5108
|
event.preventDefault();
|
|
5016
5109
|
if (event.type === 'pointerdown') {
|
|
5017
5110
|
this.indexRail.setPointerCapture?.(event.pointerId);
|
|
5018
5111
|
}
|
|
5019
|
-
this.selectIndexPosition(
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
)
|
|
5112
|
+
this.selectIndexPosition(entry.position);
|
|
5113
|
+
};
|
|
5114
|
+
|
|
5115
|
+
private handleIndexPointerEnd = (event: PointerEvent) => {
|
|
5116
|
+
if (event.type === 'pointerup') {
|
|
5117
|
+
const entry = this.sectionIndexEntryAtEvent(event);
|
|
5118
|
+
if (entry) this.selectIndexPosition(entry.position);
|
|
5119
|
+
}
|
|
5024
5120
|
};
|
|
5025
5121
|
|
|
5026
5122
|
private handleIndexClick = (event: Event) => {
|
|
@@ -5037,12 +5133,7 @@ export class NativeListWebEngine {
|
|
|
5037
5133
|
const entry =
|
|
5038
5134
|
this.sectionIndexEntries[Number(button.dataset.sectionEntryIndex)];
|
|
5039
5135
|
if (!entry) return;
|
|
5040
|
-
|
|
5041
|
-
this.selectIndexPosition(
|
|
5042
|
-
entry.position,
|
|
5043
|
-
entry.title,
|
|
5044
|
-
rect.top + rect.height / 2
|
|
5045
|
-
);
|
|
5136
|
+
this.selectIndexPosition(entry.position);
|
|
5046
5137
|
};
|
|
5047
5138
|
|
|
5048
5139
|
private handlePullStart = (event: PointerEvent) => {
|
|
@@ -5245,7 +5336,12 @@ export class NativeListWebEngine {
|
|
|
5245
5336
|
const maximum = Math.max(0, this.contentLength() - this.viewportLength());
|
|
5246
5337
|
const next = Math.max(0, Math.min(maximum, offset));
|
|
5247
5338
|
if (this.layout.horizontal) this.viewport.scrollLeft = next;
|
|
5248
|
-
else
|
|
5339
|
+
else {
|
|
5340
|
+
this.viewport.scrollTop = resolveWebCollapsiblePagerRawOffset(
|
|
5341
|
+
next,
|
|
5342
|
+
this.collapsiblePagerInsets().header
|
|
5343
|
+
);
|
|
5344
|
+
}
|
|
5249
5345
|
this.scheduleFrame();
|
|
5250
5346
|
}
|
|
5251
5347
|
|
|
@@ -5327,10 +5423,15 @@ export class NativeListWebEngine {
|
|
|
5327
5423
|
}
|
|
5328
5424
|
this.reorderSettlingKey = state.sourceKey;
|
|
5329
5425
|
const viewportRect = this.viewport.getBoundingClientRect();
|
|
5426
|
+
const insets = this.collapsiblePagerInsets();
|
|
5330
5427
|
const left =
|
|
5331
5428
|
viewportRect.left + destinationLayout.x - this.viewport.scrollLeft;
|
|
5332
5429
|
const top =
|
|
5333
|
-
viewportRect.top +
|
|
5430
|
+
viewportRect.top +
|
|
5431
|
+
destinationLayout.y +
|
|
5432
|
+
insets.header +
|
|
5433
|
+
insets.sticky -
|
|
5434
|
+
this.viewport.scrollTop;
|
|
5334
5435
|
this.reorderPreview.getBoundingClientRect();
|
|
5335
5436
|
this.reorderPreview.style.transition =
|
|
5336
5437
|
'transform ' +
|