@onekeyfe/react-native-native-list 3.0.157-alpha.249 → 3.0.157-alpha.251
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/README.md +21 -5
- package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +711 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActionRenderer.kt +169 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +243 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +20 -6
- package/android/src/main/java/com/onekey/nativelist/NativeListDataRowRenderer.kt +487 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListIdentityRenderer.kt +820 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListImageSlot.kt +147 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +453 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMarketRenderer.kt +997 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMediaTileRenderer.kt +234 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMessageRenderer.kt +232 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMetricCardRenderer.kt +551 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +24 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +475 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRailRenderer.kt +143 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRegistry.kt +42 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +415 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListResolvedText.kt +163 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowHost.kt +70 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +748 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSystemRenderer.kt +464 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListTextView.kt +25 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +174 -104
- package/android/src/main/java/com/onekey/nativelist/NativeListWalletGroupRenderer.kt +407 -0
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListSelectorBackgroundColorTest.kt +34 -0
- package/docs/DESIGN.md +518 -9
- package/docs/MIGRATION_BASELINE.md +117 -0
- package/docs/ROW_TEMPLATES.md +359 -0
- package/docs/SPEC.md +358 -0
- package/docs/STYLE_SPEC.md +978 -0
- package/docs/images/list-capabilities.svg +39 -0
- package/docs/images/row-action.svg +17 -0
- package/docs/images/row-activity.svg +24 -0
- package/docs/images/row-data.svg +24 -0
- package/docs/images/row-identity.svg +25 -0
- package/docs/images/row-market.svg +23 -0
- package/docs/images/row-media-tile.svg +26 -0
- package/docs/images/row-message.svg +20 -0
- package/docs/images/row-metric-card.svg +33 -0
- package/docs/images/row-rail.svg +18 -0
- package/docs/images/row-section-header.svg +19 -0
- package/docs/images/row-style-regions.svg +30 -0
- package/docs/images/row-system.svg +30 -0
- package/docs/images/row-wallet-group.svg +26 -0
- package/ios/NativeListAccessoryStack.swift +680 -0
- package/ios/NativeListActionRenderer.swift +108 -0
- package/ios/NativeListActivityRenderer.swift +179 -0
- package/ios/NativeListDataRowRenderer.swift +444 -0
- package/ios/NativeListIdentityRenderer.swift +685 -0
- package/ios/NativeListImageSlot.swift +140 -0
- package/ios/NativeListLeadingVisual.swift +372 -0
- package/ios/NativeListMarketRenderer.swift +698 -0
- package/ios/NativeListMediaTileRenderer.swift +184 -0
- package/ios/NativeListMessageRenderer.swift +168 -0
- package/ios/NativeListMetricCardRenderer.swift +420 -0
- package/ios/NativeListModels.swift +32 -0
- package/ios/NativeListRailRenderer.swift +152 -0
- package/ios/NativeListRendererCell.swift +311 -0
- package/ios/NativeListRendererRegistry.swift +50 -0
- package/ios/NativeListResolvedText.swift +122 -0
- package/ios/NativeListRowHost.swift +63 -0
- package/ios/NativeListSectionHeaderRenderer.swift +708 -0
- package/ios/NativeListSystemRenderer.swift +568 -0
- package/ios/NativeListTextLabel.swift +42 -0
- package/ios/NativeListTextStyles.swift +236 -0
- package/ios/NativeListWalletGroupRenderer.swift +255 -0
- package/ios/RNCNativeListView.swift +111 -180
- package/lib/module/models.js +54 -0
- package/lib/module/validation.js +324 -26
- package/lib/module/web/NativeListWebEngine.js +148 -936
- package/lib/module/web/templates/ActionRowRenderer.js +97 -0
- package/lib/module/web/templates/ActivityRowRenderer.js +95 -0
- package/lib/module/web/templates/DataRowRenderer.js +145 -0
- package/lib/module/web/templates/IdentityRowRenderer.js +289 -0
- package/lib/module/web/templates/MarketRowRenderer.js +310 -0
- package/lib/module/web/templates/MediaTileRowRenderer.js +132 -0
- package/lib/module/web/templates/MessageRowRenderer.js +165 -0
- package/lib/module/web/templates/MetricCardRowRenderer.js +172 -0
- package/lib/module/web/templates/RailRowRenderer.js +98 -0
- package/lib/module/web/templates/RowContainerStyle.js +100 -0
- package/lib/module/web/templates/RowElements.js +93 -0
- package/lib/module/web/templates/RowRendererRegistry.js +70 -0
- package/lib/module/web/templates/RowText.js +121 -0
- package/lib/module/web/templates/RowVisual.js +43 -0
- package/lib/module/web/templates/SectionHeaderRowRenderer.js +146 -0
- package/lib/module/web/templates/SystemRowRenderer.js +161 -0
- package/lib/module/web/templates/WalletGroupRowRenderer.js +96 -0
- package/lib/typescript/src/models.d.ts +166 -13
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +18 -16
- package/lib/typescript/src/web/templates/ActionRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/ActivityRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/DataRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/IdentityRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/MarketRowRenderer.d.ts +30 -0
- package/lib/typescript/src/web/templates/MediaTileRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/MessageRowRenderer.d.ts +44 -0
- package/lib/typescript/src/web/templates/MetricCardRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/RailRowRenderer.d.ts +28 -0
- package/lib/typescript/src/web/templates/RowContainerStyle.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowElements.d.ts +38 -0
- package/lib/typescript/src/web/templates/RowRendererRegistry.d.ts +83 -0
- package/lib/typescript/src/web/templates/RowText.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowVisual.d.ts +20 -0
- package/lib/typescript/src/web/templates/SectionHeaderRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/SystemRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/WalletGroupRowRenderer.d.ts +20 -0
- package/package.json +3 -3
- package/src/models.ts +281 -19
- package/src/validation.ts +501 -46
- package/src/web/NativeListWebEngine.ts +361 -1932
- package/src/web/templates/ActionRowRenderer.ts +123 -0
- package/src/web/templates/ActivityRowRenderer.ts +159 -0
- package/src/web/templates/DataRowRenderer.ts +212 -0
- package/src/web/templates/IdentityRowRenderer.ts +527 -0
- package/src/web/templates/MarketRowRenderer.ts +467 -0
- package/src/web/templates/MediaTileRowRenderer.ts +182 -0
- package/src/web/templates/MessageRowRenderer.ts +306 -0
- package/src/web/templates/MetricCardRowRenderer.ts +337 -0
- package/src/web/templates/RailRowRenderer.ts +136 -0
- package/src/web/templates/RowContainerStyle.ts +131 -0
- package/src/web/templates/RowElements.ts +160 -0
- package/src/web/templates/RowRendererRegistry.ts +111 -0
- package/src/web/templates/RowText.ts +181 -0
- package/src/web/templates/RowVisual.ts +115 -0
- package/src/web/templates/SectionHeaderRowRenderer.ts +243 -0
- package/src/web/templates/SystemRowRenderer.ts +282 -0
- package/src/web/templates/WalletGroupRowRenderer.ts +131 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +0 -4538
- package/ios/NativeListCell.swift +0 -4300
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyRowContainerStyle,
|
|
3
|
+
resetRowContainerStyle,
|
|
4
|
+
} from './templates/RowContainerStyle';
|
|
5
|
+
import { hasExplicitRowHeight, rowSizeModifier } from './templates/RowElements';
|
|
6
|
+
import { applyTextStyleToSlot, applyValueSegments } from './templates/RowText';
|
|
7
|
+
import { setMarketQuoteContent } from './templates/MarketRowRenderer';
|
|
8
|
+
export {
|
|
9
|
+
resolveWebMarketLayoutStyle,
|
|
10
|
+
type WebMarketLayoutStyle,
|
|
11
|
+
} from './templates/MarketRowRenderer';
|
|
12
|
+
import { measureRailWidth } from './templates/RailRowRenderer';
|
|
13
|
+
import {
|
|
14
|
+
rowRenderer,
|
|
15
|
+
rowRendererKey,
|
|
16
|
+
recycleRowBody,
|
|
17
|
+
type RowRendererKey,
|
|
18
|
+
} from './templates/RowRendererRegistry';
|
|
1
19
|
import type {
|
|
2
20
|
ActionAnchorInvalidatedEvent,
|
|
3
21
|
CheckboxState,
|
|
4
22
|
ImageSource,
|
|
5
23
|
LeadingVisual,
|
|
6
|
-
MarketRow,
|
|
7
|
-
MarketTextStyle,
|
|
8
24
|
NativeListSnapshot,
|
|
9
25
|
NativeListActionAnchor,
|
|
10
26
|
NativeListActionSource,
|
|
@@ -189,49 +205,7 @@ export function webSectionIndexActiveKey(
|
|
|
189
205
|
return activeKey;
|
|
190
206
|
}
|
|
191
207
|
|
|
192
|
-
export type WebMarketLayoutStyle = Readonly<{
|
|
193
|
-
horizontalPadding: number;
|
|
194
|
-
verticalPadding: number;
|
|
195
|
-
leadingGap: number;
|
|
196
|
-
titleBadgeGap: number;
|
|
197
|
-
trailingGap: number;
|
|
198
|
-
imageWidth: number;
|
|
199
|
-
imageHeight: number;
|
|
200
|
-
imageCornerRadius: number;
|
|
201
|
-
changeWidth: number;
|
|
202
|
-
changeHeight: number;
|
|
203
|
-
changeCornerRadius: number;
|
|
204
|
-
}>;
|
|
205
|
-
|
|
206
208
|
/** Resolves every reusable Market geometry field, including legacy defaults. */
|
|
207
|
-
export function resolveWebMarketLayoutStyle(
|
|
208
|
-
row: MarketRow
|
|
209
|
-
): WebMarketLayoutStyle {
|
|
210
|
-
const style = row.style;
|
|
211
|
-
const imageWidth = style?.image?.width ?? (row.variant === 'stock' ? 40 : 32);
|
|
212
|
-
const imageHeight =
|
|
213
|
-
style?.image?.height ?? (row.variant === 'stock' ? 40 : 32);
|
|
214
|
-
return {
|
|
215
|
-
horizontalPadding:
|
|
216
|
-
style?.horizontalPadding ?? (row.variant === 'perp' ? 16 : 20),
|
|
217
|
-
verticalPadding: style?.verticalPadding ?? 12,
|
|
218
|
-
leadingGap: style?.leadingGap ?? (row.variant === 'perp' ? 8 : 14),
|
|
219
|
-
titleBadgeGap: style?.titleBadgeGap ?? 4,
|
|
220
|
-
trailingGap: style?.trailingGap ?? 8,
|
|
221
|
-
imageWidth,
|
|
222
|
-
imageHeight,
|
|
223
|
-
imageCornerRadius:
|
|
224
|
-
style?.image?.cornerRadius ??
|
|
225
|
-
(style?.image?.shape === 'square'
|
|
226
|
-
? 0
|
|
227
|
-
: style?.image?.shape === 'rounded'
|
|
228
|
-
? 8
|
|
229
|
-
: Math.min(imageWidth, imageHeight) / 2),
|
|
230
|
-
changeWidth: style?.changeWidth ?? 80,
|
|
231
|
-
changeHeight: style?.changeHeight ?? 32,
|
|
232
|
-
changeCornerRadius: style?.changeCornerRadius ?? 8,
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
209
|
|
|
236
210
|
export type NativeListWebCallbacks = Readonly<{
|
|
237
211
|
onRowAction?: (event: RowActionEvent) => void;
|
|
@@ -460,28 +434,7 @@ function sizeModifier(row: RowModel): number {
|
|
|
460
434
|
(row.variant === 'summary' || row.variant === 'gallery')
|
|
461
435
|
)
|
|
462
436
|
return 0;
|
|
463
|
-
|
|
464
|
-
if (row.size === 'large') return 12;
|
|
465
|
-
return 0;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
function approximateMessageHeight(row: RowModel, availableWidth: number) {
|
|
469
|
-
if (row.type !== 'message') return 0;
|
|
470
|
-
const leadingWidth = row.leading ? 52 : 0;
|
|
471
|
-
const thumbnailWidth = row.thumbnail ? 88 : 0;
|
|
472
|
-
const charactersPerLine = Math.max(
|
|
473
|
-
18,
|
|
474
|
-
Math.floor((availableWidth - leadingWidth - thumbnailWidth - 40) / 7)
|
|
475
|
-
);
|
|
476
|
-
const titleLines = Math.min(
|
|
477
|
-
2,
|
|
478
|
-
Math.max(1, Math.ceil(row.title.length / charactersPerLine))
|
|
479
|
-
);
|
|
480
|
-
const bodyLines = Math.min(
|
|
481
|
-
row.bodyLines ?? 3,
|
|
482
|
-
Math.max(1, Math.ceil(row.body.length / charactersPerLine))
|
|
483
|
-
);
|
|
484
|
-
return 32 + titleLines * 20 + bodyLines * 20 + 22;
|
|
437
|
+
return rowSizeModifier(row.size);
|
|
485
438
|
}
|
|
486
439
|
|
|
487
440
|
export function estimateWebRowHeight(
|
|
@@ -489,145 +442,21 @@ export function estimateWebRowHeight(
|
|
|
489
442
|
snapshot: NativeListSnapshot,
|
|
490
443
|
availableWidth: number
|
|
491
444
|
): number {
|
|
492
|
-
//
|
|
493
|
-
|
|
494
|
-
if (
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
Array.from(text).reduce(
|
|
502
|
-
(length, char) => length + (char.charCodeAt(0) > 255 ? 14 : 7),
|
|
503
|
-
0
|
|
504
|
-
) / width
|
|
505
|
-
)
|
|
506
|
-
);
|
|
507
|
-
return 32 + 20 * (lines(row.title) + lines(row.message));
|
|
508
|
-
}
|
|
509
|
-
if (row.type === 'walletGroup')
|
|
510
|
-
// OneKey patch: wallet badges participate in the outer group height.
|
|
511
|
-
// return (row.children.length + 1) * 68 + row.children.length * 12;
|
|
512
|
-
return (
|
|
513
|
-
[row.parent, ...row.children].reduce(
|
|
514
|
-
(height, member) =>
|
|
515
|
-
height + estimateWebRowHeight(member, snapshot, availableWidth),
|
|
516
|
-
0
|
|
517
|
-
) +
|
|
518
|
-
row.children.length * 12 +
|
|
519
|
-
(row.parent.height !== undefined ? 2 : 0)
|
|
520
|
-
);
|
|
521
|
-
// OneKey patch: reserve the source badge line below wallet names.
|
|
522
|
-
// if (row.type === 'identity' && row.presentation === 'walletSidebar')
|
|
523
|
-
// return 68;
|
|
524
|
-
if (row.type === 'identity' && row.presentation === 'walletSidebar')
|
|
525
|
-
return 68 + (row.badges?.length ? 24 : 0);
|
|
526
|
-
if (row.type === 'identity' && row.presentation === 'networkSelector')
|
|
527
|
-
return 47;
|
|
528
|
-
if (row.type === 'identity' && row.presentation === 'accountSelector')
|
|
529
|
-
return 58;
|
|
530
|
-
|
|
531
|
-
let base: number;
|
|
532
|
-
switch (row.type) {
|
|
533
|
-
case 'rail':
|
|
534
|
-
base = 40;
|
|
535
|
-
break;
|
|
536
|
-
case 'activity':
|
|
537
|
-
base = row.footerActions?.length ? 100 : 60;
|
|
538
|
-
break;
|
|
539
|
-
case 'message':
|
|
540
|
-
base = approximateMessageHeight(row, availableWidth);
|
|
541
|
-
break;
|
|
542
|
-
case 'mediaTile':
|
|
543
|
-
base = 244;
|
|
544
|
-
break;
|
|
545
|
-
case 'metricCard':
|
|
546
|
-
base =
|
|
547
|
-
row.variant === 'activity'
|
|
548
|
-
? 161
|
|
549
|
-
: row.variant === 'performance'
|
|
550
|
-
? 178
|
|
551
|
-
: 132;
|
|
552
|
-
break;
|
|
553
|
-
case 'sectionHeader': {
|
|
554
|
-
const isHistory =
|
|
555
|
-
row.variant === 'history' ||
|
|
556
|
-
row.key.startsWith('history-') ||
|
|
557
|
-
row.sectionKey.startsWith('history-');
|
|
558
|
-
base =
|
|
559
|
-
snapshot.layout.kind === 'table'
|
|
560
|
-
? 28
|
|
561
|
-
: row.presentation === 'networkSelector'
|
|
562
|
-
? 47
|
|
563
|
-
: isHistory
|
|
564
|
-
? 16
|
|
565
|
-
: row.variant === 'summary'
|
|
566
|
-
? 68
|
|
567
|
-
: row.variant === 'gallery'
|
|
568
|
-
? 32
|
|
569
|
-
: row.checkbox
|
|
570
|
-
? 56
|
|
571
|
-
: snapshot.layout.kind === 'linear'
|
|
572
|
-
? 30
|
|
573
|
-
: 36;
|
|
574
|
-
break;
|
|
575
|
-
}
|
|
576
|
-
case 'system':
|
|
577
|
-
base =
|
|
578
|
-
row.variant === 'loading' && row.loadingStyle === 'skeleton'
|
|
579
|
-
? 56
|
|
580
|
-
: row.variant === 'loading' && row.loadingStyle === 'spinner'
|
|
581
|
-
? 52
|
|
582
|
-
: 'presentation' in row && row.presentation === 'market'
|
|
583
|
-
? row.variant === 'loading'
|
|
584
|
-
? 68
|
|
585
|
-
: 44
|
|
586
|
-
: row.variant === 'noMatch' || row.variant === 'end'
|
|
587
|
-
? 36
|
|
588
|
-
: row.variant === 'retry'
|
|
589
|
-
? 44
|
|
590
|
-
: 56;
|
|
591
|
-
break;
|
|
592
|
-
case 'action':
|
|
593
|
-
base = row.presentation === 'accountSelector' ? 48 : row.icon ? 60 : 44;
|
|
594
|
-
break;
|
|
595
|
-
case 'dataRow':
|
|
596
|
-
base = row.columns.some((column) => column.secondaryText) ? 60 : 56;
|
|
597
|
-
break;
|
|
598
|
-
case 'market': {
|
|
599
|
-
const marketStyle = resolveWebMarketLayoutStyle(row);
|
|
600
|
-
base = Math.max(
|
|
601
|
-
row.variant === 'stock' ? 72 : 68,
|
|
602
|
-
marketStyle.imageHeight + marketStyle.verticalPadding * 2
|
|
603
|
-
);
|
|
604
|
-
break;
|
|
605
|
-
}
|
|
606
|
-
case 'identity':
|
|
607
|
-
base = row.tertiary ? 72 : row.subtitle ? 60 : 56;
|
|
608
|
-
break;
|
|
609
|
-
default:
|
|
610
|
-
base = 56;
|
|
611
|
-
}
|
|
612
|
-
const tableAdjustment =
|
|
613
|
-
snapshot.layout.kind === 'table' &&
|
|
614
|
-
row.type === 'dataRow' &&
|
|
615
|
-
!row.columns.some((column) => column.secondaryText)
|
|
616
|
-
? -8
|
|
617
|
-
: 0;
|
|
618
|
-
return Math.max(0, base + sizeModifier(row) + tableAdjustment);
|
|
445
|
+
// Explicit container/model height takes precedence over template presets.
|
|
446
|
+
const explicitHeight = row.style?.container?.height ?? row.height;
|
|
447
|
+
if (explicitHeight !== undefined) return explicitHeight;
|
|
448
|
+
const registered = rowRenderer(row);
|
|
449
|
+
return Math.max(
|
|
450
|
+
0,
|
|
451
|
+
registered.measure(availableWidth, snapshot.layout.kind) +
|
|
452
|
+
(registered.appliesSizePreset ? sizeModifier(row) : 0)
|
|
453
|
+
);
|
|
619
454
|
}
|
|
620
455
|
|
|
621
456
|
function estimateHorizontalWidth(row: RowModel): number {
|
|
622
457
|
if (row.type === 'mediaTile') return 200;
|
|
623
458
|
if (row.type !== 'rail') return 280;
|
|
624
|
-
|
|
625
|
-
const statusLength =
|
|
626
|
-
row.status && row.status !== 'none' ? row.status.length : 0;
|
|
627
|
-
return Math.min(
|
|
628
|
-
288,
|
|
629
|
-
Math.max(72, 50 + (row.title.length + badgeLength + statusLength) * 7)
|
|
630
|
-
);
|
|
459
|
+
return measureRailWidth(row);
|
|
631
460
|
}
|
|
632
461
|
|
|
633
462
|
function sectionIndexEnabled(snapshot: NativeListSnapshot): boolean {
|
|
@@ -680,9 +509,14 @@ export function computeWebListLayout(
|
|
|
680
509
|
y: padding.top,
|
|
681
510
|
width: itemWidth,
|
|
682
511
|
height:
|
|
683
|
-
row.type === '
|
|
512
|
+
(row.type === 'walletGroup' && row.key === compactRowKey
|
|
513
|
+
? WALLET_REORDER_COMPACT_HEIGHT
|
|
514
|
+
: undefined) ??
|
|
515
|
+
row.style?.container?.height ??
|
|
516
|
+
row.height ??
|
|
517
|
+
(row.type === 'rail'
|
|
684
518
|
? Math.min(rowHeight, availableHeight)
|
|
685
|
-
: availableHeight,
|
|
519
|
+
: availableHeight),
|
|
686
520
|
});
|
|
687
521
|
x += itemWidth + spacing;
|
|
688
522
|
});
|
|
@@ -760,9 +594,11 @@ export function computeWebListLayout(
|
|
|
760
594
|
return;
|
|
761
595
|
}
|
|
762
596
|
const itemHeight =
|
|
763
|
-
row.
|
|
597
|
+
row.style?.container?.height ??
|
|
598
|
+
row.height ??
|
|
599
|
+
(row.type === 'mediaTile'
|
|
764
600
|
? itemWidth + 48
|
|
765
|
-
: estimateWebRowHeight(row, snapshot, itemWidth);
|
|
601
|
+
: estimateWebRowHeight(row, snapshot, itemWidth));
|
|
766
602
|
items.push({
|
|
767
603
|
index,
|
|
768
604
|
key: row.key,
|
|
@@ -806,6 +642,8 @@ export function canStartWebWalletGroupReorder(
|
|
|
806
642
|
const member = [row.parent, ...row.children].find(
|
|
807
643
|
(candidate) => candidate.key === memberKey
|
|
808
644
|
);
|
|
645
|
+
// Legacy: only `draggable: false` excludes a member; disabled members may
|
|
646
|
+
// still start the atomic group drag.
|
|
809
647
|
return member?.draggable !== false;
|
|
810
648
|
}
|
|
811
649
|
|
|
@@ -951,15 +789,15 @@ export function webMarketImageBindDeltaForPatches(
|
|
|
951
789
|
// OneKey patch: selector names must shrink before the sidebar clips their contents.
|
|
952
790
|
export const WEB_LIST_CSS = `
|
|
953
791
|
[data-native-list-selector="walletSidebar"] .ok-native-list-title{max-width:100%;min-width:0}
|
|
954
|
-
.ok-native-list-root{--nl-bg:#f7f7f7;--nl-row:#fff;--nl-selected:#eaf2ff;--nl-pressed:#e8e8e8;--nl-subdued:#f9f9f9;--nl-strong:#0000000f;--nl-primary:#111;--nl-secondary:#6b7280;--nl-disabled:#8d8d8d;--nl-icon:#111;--nl-icon-subdued:#8d8d8d;--nl-separator:#e5e7eb;--nl-accent:#2f6bff;--nl-positive:#15803d;--nl-negative:#dc2626;--nl-critical:#feecec;--nl-inverse:#202020;--nl-inverse-text:#fcfcfc;--nl-info:#0d74ce;position:absolute;inset:0;display:flex;min-width:0;min-height:0;overflow:hidden;background:var(--nl-bg);color:var(--nl-primary);font-family:Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-synthesis:none}
|
|
792
|
+
.ok-native-list-root{--nl-bg:#f7f7f7;--nl-row:#fff;--nl-selected:#eaf2ff;--nl-pressed:#e8e8e8;--nl-subdued:#f9f9f9;--nl-strong:#0000000f;--nl-primary:#111;--nl-secondary:#6b7280;--nl-disabled:#8d8d8d;--nl-icon:#111;--nl-icon-subdued:#8d8d8d;--nl-separator:#e5e7eb;--nl-accent:#2f6bff;--nl-positive:#15803d;--nl-negative:#dc2626;--nl-critical:#feecec;--nl-inverse:#202020;--nl-inverse-text:#fcfcfc;--nl-info:#0d74ce;position:absolute;inset:0;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:var(--nl-bg);color:var(--nl-primary);font-family:Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-synthesis:none}
|
|
955
793
|
.ok-native-list-viewport-frame{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden}
|
|
956
794
|
.ok-native-list-viewport{position:absolute;inset:0;overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}
|
|
957
795
|
.ok-native-list-content{position:relative;min-width:100%;min-height:100%}
|
|
958
|
-
.ok-native-list-item{position:absolute;box-sizing:border-box;contain:layout paint style;outline:none}
|
|
796
|
+
.ok-native-list-item{position:absolute;left:0;top:0;box-sizing:border-box;contain:layout paint style;outline:none}
|
|
959
797
|
.ok-native-list-row{width:100%;height:100%;box-sizing:border-box;display:flex;align-items:center;gap:12px;overflow:hidden;background:var(--nl-row);color:var(--nl-primary);cursor:default;user-select:none;-webkit-user-select:none}
|
|
960
798
|
.ok-native-list-item[data-table-alternate="true"]>.ok-native-list-row{background:var(--nl-bg)}
|
|
961
799
|
.ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
|
|
962
|
-
.ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{
|
|
800
|
+
.ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{cursor:default}
|
|
963
801
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]>.ok-native-list-row{cursor:pointer}
|
|
964
802
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>.ok-native-list-row{background:var(--nl-pressed)}
|
|
965
803
|
.ok-native-list-item[data-native-list-row-press-enabled="true"]:active>.ok-native-list-row{background:var(--nl-pressed)}
|
|
@@ -984,10 +822,13 @@ export const WEB_LIST_CSS = `
|
|
|
984
822
|
.ok-native-list-reorder-preview>.ok-native-list-row{background:var(--nl-pressed);cursor:grabbing}
|
|
985
823
|
.ok-native-list-reorder-preview[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
|
|
986
824
|
.ok-native-list-reorder-count{position:absolute;right:4px;bottom:4px;display:flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:24px;height:24px;padding:0 6px;border:1px solid var(--nl-row);border-radius:12px;background:var(--nl-inverse);color:var(--nl-inverse-text);font-size:12px;line-height:22px;font-weight:600}
|
|
987
|
-
.ok-native-list-item[data-separator="true"]>.ok-native-list-row{border-bottom:1px solid var(--nl-separator)}
|
|
988
|
-
|
|
989
|
-
.ok-native-list-
|
|
990
|
-
.ok-native-list-
|
|
825
|
+
.ok-native-list-item[data-separator="true"]>.ok-native-list-row{border-bottom:1px solid var(--nl-separator-color,var(--nl-separator))}
|
|
826
|
+
/* An inset separator keeps the transparent border so the row's height is unchanged, and paints the visible line with a logical-inset overlay so it follows RTL. */
|
|
827
|
+
.ok-native-list-root[data-separator-inset="true"] .ok-native-list-item[data-separator="true"]>.ok-native-list-row{position:relative;border-bottom-color:transparent}
|
|
828
|
+
.ok-native-list-root[data-separator-inset="true"] .ok-native-list-item[data-separator="true"]>.ok-native-list-row::after{content:"";position:absolute;inset-inline-start:var(--nl-separator-inset,0);inset-inline-end:0;bottom:-1px;height:1px;background:var(--nl-separator-color,var(--nl-separator))}
|
|
829
|
+
.ok-native-list-item[data-group-position="first"]>.ok-native-list-row{border-radius:var(--nl-group-radius,12px) var(--nl-group-radius,12px) 0 0}
|
|
830
|
+
.ok-native-list-item[data-group-position="last"]>.ok-native-list-row{border-radius:0 0 var(--nl-group-radius,12px) var(--nl-group-radius,12px)}
|
|
831
|
+
.ok-native-list-item[data-group-position="single"]>.ok-native-list-row{border-radius:var(--nl-group-radius,12px)}
|
|
991
832
|
.ok-native-list-standard{padding:8px 12px}.ok-native-list-network-row{padding:0 12px}.ok-native-list-wallet-row{padding:4px 8px;flex-direction:column;justify-content:center;gap:4px}.ok-native-list-account-row{padding:4px 12px;gap:8px}
|
|
992
833
|
.ok-native-list-account-row .ok-native-list-visual,.ok-native-list-account-action-row .ok-native-list-visual{width:32px;height:32px;flex-basis:32px}.ok-native-list-account-row .ok-native-list-visual>img,.ok-native-list-account-row .ok-native-list-visual-main,.ok-native-list-account-action-row .ok-native-list-visual>img,.ok-native-list-account-action-row .ok-native-list-visual-main{width:32px;height:32px}.ok-native-list-account-row .ok-native-list-visual>.ok-native-list-visual-corner{width:20px;height:20px;padding:2px}.ok-native-list-account-action-row .ok-native-list-visual{border-radius:8px!important}.ok-native-list-wallet-row .ok-native-list-title{color:var(--nl-secondary);font-size:12px;line-height:16px;font-weight:400}.ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-wallet-row .ok-native-list-title{color:var(--nl-primary)}.ok-native-list-account-row .ok-native-list-title{font-size:16px;line-height:20px;font-weight:400}.ok-native-list-account-row .ok-native-list-secondary{font-size:14px;line-height:20px;font-weight:400}
|
|
993
834
|
.ok-native-list-flex{display:flex;flex:1;min-width:0;flex-direction:column;justify-content:center}.ok-native-list-title{font-size:15px;line-height:20px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-secondary{font-size:13px;line-height:18px;color:var(--nl-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-tertiary{color:var(--nl-secondary)}.ok-native-list-info{color:var(--nl-info)}
|
|
@@ -1007,18 +848,13 @@ export const WEB_LIST_CSS = `
|
|
|
1007
848
|
.ok-native-list-data{padding:6px 12px}.ok-native-list-index{flex:0 0 28px;color:var(--nl-secondary);font-size:13px}.ok-native-list-favorite{flex:0 0 24px;color:var(--nl-icon-subdued);font-size:22px}.ok-native-list-favorite[data-active="true"]{color:var(--nl-accent)}.ok-native-list-data-cell{display:flex;flex-direction:column;min-width:0}.ok-native-list-data-cell[data-align="center"]{align-items:center}.ok-native-list-data-cell[data-align="end"]{align-items:flex-end}.ok-native-list-data-primary{display:flex;align-items:center;gap:5px;max-width:100%;font-size:16px;font-weight:500;white-space:nowrap}.ok-native-list-unread{width:7px;height:7px;flex:0 0 7px;border-radius:50%;background:var(--nl-accent)}.ok-native-list-thumbnail{width:64px;height:64px;border-radius:10px;object-fit:cover}
|
|
1008
849
|
.ok-native-list-market{padding:12px 20px;gap:14px}.ok-native-list-market>.ok-native-list-visual{width:32px;height:32px;flex-basis:32px}.ok-native-list-market[data-variant="stock"]>.ok-native-list-visual{width:40px;height:40px;flex-basis:40px}.ok-native-list-market>.ok-native-list-visual>.ok-native-list-visual-main{width:100%;height:100%}.ok-native-list-market-main{display:flex;flex:1;min-width:0;flex-direction:column;justify-content:center}.ok-native-list-market-title-line{display:flex;align-items:center;min-width:0;gap:4px}.ok-native-list-market-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--nl-primary);font-size:16px;line-height:24px;font-weight:500}.ok-native-list-market-subtitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--nl-secondary);font-size:14px;line-height:20px;font-weight:400}.ok-native-list-market-badge{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;box-sizing:border-box;max-width:72px;height:18px;padding:0 5px;border:0;border-radius:4px;background:var(--nl-strong);color:var(--nl-secondary);font:500 11px/18px inherit;overflow:hidden;white-space:nowrap}.ok-native-list-market-badge img{width:14px;height:14px;object-fit:contain}.ok-native-list-market-trailing{display:flex;flex:0 0 auto;align-items:center;gap:8px}.ok-native-list-market-price{max-width:112px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right;color:var(--nl-primary);font-size:16px;line-height:24px;font-weight:500;font-variant-numeric:tabular-nums}.ok-native-list-market-change{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:80px;height:32px;border-radius:8px;color:#fff;background:#8d8d8d;font-size:14px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}.ok-native-list-market-change[data-tone="positive"]{background:var(--nl-positive)}.ok-native-list-market-change[data-tone="negative"]{background:var(--nl-negative)}
|
|
1009
850
|
.ok-native-list-market-badge>svg,.ok-native-list-market-badge>.ok-native-list-market-badge-icon>svg{display:block;width:16px;height:16px;flex:0 0 16px}.ok-native-list-system[data-native-list-presentation="market"]{box-sizing:border-box;padding:12px 20px}.ok-native-list-system[data-native-list-presentation="market"]>.ok-native-list-spinner{width:32px;height:32px}
|
|
1010
|
-
.ok-native-list-
|
|
1011
|
-
.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)}
|
|
1012
|
-
.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)}
|
|
1013
|
-
.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}
|
|
851
|
+
.ok-native-list-index-preview{position:absolute;z-index:8;right:40px;top:50%;display:flex;width:48px;height:48px;align-items:center;justify-content:center;transform:translateY(-50%) scale(.92);border-radius:14px;background:var(--nl-inverse);color:var(--nl-inverse-text);font-size:22px;font-weight:600;opacity:0;pointer-events:none;transition:opacity .15s ease,transform .15s ease}.ok-native-list-index-preview[data-visible="true"]{opacity:1;transform:translateY(-50%) scale(1)}
|
|
1014
852
|
.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}
|
|
1015
853
|
@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)}}
|
|
1016
854
|
.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,.ok-native-list-viewport-frame[data-section-index-visible="true"]>.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,.ok-native-list-viewport-frame[data-section-index-visible="true"]>.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;font-family:Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.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;opacity:.5;transition:opacity .15s ease}.ok-native-list-index-rail:hover .ok-native-list-index-button,.ok-native-list-index-rail:focus-within .ok-native-list-index-button,.ok-native-list-index-button[data-active="true"]{opacity:1}.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}
|
|
1017
855
|
.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)}
|
|
1018
856
|
.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)}
|
|
1019
|
-
.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}
|
|
1020
|
-
@media (prefers-reduced-motion:reduce){.ok-native-list-refresh{transition:none}.ok-native-list-spinner{animation:none}}
|
|
1021
|
-
/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
857
|
+
.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}/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
1022
858
|
.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))}
|
|
1023
859
|
.ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
|
|
1024
860
|
.ok-native-list-checkbox[data-selector="networkSelector"]>svg{display:none;width:16px;height:16px;color:var(--nl-checkbox-icon,var(--nl-inverse-text));flex-shrink:0}
|
|
@@ -1044,6 +880,11 @@ export const WEB_LIST_CSS = `
|
|
|
1044
880
|
.ok-native-list-root .ok-native-list-item>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-wallet-member>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-action-row,.ok-native-list-wallet-member{cursor:default}
|
|
1045
881
|
/* OneKey patch: Add account hover and pressed backgrounds keep the account row corner radius. */
|
|
1046
882
|
.ok-native-list-account-action-row{border-radius:12px}
|
|
883
|
+
|
|
884
|
+
.ok-native-list-root .ok-native-list-item>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member>[data-nl-container-background="true"]{background:var(--nl-container-background)}
|
|
885
|
+
.ok-native-list-root [data-nl-container-border="true"]{position:relative}
|
|
886
|
+
.ok-native-list-root [data-nl-container-border="true"]::before{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 var(--nl-container-border-width) var(--nl-container-border-color);z-index:2;pointer-events:none}
|
|
887
|
+
.ok-native-list-root .ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-item[data-native-list-row-press-enabled="true"]:active>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member:hover>[data-nl-container-background="true"],.ok-native-list-root .ok-native-list-wallet-member:active>[data-nl-container-background="true"]{background:var(--nl-pressed)}
|
|
1047
888
|
`;
|
|
1048
889
|
|
|
1049
890
|
function createElement(
|
|
@@ -1604,17 +1445,6 @@ function iconGlyph(name: string): string {
|
|
|
1604
1445
|
return name.slice(0, 1).toLocaleUpperCase();
|
|
1605
1446
|
}
|
|
1606
1447
|
|
|
1607
|
-
function visualFromRow(row: RowModel): LeadingVisual | undefined {
|
|
1608
|
-
if (row.type === 'identity') return row.leading;
|
|
1609
|
-
if (row.type === 'rail') return row.visual;
|
|
1610
|
-
if (row.type === 'activity') return row.leading;
|
|
1611
|
-
if (row.type === 'message') return row.leading;
|
|
1612
|
-
if (row.type === 'dataRow') return row.leading;
|
|
1613
|
-
if (row.type === 'market') return row.leading;
|
|
1614
|
-
if (row.type === 'metricCard') return row.visual;
|
|
1615
|
-
return undefined;
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
1448
|
function createVisual(
|
|
1619
1449
|
context: RenderContext,
|
|
1620
1450
|
visual: LeadingVisual | undefined,
|
|
@@ -1828,20 +1658,6 @@ function toneColor(
|
|
|
1828
1658
|
return fallback === 'secondary' ? 'var(--nl-secondary)' : 'var(--nl-primary)';
|
|
1829
1659
|
}
|
|
1830
1660
|
|
|
1831
|
-
function createBadge(
|
|
1832
|
-
context: RenderContext,
|
|
1833
|
-
badge: Readonly<{ text: string; tone?: string }>
|
|
1834
|
-
): HTMLElement {
|
|
1835
|
-
const element = createElement(
|
|
1836
|
-
context.document,
|
|
1837
|
-
'span',
|
|
1838
|
-
'ok-native-list-badge',
|
|
1839
|
-
badge.text
|
|
1840
|
-
);
|
|
1841
|
-
setData(element, 'tone', badge.tone);
|
|
1842
|
-
return element;
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
1661
|
function selectionKeysForTarget(
|
|
1846
1662
|
target: SelectionTarget | undefined,
|
|
1847
1663
|
rowKey: string,
|
|
@@ -1909,1625 +1725,207 @@ function createCheckbox(
|
|
|
1909
1725
|
context.document,
|
|
1910
1726
|
'button',
|
|
1911
1727
|
'ok-native-list-checkbox'
|
|
1912
|
-
);
|
|
1913
|
-
element.setAttribute('type', 'button');
|
|
1914
|
-
element.setAttribute('role', 'checkbox');
|
|
1915
|
-
element.setAttribute(
|
|
1916
|
-
'aria-checked',
|
|
1917
|
-
state === 'indeterminate' ? 'mixed' : String(state === 'checked')
|
|
1918
|
-
);
|
|
1919
|
-
element.setAttribute('aria-label', 'Select');
|
|
1920
|
-
element.toggleAttribute('disabled', Boolean(accessory.disabled));
|
|
1921
|
-
setData(element, 'state', state);
|
|
1922
|
-
setData(element, 'checkboxFallback', accessory.state);
|
|
1923
|
-
setData(element, 'nativeListAction', accessory.actionKey ?? 'selection');
|
|
1924
|
-
setData(element, 'selectionScope', accessory.target?.scope ?? 'row');
|
|
1925
|
-
const row = context.snapshot.rows[context.itemIndex];
|
|
1926
|
-
if (row && 'presentation' in row && row.presentation === 'networkSelector') {
|
|
1927
|
-
setData(element, 'selector', 'networkSelector');
|
|
1928
|
-
for (const [state, name] of [
|
|
1929
|
-
['checked', 'CheckboxCheckedCustom'],
|
|
1930
|
-
['indeterminate', 'CheckboxIndeterminateCustom'],
|
|
1931
|
-
]) {
|
|
1932
|
-
const holder = createElement(context.document, 'span');
|
|
1933
|
-
applySelectorIcon(holder, name);
|
|
1934
|
-
const svg = holder.firstElementChild;
|
|
1935
|
-
if (svg) {
|
|
1936
|
-
svg.setAttribute('data-state', state);
|
|
1937
|
-
element.appendChild(svg);
|
|
1938
|
-
}
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
if (accessory.target?.scope === 'section')
|
|
1942
|
-
setData(element, 'selectionKey', accessory.target.sectionKey);
|
|
1943
|
-
else if (accessory.target?.scope === 'row')
|
|
1944
|
-
setData(element, 'selectionKey', rowKey);
|
|
1945
|
-
return element;
|
|
1946
|
-
}
|
|
1947
|
-
|
|
1948
|
-
function createIconAction(
|
|
1949
|
-
context: RenderContext,
|
|
1950
|
-
name: string,
|
|
1951
|
-
actionKey: string | undefined,
|
|
1952
|
-
disabled?: boolean,
|
|
1953
|
-
tintColor?: string
|
|
1954
|
-
): HTMLElement {
|
|
1955
|
-
const element = createElement(
|
|
1956
|
-
context.document,
|
|
1957
|
-
actionKey ? 'button' : 'span',
|
|
1958
|
-
'ok-native-list-icon-button',
|
|
1959
|
-
iconGlyph(name)
|
|
1960
|
-
);
|
|
1961
|
-
if (element.tagName === 'BUTTON') {
|
|
1962
|
-
element.setAttribute('type', 'button');
|
|
1963
|
-
element.toggleAttribute('disabled', Boolean(disabled));
|
|
1964
|
-
}
|
|
1965
|
-
applySelectorIcon(element, name);
|
|
1966
|
-
if (actionKey) setData(element, 'nativeListAction', actionKey);
|
|
1967
|
-
if (tintColor) element.style.color = tintColor;
|
|
1968
|
-
return element;
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
|
-
function markActionAnchorSource(
|
|
1972
|
-
element: HTMLElement,
|
|
1973
|
-
source: NativeListActionSource,
|
|
1974
|
-
slot?: number
|
|
1975
|
-
) {
|
|
1976
|
-
setData(element, 'nativeListAnchorSource', source);
|
|
1977
|
-
if (slot !== undefined) setData(element, 'nativeListAnchorSlot', slot);
|
|
1978
|
-
}
|
|
1979
|
-
|
|
1980
|
-
// OneKey patch: the compact zero-count digits share the amount baseline.
|
|
1981
|
-
function applyValueSegments(
|
|
1982
|
-
element: HTMLElement,
|
|
1983
|
-
segments:
|
|
1984
|
-
| readonly Readonly<{ text: string; style?: 'subscript' }>[]
|
|
1985
|
-
| undefined,
|
|
1986
|
-
fontSize = 16,
|
|
1987
|
-
lineHeight = 24,
|
|
1988
|
-
weight = 500
|
|
1989
|
-
) {
|
|
1990
|
-
if (!segments?.length) return;
|
|
1991
|
-
element.textContent = '';
|
|
1992
|
-
element.style.fontSize = String(fontSize) + 'px';
|
|
1993
|
-
element.style.lineHeight = String(lineHeight) + 'px';
|
|
1994
|
-
element.style.fontWeight = String(weight);
|
|
1995
|
-
segments.forEach((segment) => {
|
|
1996
|
-
const span = createElement(
|
|
1997
|
-
element.ownerDocument,
|
|
1998
|
-
'span',
|
|
1999
|
-
undefined,
|
|
2000
|
-
segment.text
|
|
2001
|
-
);
|
|
2002
|
-
if (segment.style === 'subscript') {
|
|
2003
|
-
span.style.fontSize = String(Math.ceil(fontSize * 0.6)) + 'px';
|
|
2004
|
-
span.style.lineHeight = String(fontSize) + 'px';
|
|
2005
|
-
}
|
|
2006
|
-
element.appendChild(span);
|
|
2007
|
-
});
|
|
2008
|
-
}
|
|
2009
|
-
|
|
2010
|
-
function createAccessory(
|
|
2011
|
-
context: RenderContext,
|
|
2012
|
-
rowKey: string,
|
|
2013
|
-
accessory: TrailingAccessory,
|
|
2014
|
-
slot: number
|
|
2015
|
-
): HTMLElement {
|
|
2016
|
-
if (accessory.kind === 'checkbox') {
|
|
2017
|
-
const element = createCheckbox(context, rowKey, accessory);
|
|
2018
|
-
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
2019
|
-
return element;
|
|
2020
|
-
}
|
|
2021
|
-
if (accessory.kind === 'icon') {
|
|
2022
|
-
const element = createIconAction(
|
|
2023
|
-
context,
|
|
2024
|
-
accessory.name,
|
|
2025
|
-
accessory.actionKey,
|
|
2026
|
-
accessory.disabled,
|
|
2027
|
-
accessory.tintColor
|
|
2028
|
-
);
|
|
2029
|
-
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
2030
|
-
setData(element, 'testid', accessory.testID);
|
|
2031
|
-
if (accessory.hoverActionKey)
|
|
2032
|
-
setData(element, 'nativeListHoverAction', accessory.hoverActionKey);
|
|
2033
|
-
if (accessory.accessibilityLabel)
|
|
2034
|
-
element.setAttribute('aria-label', accessory.accessibilityLabel);
|
|
2035
|
-
const row = context.snapshot.rows[context.itemIndex];
|
|
2036
|
-
if (
|
|
2037
|
-
row &&
|
|
2038
|
-
'presentation' in row &&
|
|
2039
|
-
row.presentation === 'accountSelector'
|
|
2040
|
-
) {
|
|
2041
|
-
setData(element, 'nativeListAnchorInset', 7);
|
|
2042
|
-
// OneKey patch: the create-address button omits IconButton's one-point border.
|
|
2043
|
-
if (row.height !== undefined && accessory.name === 'PlusSmallOutline') {
|
|
2044
|
-
setData(element, 'nativeListAccountControl', 'createAddress');
|
|
2045
|
-
if (!accessory.tintColor)
|
|
2046
|
-
element.style.color = 'var(--nl-icon-subdued)';
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
return element;
|
|
2050
|
-
}
|
|
2051
|
-
if (accessory.kind === 'spinner') {
|
|
2052
|
-
return createElement(context.document, 'span', 'ok-native-list-spinner');
|
|
2053
|
-
}
|
|
2054
|
-
const actionKey = 'actionKey' in accessory ? accessory.actionKey : undefined;
|
|
2055
|
-
const element = createElement(
|
|
2056
|
-
context.document,
|
|
2057
|
-
actionKey ? 'button' : 'span',
|
|
2058
|
-
'ok-native-list-accessory'
|
|
2059
|
-
);
|
|
2060
|
-
if (element.tagName === 'BUTTON') {
|
|
2061
|
-
element.setAttribute('type', 'button');
|
|
2062
|
-
element.classList.add('ok-native-list-icon-button');
|
|
2063
|
-
setData(element, 'nativeListAction', actionKey);
|
|
2064
|
-
}
|
|
2065
|
-
switch (accessory.kind) {
|
|
2066
|
-
case 'value':
|
|
2067
|
-
element.textContent = accessory.text;
|
|
2068
|
-
applyValueSegments(element, accessory.textSegments);
|
|
2069
|
-
if (accessory.secondary)
|
|
2070
|
-
element.classList.add('ok-native-list-accessory-secondary');
|
|
2071
|
-
break;
|
|
2072
|
-
case 'valuePair': {
|
|
2073
|
-
const primary = createElement(
|
|
2074
|
-
context.document,
|
|
2075
|
-
'span',
|
|
2076
|
-
undefined,
|
|
2077
|
-
accessory.primary
|
|
2078
|
-
);
|
|
2079
|
-
primary.style.color = toneColor(accessory.primaryTone, 'primary');
|
|
2080
|
-
const secondary = createElement(
|
|
2081
|
-
context.document,
|
|
2082
|
-
'span',
|
|
2083
|
-
'ok-native-list-secondary',
|
|
2084
|
-
accessory.secondary
|
|
2085
|
-
);
|
|
2086
|
-
secondary.style.color = toneColor(accessory.secondaryTone, 'secondary');
|
|
2087
|
-
element.replaceChildren(primary, secondary);
|
|
2088
|
-
element.classList.add('ok-native-list-amounts');
|
|
2089
|
-
break;
|
|
2090
|
-
}
|
|
2091
|
-
case 'radio':
|
|
2092
|
-
element.textContent = accessory.checked ? '●' : '○';
|
|
2093
|
-
break;
|
|
2094
|
-
case 'switch':
|
|
2095
|
-
element.textContent = accessory.value ? 'ON' : 'OFF';
|
|
2096
|
-
setData(element, 'nativeListAction', accessory.actionKey);
|
|
2097
|
-
break;
|
|
2098
|
-
case 'chevron':
|
|
2099
|
-
element.textContent = '›';
|
|
2100
|
-
break;
|
|
2101
|
-
case 'menu':
|
|
2102
|
-
element.textContent = '⋮';
|
|
2103
|
-
break;
|
|
2104
|
-
case 'drag':
|
|
2105
|
-
element.textContent = '≡';
|
|
2106
|
-
break;
|
|
2107
|
-
case 'progress':
|
|
2108
|
-
element.textContent = String(Math.round(accessory.value * 100)) + '%';
|
|
2109
|
-
break;
|
|
2110
|
-
}
|
|
2111
|
-
if (actionKey) markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
2112
|
-
return element;
|
|
2113
|
-
}
|
|
2114
|
-
|
|
2115
|
-
function appendAccessories(
|
|
2116
|
-
parent: HTMLElement,
|
|
2117
|
-
context: RenderContext,
|
|
2118
|
-
rowKey: string,
|
|
2119
|
-
accessories: readonly TrailingAccessory[] | undefined
|
|
2120
|
-
) {
|
|
2121
|
-
if (!accessories?.length) return;
|
|
2122
|
-
const container = createElement(
|
|
2123
|
-
context.document,
|
|
2124
|
-
'span',
|
|
2125
|
-
'ok-native-list-accessories'
|
|
2126
|
-
);
|
|
2127
|
-
const row = context.snapshot.rows[context.itemIndex];
|
|
2128
|
-
if (
|
|
2129
|
-
row &&
|
|
2130
|
-
row.height !== undefined &&
|
|
2131
|
-
'presentation' in row &&
|
|
2132
|
-
row.presentation === 'networkSelector'
|
|
2133
|
-
) {
|
|
2134
|
-
container.style.gap = accessories.some(
|
|
2135
|
-
(accessory) => accessory.kind === 'checkbox'
|
|
2136
|
-
)
|
|
2137
|
-
? '12px'
|
|
2138
|
-
: '20px';
|
|
2139
|
-
}
|
|
2140
|
-
if (
|
|
2141
|
-
row &&
|
|
2142
|
-
row.height !== undefined &&
|
|
2143
|
-
'presentation' in row &&
|
|
2144
|
-
row.presentation === 'accountSelector' &&
|
|
2145
|
-
accessories.length === 1 &&
|
|
2146
|
-
accessories[0]?.kind === 'icon' &&
|
|
2147
|
-
accessories[0].name === 'PlusSmallOutline'
|
|
2148
|
-
) {
|
|
2149
|
-
setData(container, 'nativeListAccountControl', 'createAddress');
|
|
2150
|
-
}
|
|
2151
|
-
accessories.forEach((accessory, slot) =>
|
|
2152
|
-
container.appendChild(createAccessory(context, rowKey, accessory, slot))
|
|
2153
|
-
);
|
|
2154
|
-
parent.appendChild(container);
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
function createTextColumn(
|
|
2158
|
-
context: RenderContext,
|
|
2159
|
-
title: string,
|
|
2160
|
-
subtitle?: string,
|
|
2161
|
-
tertiary?: string,
|
|
2162
|
-
tertiaryTone?: 'secondary' | 'info',
|
|
2163
|
-
badges?: readonly Readonly<{ text: string; tone?: string }>[]
|
|
2164
|
-
): HTMLElement {
|
|
2165
|
-
const column = createElement(context.document, 'span', 'ok-native-list-flex');
|
|
2166
|
-
const titleLine = createElement(
|
|
2167
|
-
context.document,
|
|
2168
|
-
'span',
|
|
2169
|
-
'ok-native-list-title',
|
|
2170
|
-
title
|
|
2171
|
-
);
|
|
2172
|
-
if (badges?.length) {
|
|
2173
|
-
const badgeLine = createElement(
|
|
2174
|
-
context.document,
|
|
2175
|
-
'span',
|
|
2176
|
-
'ok-native-list-badges'
|
|
2177
|
-
);
|
|
2178
|
-
badges.forEach((badge) =>
|
|
2179
|
-
badgeLine.appendChild(createBadge(context, badge))
|
|
2180
|
-
);
|
|
2181
|
-
titleLine.appendChild(badgeLine);
|
|
2182
|
-
}
|
|
2183
|
-
column.appendChild(titleLine);
|
|
2184
|
-
if (subtitle)
|
|
2185
|
-
column.appendChild(
|
|
2186
|
-
createElement(
|
|
2187
|
-
context.document,
|
|
2188
|
-
'span',
|
|
2189
|
-
'ok-native-list-secondary',
|
|
2190
|
-
subtitle
|
|
2191
|
-
)
|
|
2192
|
-
);
|
|
2193
|
-
if (tertiary) {
|
|
2194
|
-
const element = createElement(
|
|
2195
|
-
context.document,
|
|
2196
|
-
'span',
|
|
2197
|
-
tertiaryTone === 'info'
|
|
2198
|
-
? 'ok-native-list-secondary ok-native-list-info'
|
|
2199
|
-
: 'ok-native-list-secondary ok-native-list-tertiary',
|
|
2200
|
-
tertiary
|
|
2201
|
-
);
|
|
2202
|
-
column.appendChild(element);
|
|
2203
|
-
}
|
|
2204
|
-
return column;
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
function createSectionHeader(
|
|
2208
|
-
context: RenderContext,
|
|
2209
|
-
row: Extract<RowModel, { type: 'sectionHeader' }>
|
|
2210
|
-
): HTMLElement {
|
|
2211
|
-
const body = createElement(
|
|
2212
|
-
context.document,
|
|
2213
|
-
'div',
|
|
2214
|
-
'ok-native-list-row ok-native-list-section'
|
|
2215
|
-
);
|
|
2216
|
-
setData(body, 'variant', row.variant);
|
|
2217
|
-
if (row.titleIcon) {
|
|
2218
|
-
const titleIcon = createIconAction(
|
|
2219
|
-
context,
|
|
2220
|
-
row.titleIcon.name,
|
|
2221
|
-
row.titleIcon.actionKey,
|
|
2222
|
-
row.titleIcon.disabled,
|
|
2223
|
-
row.titleIcon.tintColor
|
|
2224
|
-
);
|
|
2225
|
-
markActionAnchorSource(titleIcon, 'leadingAction');
|
|
2226
|
-
body.appendChild(titleIcon);
|
|
2227
|
-
}
|
|
2228
|
-
// OneKey patch: section title help has its own measurable action target.
|
|
2229
|
-
// body.appendChild(createTextColumn(context, row.title, row.subtitle));
|
|
2230
|
-
const column = createTextColumn(context, row.title, row.subtitle);
|
|
2231
|
-
const title = column.firstElementChild as HTMLElement;
|
|
2232
|
-
title.classList.add('ok-native-list-section-title');
|
|
2233
|
-
if (row.titleActionKey) {
|
|
2234
|
-
setData(title, 'nativeListAction', row.titleActionKey);
|
|
2235
|
-
markActionAnchorSource(title, 'leadingAction');
|
|
2236
|
-
title.setAttribute('role', 'button');
|
|
2237
|
-
title.tabIndex = 0;
|
|
2238
|
-
title.style.alignSelf = 'flex-start';
|
|
2239
|
-
title.style.maxWidth = '100%';
|
|
2240
|
-
// OneKey patch: explicit network headers reserve a separate 3-point underline area.
|
|
2241
|
-
if (row.presentation !== 'networkSelector' || row.height === undefined) {
|
|
2242
|
-
title.style.textDecoration = 'underline dotted';
|
|
2243
|
-
title.style.textUnderlineOffset = '6px';
|
|
2244
|
-
}
|
|
2245
|
-
if (row.titleActionOnHover) setData(title, 'nativeListHoverAction', true);
|
|
2246
|
-
}
|
|
2247
|
-
if (row.presentation === 'networkSelector' && row.height !== undefined) {
|
|
2248
|
-
body.style.padding =
|
|
2249
|
-
row.variant === 'summary' ? '24px 12px 20px' : '0 12px';
|
|
2250
|
-
body.style.backgroundColor = 'var(--nl-bg)';
|
|
2251
|
-
body.style.gap = row.checkbox ? '12px' : '8px';
|
|
2252
|
-
title.style.fontSize = row.variant === 'summary' ? '16px' : '14px';
|
|
2253
|
-
title.style.lineHeight = row.variant === 'summary' ? '24px' : '20px';
|
|
2254
|
-
title.style.fontWeight =
|
|
2255
|
-
row.variant === 'summary' || (row.titleActionKey && !row.checkbox)
|
|
2256
|
-
? '500'
|
|
2257
|
-
: '600';
|
|
2258
|
-
if (row.titleActionKey) {
|
|
2259
|
-
const text = createElement(
|
|
2260
|
-
context.document,
|
|
2261
|
-
'span',
|
|
2262
|
-
'ok-native-list-section-title-text',
|
|
2263
|
-
row.title
|
|
2264
|
-
);
|
|
2265
|
-
text.style.overflow = 'hidden';
|
|
2266
|
-
text.style.textOverflow = 'ellipsis';
|
|
2267
|
-
text.style.maxWidth = '100%';
|
|
2268
|
-
const dotted = context.document.createElementNS(
|
|
2269
|
-
'http://www.w3.org/2000/svg',
|
|
2270
|
-
'svg'
|
|
2271
|
-
);
|
|
2272
|
-
dotted.setAttribute('height', '2');
|
|
2273
|
-
dotted.style.cssText =
|
|
2274
|
-
'display:block;position:absolute;left:0;bottom:0;width:100%;height:2px;color:var(--nl-secondary)';
|
|
2275
|
-
const line = context.document.createElementNS(
|
|
2276
|
-
'http://www.w3.org/2000/svg',
|
|
2277
|
-
'line'
|
|
2278
|
-
);
|
|
2279
|
-
for (const [key, value] of Object.entries({
|
|
2280
|
-
x1: '1',
|
|
2281
|
-
y1: '1',
|
|
2282
|
-
x2: '100%',
|
|
2283
|
-
y2: '1',
|
|
2284
|
-
stroke: 'currentColor',
|
|
2285
|
-
'stroke-width': '1.5',
|
|
2286
|
-
'stroke-dasharray': '0,4',
|
|
2287
|
-
'stroke-linecap': 'round',
|
|
2288
|
-
}))
|
|
2289
|
-
line.setAttribute(key, value);
|
|
2290
|
-
// OneKey patch: keep both round caps inside the original full-width viewport.
|
|
2291
|
-
const lineViewport = context.document.createElementNS(
|
|
2292
|
-
'http://www.w3.org/2000/svg',
|
|
2293
|
-
'svg'
|
|
2294
|
-
);
|
|
2295
|
-
lineViewport.setAttribute('width', 'calc(100% - 1px)');
|
|
2296
|
-
lineViewport.setAttribute('height', '2');
|
|
2297
|
-
lineViewport.setAttribute('overflow', 'visible');
|
|
2298
|
-
lineViewport.appendChild(line);
|
|
2299
|
-
dotted.appendChild(lineViewport);
|
|
2300
|
-
// OneKey patch: SVG intrinsic width must not expand the title action beyond its text.
|
|
2301
|
-
title.style.display = 'block';
|
|
2302
|
-
title.style.position = 'relative';
|
|
2303
|
-
title.style.width = 'fit-content';
|
|
2304
|
-
title.style.paddingBottom = '3px';
|
|
2305
|
-
text.style.display = 'block';
|
|
2306
|
-
title.replaceChildren(text, dotted);
|
|
2307
|
-
}
|
|
2308
|
-
}
|
|
2309
|
-
body.appendChild(column);
|
|
2310
|
-
if (row.value) {
|
|
2311
|
-
const value = createElement(
|
|
2312
|
-
context.document,
|
|
2313
|
-
row.valueActionKey ? 'button' : 'span',
|
|
2314
|
-
row.valueActionKey
|
|
2315
|
-
? 'ok-native-list-action-button ok-native-list-section-value'
|
|
2316
|
-
: 'ok-native-list-value ok-native-list-section-value',
|
|
2317
|
-
row.value
|
|
2318
|
-
);
|
|
2319
|
-
applyValueSegments(value, row.valueSegments);
|
|
2320
|
-
if (row.presentation === 'networkSelector' && row.height !== undefined) {
|
|
2321
|
-
value.style.fontFamily = 'inherit';
|
|
2322
|
-
value.style.fontSize = '16px';
|
|
2323
|
-
value.style.lineHeight = '24px';
|
|
2324
|
-
value.style.fontWeight = '500';
|
|
2325
|
-
if (row.valueActionKey) {
|
|
2326
|
-
value.style.color = 'var(--nl-secondary)';
|
|
2327
|
-
value.style.padding = '0';
|
|
2328
|
-
value.style.flexShrink = '0';
|
|
2329
|
-
}
|
|
2330
|
-
}
|
|
2331
|
-
if (row.valueActionTestID) setData(value, 'testid', row.valueActionTestID);
|
|
2332
|
-
if (row.valueActionKey) {
|
|
2333
|
-
value.setAttribute('type', 'button');
|
|
2334
|
-
setData(value, 'nativeListAction', row.valueActionKey);
|
|
2335
|
-
markActionAnchorSource(value, 'trailingAccessory', 0);
|
|
2336
|
-
}
|
|
2337
|
-
body.appendChild(value);
|
|
2338
|
-
}
|
|
2339
|
-
if (row.valueIcon) {
|
|
2340
|
-
const valueIcon = createIconAction(
|
|
2341
|
-
context,
|
|
2342
|
-
row.valueIcon.name,
|
|
2343
|
-
row.valueIcon.actionKey,
|
|
2344
|
-
row.valueIcon.disabled,
|
|
2345
|
-
row.valueIcon.tintColor
|
|
2346
|
-
);
|
|
2347
|
-
markActionAnchorSource(valueIcon, 'trailingAccessory', 1);
|
|
2348
|
-
body.appendChild(valueIcon);
|
|
2349
|
-
}
|
|
2350
|
-
if (row.checkbox)
|
|
2351
|
-
body.appendChild(createCheckbox(context, row.key, row.checkbox));
|
|
2352
|
-
return body;
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2355
|
-
function createActionRow(
|
|
2356
|
-
context: RenderContext,
|
|
2357
|
-
row: Extract<RowModel, { type: 'action' }>
|
|
2358
|
-
): HTMLElement {
|
|
2359
|
-
const body = createElement(
|
|
2360
|
-
context.document,
|
|
2361
|
-
'div',
|
|
2362
|
-
[
|
|
2363
|
-
'ok-native-list-row',
|
|
2364
|
-
'ok-native-list-action-row',
|
|
2365
|
-
row.presentation === 'accountSelector'
|
|
2366
|
-
? 'ok-native-list-account-action-row'
|
|
2367
|
-
: '',
|
|
2368
|
-
]
|
|
2369
|
-
.filter(Boolean)
|
|
2370
|
-
.join(' ')
|
|
2371
|
-
);
|
|
2372
|
-
if (row.icon) body.appendChild(createVisual(context, row.icon)!);
|
|
2373
|
-
const title = createElement(
|
|
2374
|
-
context.document,
|
|
2375
|
-
'span',
|
|
2376
|
-
'ok-native-list-action-title',
|
|
2377
|
-
row.title
|
|
2378
|
-
);
|
|
2379
|
-
setData(title, 'tone', row.tone);
|
|
2380
|
-
if (row.presentation === 'accountSelector' && row.icon)
|
|
2381
|
-
title.style.fontWeight = '500';
|
|
2382
|
-
body.appendChild(title);
|
|
2383
|
-
if (row.checkbox)
|
|
2384
|
-
body.appendChild(createCheckbox(context, row.key, row.checkbox));
|
|
2385
|
-
appendAccessories(body, context, row.key, row.trailing);
|
|
2386
|
-
return body;
|
|
2387
|
-
}
|
|
2388
|
-
|
|
2389
|
-
function createSystemRow(
|
|
2390
|
-
context: RenderContext,
|
|
2391
|
-
row: Extract<RowModel, { type: 'system' }>
|
|
2392
|
-
): HTMLElement {
|
|
2393
|
-
const body = createElement(
|
|
2394
|
-
context.document,
|
|
2395
|
-
'div',
|
|
2396
|
-
'ok-native-list-row ok-native-list-system'
|
|
2397
|
-
);
|
|
2398
|
-
setData(body, 'variant', row.variant);
|
|
2399
|
-
if ('presentation' in row)
|
|
2400
|
-
setData(body, 'nativeListPresentation', row.presentation);
|
|
2401
|
-
if (row.variant === 'loading' && row.loadingStyle === 'skeleton') {
|
|
2402
|
-
body.classList.add('ok-native-list-market-skeleton');
|
|
2403
|
-
const background = resolvedTheme(context.snapshot).background;
|
|
2404
|
-
const rgb = Number.parseInt(background.slice(1, 7), 16);
|
|
2405
|
-
const dark =
|
|
2406
|
-
((rgb >> 16) & 255) * 0.299 +
|
|
2407
|
-
((rgb >> 8) & 255) * 0.587 +
|
|
2408
|
-
(rgb & 255) * 0.114 <
|
|
2409
|
-
128;
|
|
2410
|
-
body.style.setProperty('--nl-skeleton-base', dark ? '#111111' : '#fafafa');
|
|
2411
|
-
body.style.setProperty(
|
|
2412
|
-
'--nl-skeleton-highlight',
|
|
2413
|
-
dark ? '#333333' : '#cdcdcd'
|
|
2414
|
-
);
|
|
2415
|
-
const left = createElement(
|
|
2416
|
-
context.document,
|
|
2417
|
-
'div',
|
|
2418
|
-
'ok-native-list-skeleton-left'
|
|
2419
|
-
);
|
|
2420
|
-
const mark = (width: number, height: number, circle = false) => {
|
|
2421
|
-
const element = createElement(
|
|
2422
|
-
context.document,
|
|
2423
|
-
'span',
|
|
2424
|
-
'ok-native-list-skeleton-mark'
|
|
2425
|
-
);
|
|
2426
|
-
element.style.width = `${width}px`;
|
|
2427
|
-
element.style.height = `${height}px`;
|
|
2428
|
-
if (circle) element.style.borderRadius = '50%';
|
|
2429
|
-
return element;
|
|
2430
|
-
};
|
|
2431
|
-
left.appendChild(mark(32, 32, true));
|
|
2432
|
-
const text = createElement(
|
|
2433
|
-
context.document,
|
|
2434
|
-
'div',
|
|
2435
|
-
'ok-native-list-skeleton-text'
|
|
2436
|
-
);
|
|
2437
|
-
text.appendChild(mark(80, 16));
|
|
2438
|
-
text.appendChild(mark(60, 12));
|
|
2439
|
-
left.appendChild(text);
|
|
2440
|
-
body.appendChild(left);
|
|
2441
|
-
const right = createElement(
|
|
2442
|
-
context.document,
|
|
2443
|
-
'div',
|
|
2444
|
-
'ok-native-list-skeleton-right'
|
|
2445
|
-
);
|
|
2446
|
-
right.appendChild(mark(80, 18));
|
|
2447
|
-
right.appendChild(mark(80, 18));
|
|
2448
|
-
body.appendChild(right);
|
|
2449
|
-
return body;
|
|
2450
|
-
}
|
|
2451
|
-
if (row.variant === 'loading' && row.loadingStyle === 'spinner') {
|
|
2452
|
-
body.style.justifyContent = 'center';
|
|
2453
|
-
body.style.padding = '16px';
|
|
2454
|
-
const spinner = createElement(
|
|
2455
|
-
context.document,
|
|
2456
|
-
'span',
|
|
2457
|
-
'ok-native-list-market-spinner'
|
|
2458
|
-
);
|
|
2459
|
-
spinner.setAttribute('role', 'progressbar');
|
|
2460
|
-
// Same 20px SVG and 750ms rotation as react-native-web ActivityIndicator.
|
|
2461
|
-
spinner.innerHTML =
|
|
2462
|
-
'<svg viewBox="0 0 32 32" width="20" height="20"><circle cx="16" cy="16" r="14" fill="none" stroke="currentColor" stroke-width="4" opacity="0.2"/><circle cx="16" cy="16" r="14" fill="none" stroke="currentColor" stroke-width="4" stroke-dasharray="80" stroke-dashoffset="60"/></svg>';
|
|
2463
|
-
body.appendChild(spinner);
|
|
2464
|
-
return body;
|
|
2465
|
-
}
|
|
2466
|
-
if ('presentation' in row && row.presentation === 'market') {
|
|
2467
|
-
if (row.variant === 'noMatch') {
|
|
2468
|
-
body.style.justifyContent = 'center';
|
|
2469
|
-
body.style.padding = '32px';
|
|
2470
|
-
const message = createElement(context.document, 'span', '', row.message);
|
|
2471
|
-
message.style.fontSize = '16px';
|
|
2472
|
-
message.style.lineHeight = '24px';
|
|
2473
|
-
body.appendChild(message);
|
|
2474
|
-
return body;
|
|
2475
|
-
}
|
|
2476
|
-
if (row.variant === 'end') {
|
|
2477
|
-
body.style.justifyContent = 'center';
|
|
2478
|
-
body.style.padding = '16px';
|
|
2479
|
-
body.style.gap = '8px';
|
|
2480
|
-
for (const width of [80, 4, 80]) {
|
|
2481
|
-
const mark = createElement(context.document, 'span', '');
|
|
2482
|
-
mark.style.width = String(width) + 'px';
|
|
2483
|
-
mark.style.height = width === 4 ? '4px' : '1px';
|
|
2484
|
-
mark.style.borderRadius = width === 4 ? '2px' : '0';
|
|
2485
|
-
mark.style.background = 'var(--nl-separator)';
|
|
2486
|
-
body.appendChild(mark);
|
|
2487
|
-
}
|
|
2488
|
-
return body;
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
if (row.variant === 'warning') {
|
|
2492
|
-
body.classList.add('ok-native-list-warning');
|
|
2493
|
-
body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
|
|
2494
|
-
body.appendChild(
|
|
2495
|
-
createElement(
|
|
2496
|
-
context.document,
|
|
2497
|
-
'span',
|
|
2498
|
-
'ok-native-list-warning-title',
|
|
2499
|
-
row.title
|
|
2500
|
-
)
|
|
2501
|
-
);
|
|
2502
|
-
body.appendChild(
|
|
2503
|
-
createElement(
|
|
2504
|
-
context.document,
|
|
2505
|
-
'span',
|
|
2506
|
-
'ok-native-list-warning-message',
|
|
2507
|
-
row.message
|
|
2508
|
-
)
|
|
2509
|
-
);
|
|
2510
|
-
return body;
|
|
2511
|
-
}
|
|
2512
|
-
if (row.variant === 'loading')
|
|
2513
|
-
body.appendChild(
|
|
2514
|
-
createElement(context.document, 'span', 'ok-native-list-spinner')
|
|
2515
|
-
);
|
|
2516
|
-
const message =
|
|
2517
|
-
row.variant === 'spacer'
|
|
2518
|
-
? ''
|
|
2519
|
-
: row.message ?? (row.variant === 'end' ? 'End' : '');
|
|
2520
|
-
if (message)
|
|
2521
|
-
body.appendChild(
|
|
2522
|
-
createElement(
|
|
2523
|
-
context.document,
|
|
2524
|
-
'span',
|
|
2525
|
-
'ok-native-list-secondary',
|
|
2526
|
-
message
|
|
2527
|
-
)
|
|
2528
|
-
);
|
|
2529
|
-
return body;
|
|
2530
|
-
}
|
|
2531
|
-
|
|
2532
|
-
function createRailRow(
|
|
2533
|
-
context: RenderContext,
|
|
2534
|
-
row: Extract<RowModel, { type: 'rail' }>
|
|
2535
|
-
): HTMLElement {
|
|
2536
|
-
const body = createElement(
|
|
2537
|
-
context.document,
|
|
2538
|
-
'div',
|
|
2539
|
-
'ok-native-list-row ok-native-list-rail'
|
|
2540
|
-
);
|
|
2541
|
-
const visual = createVisual(context, row.visual);
|
|
2542
|
-
if (visual) body.appendChild(visual);
|
|
2543
|
-
body.appendChild(
|
|
2544
|
-
createElement(
|
|
2545
|
-
context.document,
|
|
2546
|
-
'span',
|
|
2547
|
-
'ok-native-list-rail-title',
|
|
2548
|
-
row.title
|
|
2549
|
-
)
|
|
2550
|
-
);
|
|
2551
|
-
if (row.status && row.status !== 'none')
|
|
2552
|
-
body.appendChild(
|
|
2553
|
-
createElement(
|
|
2554
|
-
context.document,
|
|
2555
|
-
'span',
|
|
2556
|
-
'ok-native-list-secondary',
|
|
2557
|
-
row.status
|
|
2558
|
-
)
|
|
2559
|
-
);
|
|
2560
|
-
if (row.badge) body.appendChild(createBadge(context, row.badge));
|
|
2561
|
-
return body;
|
|
2562
|
-
}
|
|
2563
|
-
|
|
2564
|
-
function createMediaRow(
|
|
2565
|
-
context: RenderContext,
|
|
2566
|
-
row: Extract<RowModel, { type: 'mediaTile' }>
|
|
2567
|
-
): HTMLElement {
|
|
2568
|
-
const body = createElement(
|
|
2569
|
-
context.document,
|
|
2570
|
-
'div',
|
|
2571
|
-
'ok-native-list-row ok-native-list-media'
|
|
2572
|
-
);
|
|
2573
|
-
if (row.image && !row.imageState) {
|
|
2574
|
-
const image = createImage(context, row.image, 'ok-native-list-media-image');
|
|
2575
|
-
if (image) body.appendChild(image);
|
|
2576
|
-
} else {
|
|
2577
|
-
const placeholder = createElement(
|
|
2578
|
-
context.document,
|
|
2579
|
-
'span',
|
|
2580
|
-
'ok-native-list-media-image',
|
|
2581
|
-
row.imageState === 'error' ? '▧' : ''
|
|
2582
|
-
);
|
|
2583
|
-
setData(placeholder, 'state', row.imageState ?? 'empty');
|
|
2584
|
-
body.appendChild(placeholder);
|
|
2585
|
-
}
|
|
2586
|
-
const metadata = createElement(
|
|
2587
|
-
context.document,
|
|
2588
|
-
'div',
|
|
2589
|
-
'ok-native-list-media-meta'
|
|
2590
|
-
);
|
|
2591
|
-
const subtitleLine = createElement(
|
|
2592
|
-
context.document,
|
|
2593
|
-
'div',
|
|
2594
|
-
'ok-native-list-media-subtitle-row'
|
|
2595
|
-
);
|
|
2596
|
-
subtitleLine.appendChild(
|
|
2597
|
-
createElement(
|
|
2598
|
-
context.document,
|
|
2599
|
-
'span',
|
|
2600
|
-
'ok-native-list-media-subtitle',
|
|
2601
|
-
row.subtitle || '-'
|
|
2602
|
-
)
|
|
2603
|
-
);
|
|
2604
|
-
if (row.networkImage) {
|
|
2605
|
-
const network = createImage(
|
|
2606
|
-
context,
|
|
2607
|
-
row.networkImage,
|
|
2608
|
-
'ok-native-list-media-network'
|
|
2609
|
-
);
|
|
2610
|
-
if (network) subtitleLine.appendChild(network);
|
|
2611
|
-
}
|
|
2612
|
-
metadata.appendChild(subtitleLine);
|
|
2613
|
-
metadata.appendChild(
|
|
2614
|
-
createElement(
|
|
2615
|
-
context.document,
|
|
2616
|
-
'div',
|
|
2617
|
-
'ok-native-list-media-title',
|
|
2618
|
-
row.title
|
|
2619
|
-
)
|
|
2620
|
-
);
|
|
2621
|
-
if (row.badge) metadata.appendChild(createBadge(context, row.badge));
|
|
2622
|
-
body.appendChild(metadata);
|
|
2623
|
-
if (row.closeActionKey) {
|
|
2624
|
-
const close = createElement(
|
|
2625
|
-
context.document,
|
|
2626
|
-
'button',
|
|
2627
|
-
'ok-native-list-media-close',
|
|
2628
|
-
'×'
|
|
2629
|
-
);
|
|
2630
|
-
close.setAttribute('type', 'button');
|
|
2631
|
-
close.setAttribute('aria-label', 'Close');
|
|
2632
|
-
setData(close, 'nativeListAction', row.closeActionKey);
|
|
2633
|
-
markActionAnchorSource(close, 'mediaClose');
|
|
2634
|
-
body.appendChild(close);
|
|
2635
|
-
}
|
|
2636
|
-
return body;
|
|
2637
|
-
}
|
|
2638
|
-
|
|
2639
|
-
function createMetricCell(
|
|
2640
|
-
context: RenderContext,
|
|
2641
|
-
metric: NonNullable<
|
|
2642
|
-
Extract<RowModel, { type: 'metricCard' }>['metrics']
|
|
2643
|
-
>[number],
|
|
2644
|
-
shaded: boolean
|
|
2645
|
-
): HTMLElement {
|
|
2646
|
-
const cell = createElement(
|
|
2647
|
-
context.document,
|
|
2648
|
-
'div',
|
|
2649
|
-
'ok-native-list-composite-cell'
|
|
2650
|
-
);
|
|
2651
|
-
setData(cell, 'shaded', shaded);
|
|
2652
|
-
cell.appendChild(
|
|
2653
|
-
createElement(
|
|
2654
|
-
context.document,
|
|
2655
|
-
'div',
|
|
2656
|
-
'ok-native-list-secondary',
|
|
2657
|
-
metric.label
|
|
2658
|
-
)
|
|
2659
|
-
);
|
|
2660
|
-
const valueLine = createElement(context.document, 'div');
|
|
2661
|
-
valueLine.style.display = 'flex';
|
|
2662
|
-
valueLine.style.alignItems = 'center';
|
|
2663
|
-
valueLine.style.gap = '6px';
|
|
2664
|
-
if (metric.visual) {
|
|
2665
|
-
const visual = createVisual(context, metric.visual);
|
|
2666
|
-
if (visual) {
|
|
2667
|
-
visual.style.width = '16px';
|
|
2668
|
-
visual.style.height = '16px';
|
|
2669
|
-
visual.style.flexBasis = '16px';
|
|
2670
|
-
const image = visual.querySelector('img');
|
|
2671
|
-
if (image) {
|
|
2672
|
-
image.style.width = '16px';
|
|
2673
|
-
image.style.height = '16px';
|
|
2674
|
-
}
|
|
2675
|
-
valueLine.appendChild(visual);
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
const value = createElement(
|
|
2679
|
-
context.document,
|
|
2680
|
-
'span',
|
|
2681
|
-
'ok-native-list-composite-value',
|
|
2682
|
-
metric.value
|
|
2683
|
-
);
|
|
2684
|
-
value.style.color = toneColor(metric.tone, 'primary');
|
|
2685
|
-
valueLine.appendChild(value);
|
|
2686
|
-
cell.appendChild(valueLine);
|
|
2687
|
-
return cell;
|
|
2688
|
-
}
|
|
2689
|
-
|
|
2690
|
-
function createMetricRow(
|
|
2691
|
-
context: RenderContext,
|
|
2692
|
-
row: Extract<RowModel, { type: 'metricCard' }>
|
|
2693
|
-
): HTMLElement {
|
|
2694
|
-
if (row.variant === 'activity' || row.variant === 'performance') {
|
|
2695
|
-
const body = createElement(
|
|
2696
|
-
context.document,
|
|
2697
|
-
'div',
|
|
2698
|
-
'ok-native-list-row ok-native-list-composite'
|
|
2699
|
-
);
|
|
2700
|
-
body.appendChild(
|
|
2701
|
-
createElement(
|
|
2702
|
-
context.document,
|
|
2703
|
-
'div',
|
|
2704
|
-
'ok-native-list-composite-heading',
|
|
2705
|
-
row.title
|
|
2706
|
-
)
|
|
2707
|
-
);
|
|
2708
|
-
const metrics = row.metrics ?? [];
|
|
2709
|
-
const firstLine = createElement(
|
|
2710
|
-
context.document,
|
|
2711
|
-
'div',
|
|
2712
|
-
'ok-native-list-composite-row'
|
|
2713
|
-
);
|
|
2714
|
-
metrics
|
|
2715
|
-
.slice(0, 2)
|
|
2716
|
-
.forEach((metric) =>
|
|
2717
|
-
firstLine.appendChild(createMetricCell(context, metric, false))
|
|
2718
|
-
);
|
|
2719
|
-
body.appendChild(firstLine);
|
|
2720
|
-
if (row.variant === 'activity') {
|
|
2721
|
-
body.appendChild(
|
|
2722
|
-
createElement(context.document, 'div', 'ok-native-list-divider')
|
|
2723
|
-
);
|
|
2724
|
-
} else {
|
|
2725
|
-
const progress = createElement(
|
|
2726
|
-
context.document,
|
|
2727
|
-
'div',
|
|
2728
|
-
'ok-native-list-progress'
|
|
2729
|
-
);
|
|
2730
|
-
const fill = createElement(context.document, 'span');
|
|
2731
|
-
fill.style.width = String(Math.round((row.progress ?? 0) * 100)) + '%';
|
|
2732
|
-
progress.appendChild(fill);
|
|
2733
|
-
body.appendChild(progress);
|
|
2734
|
-
}
|
|
2735
|
-
const secondLine = createElement(
|
|
2736
|
-
context.document,
|
|
2737
|
-
'div',
|
|
2738
|
-
'ok-native-list-composite-row'
|
|
2739
|
-
);
|
|
2740
|
-
metrics
|
|
2741
|
-
.slice(2)
|
|
2742
|
-
.forEach((metric) =>
|
|
2743
|
-
secondLine.appendChild(
|
|
2744
|
-
createMetricCell(context, metric, row.variant === 'performance')
|
|
2745
|
-
)
|
|
2746
|
-
);
|
|
2747
|
-
body.appendChild(secondLine);
|
|
2748
|
-
return body;
|
|
2749
|
-
}
|
|
2750
|
-
|
|
2751
|
-
const body = createElement(
|
|
2752
|
-
context.document,
|
|
2753
|
-
'div',
|
|
2754
|
-
'ok-native-list-row ok-native-list-metric'
|
|
2755
|
-
);
|
|
2756
|
-
if (row.visual) {
|
|
2757
|
-
const visual = createVisual(context, row.visual);
|
|
2758
|
-
if (visual) body.appendChild(visual);
|
|
2759
|
-
}
|
|
2760
|
-
body.appendChild(
|
|
2761
|
-
createElement(
|
|
2762
|
-
context.document,
|
|
2763
|
-
'div',
|
|
2764
|
-
'ok-native-list-secondary',
|
|
2765
|
-
row.title
|
|
2766
|
-
)
|
|
2767
|
-
);
|
|
2768
|
-
body.appendChild(
|
|
2769
|
-
createElement(
|
|
2770
|
-
context.document,
|
|
2771
|
-
'div',
|
|
2772
|
-
'ok-native-list-metric-value',
|
|
2773
|
-
row.value
|
|
2774
|
-
)
|
|
2775
|
-
);
|
|
2776
|
-
if (row.trend) {
|
|
2777
|
-
const trend = createElement(
|
|
2778
|
-
context.document,
|
|
2779
|
-
'div',
|
|
2780
|
-
'ok-native-list-secondary',
|
|
2781
|
-
row.trend
|
|
2782
|
-
);
|
|
2783
|
-
trend.style.color =
|
|
2784
|
-
row.trendTone === 'positive'
|
|
2785
|
-
? 'var(--nl-positive)'
|
|
2786
|
-
: row.trendTone === 'negative'
|
|
2787
|
-
? 'var(--nl-negative)'
|
|
2788
|
-
: 'var(--nl-secondary)';
|
|
2789
|
-
body.appendChild(trend);
|
|
2790
|
-
}
|
|
2791
|
-
if (row.subtitle)
|
|
2792
|
-
body.appendChild(
|
|
2793
|
-
createElement(
|
|
2794
|
-
context.document,
|
|
2795
|
-
'div',
|
|
2796
|
-
'ok-native-list-secondary',
|
|
2797
|
-
row.subtitle
|
|
2798
|
-
)
|
|
2799
|
-
);
|
|
2800
|
-
if (row.badge) body.appendChild(createBadge(context, row.badge));
|
|
2801
|
-
return body;
|
|
2802
|
-
}
|
|
2803
|
-
|
|
2804
|
-
function createDataRow(
|
|
2805
|
-
context: RenderContext,
|
|
2806
|
-
row: Extract<RowModel, { type: 'dataRow' }>
|
|
2807
|
-
): HTMLElement {
|
|
2808
|
-
const body = createElement(
|
|
2809
|
-
context.document,
|
|
2810
|
-
'div',
|
|
2811
|
-
'ok-native-list-row ok-native-list-data'
|
|
2812
|
-
);
|
|
2813
|
-
if (row.checkbox)
|
|
2814
|
-
body.appendChild(createCheckbox(context, row.key, row.checkbox));
|
|
2815
|
-
if (row.index !== undefined)
|
|
2816
|
-
body.appendChild(
|
|
2817
|
-
createElement(
|
|
2818
|
-
context.document,
|
|
2819
|
-
'span',
|
|
2820
|
-
'ok-native-list-index',
|
|
2821
|
-
String(row.index)
|
|
2822
|
-
)
|
|
2823
|
-
);
|
|
2824
|
-
if (row.favorite) {
|
|
2825
|
-
const favorite = createElement(
|
|
2826
|
-
context.document,
|
|
2827
|
-
'span',
|
|
2828
|
-
'ok-native-list-favorite',
|
|
2829
|
-
row.favoriteActive ? '★' : '☆'
|
|
2830
|
-
);
|
|
2831
|
-
setData(favorite, 'active', row.favoriteActive);
|
|
2832
|
-
body.appendChild(favorite);
|
|
2833
|
-
}
|
|
2834
|
-
if (row.leading) {
|
|
2835
|
-
const visual = createVisual(context, row.leading);
|
|
2836
|
-
if (visual) body.appendChild(visual);
|
|
2837
|
-
}
|
|
2838
|
-
row.columns.forEach((column) => {
|
|
2839
|
-
const cell = createElement(
|
|
2840
|
-
context.document,
|
|
2841
|
-
'span',
|
|
2842
|
-
'ok-native-list-data-cell'
|
|
2843
|
-
);
|
|
2844
|
-
cell.style.flex = String(column.weight ?? 1);
|
|
2845
|
-
setData(cell, 'align', column.alignment ?? 'start');
|
|
2846
|
-
const primary = createElement(
|
|
2847
|
-
context.document,
|
|
2848
|
-
'span',
|
|
2849
|
-
'ok-native-list-data-primary'
|
|
2850
|
-
);
|
|
2851
|
-
primary.style.color = toneColor(column.tone, 'primary');
|
|
2852
|
-
if (column.secondaryLeadingText)
|
|
2853
|
-
primary.appendChild(
|
|
2854
|
-
createElement(
|
|
2855
|
-
context.document,
|
|
2856
|
-
'span',
|
|
2857
|
-
'ok-native-list-secondary',
|
|
2858
|
-
column.secondaryLeadingText
|
|
2859
|
-
)
|
|
2860
|
-
);
|
|
2861
|
-
primary.appendChild(
|
|
2862
|
-
createElement(context.document, 'span', undefined, column.text)
|
|
2863
|
-
);
|
|
2864
|
-
if (column.key === 'asset' && row.badges?.length) {
|
|
2865
|
-
row.badges.forEach((badge) =>
|
|
2866
|
-
primary.appendChild(createBadge(context, badge))
|
|
2867
|
-
);
|
|
2868
|
-
}
|
|
2869
|
-
cell.appendChild(primary);
|
|
2870
|
-
if (column.secondaryText) {
|
|
2871
|
-
const secondary = createElement(
|
|
2872
|
-
context.document,
|
|
2873
|
-
'span',
|
|
2874
|
-
'ok-native-list-secondary',
|
|
2875
|
-
column.secondaryText
|
|
2876
|
-
);
|
|
2877
|
-
secondary.style.color = toneColor(column.secondaryTone, 'secondary');
|
|
2878
|
-
cell.appendChild(secondary);
|
|
2879
|
-
}
|
|
2880
|
-
body.appendChild(cell);
|
|
2881
|
-
});
|
|
2882
|
-
return body;
|
|
2883
|
-
}
|
|
2884
|
-
|
|
2885
|
-
function createIdentityActivityOrMessageRow(
|
|
2886
|
-
context: RenderContext,
|
|
2887
|
-
row: Extract<RowModel, { type: 'identity' | 'activity' | 'message' }>
|
|
2888
|
-
): HTMLElement {
|
|
2889
|
-
const presentation = row.type === 'identity' ? row.presentation : undefined;
|
|
2890
|
-
const body = createElement(
|
|
2891
|
-
context.document,
|
|
2892
|
-
'div',
|
|
2893
|
-
[
|
|
2894
|
-
'ok-native-list-row',
|
|
2895
|
-
'ok-native-list-standard',
|
|
2896
|
-
row.type === 'identity' && !presentation
|
|
2897
|
-
? 'ok-native-list-identity-row'
|
|
2898
|
-
: '',
|
|
2899
|
-
presentation === 'networkSelector' ? 'ok-native-list-network-row' : '',
|
|
2900
|
-
presentation === 'walletSidebar' ? 'ok-native-list-wallet-row' : '',
|
|
2901
|
-
presentation === 'accountSelector' ? 'ok-native-list-account-row' : '',
|
|
2902
|
-
]
|
|
2903
|
-
.filter(Boolean)
|
|
2904
|
-
.join(' ')
|
|
2905
|
-
);
|
|
2906
|
-
setData(
|
|
2907
|
-
body,
|
|
2908
|
-
'nativeListSelector',
|
|
2909
|
-
row.height !== undefined ? presentation : undefined
|
|
2910
|
-
);
|
|
2911
|
-
if (row.type === 'identity' && row.titleActionKey && row.titleActionOnHover) {
|
|
2912
|
-
setData(body, 'nativeListHoverAction', row.titleActionKey);
|
|
2913
|
-
markActionAnchorSource(body, 'leadingAction');
|
|
2914
|
-
}
|
|
2915
|
-
if (row.type === 'identity' && row.leadingAction) {
|
|
2916
|
-
const action = createIconAction(
|
|
2917
|
-
context,
|
|
2918
|
-
row.leadingAction.name,
|
|
2919
|
-
row.leadingAction.actionKey,
|
|
2920
|
-
row.leadingAction.disabled,
|
|
2921
|
-
row.leadingAction.tintColor
|
|
2922
|
-
);
|
|
2923
|
-
markActionAnchorSource(action, 'leadingAction');
|
|
2924
|
-
body.appendChild(action);
|
|
2925
|
-
}
|
|
2926
|
-
const visual = createVisual(
|
|
2927
|
-
context,
|
|
2928
|
-
visualFromRow(row),
|
|
2929
|
-
row.height !== undefined ? presentation : undefined
|
|
2930
|
-
);
|
|
2931
|
-
if (
|
|
2932
|
-
visual &&
|
|
2933
|
-
row.type === 'identity' &&
|
|
2934
|
-
row.height !== undefined &&
|
|
2935
|
-
row.presentation === 'walletSidebar' &&
|
|
2936
|
-
'fallbackIcon' in row.leading &&
|
|
2937
|
-
row.leading.fallbackIcon?.name === 'LockSolid'
|
|
2938
|
-
) {
|
|
2939
|
-
// OneKey patch: hidden-wallet locks use WalletAvatar's full 40-point icon.
|
|
2940
|
-
const icon = visual.querySelector<SVGElement>(
|
|
2941
|
-
'.ok-native-list-visual-fallback svg'
|
|
2942
|
-
);
|
|
2943
|
-
if (icon) {
|
|
2944
|
-
icon.style.width = '40px';
|
|
2945
|
-
icon.style.height = '40px';
|
|
2946
|
-
}
|
|
2947
|
-
const fallback = visual.querySelector<HTMLElement>(
|
|
2948
|
-
'.ok-native-list-visual-fallback'
|
|
2949
|
-
);
|
|
2950
|
-
if (fallback) {
|
|
2951
|
-
fallback.style.borderRadius = '0';
|
|
2952
|
-
fallback.style.overflow = 'visible';
|
|
2953
|
-
}
|
|
2954
|
-
}
|
|
2955
|
-
if (
|
|
2956
|
-
visual &&
|
|
2957
|
-
row.type === 'identity' &&
|
|
2958
|
-
row.height !== undefined &&
|
|
2959
|
-
row.presentation === 'walletSidebar' &&
|
|
2960
|
-
'borderStyle' in row.leading &&
|
|
2961
|
-
row.leading.borderStyle === 'dashed'
|
|
2962
|
-
)
|
|
2963
|
-
visual.style.borderWidth = '1px';
|
|
2964
|
-
if (visual) body.appendChild(visual);
|
|
2965
|
-
if (row.type === 'activity' && row.secondaryLeading) {
|
|
2966
|
-
const secondVisual = createVisual(context, row.secondaryLeading);
|
|
2967
|
-
if (secondVisual) body.appendChild(secondVisual);
|
|
2968
|
-
}
|
|
2969
|
-
if (row.type === 'message' && row.unread)
|
|
2970
|
-
body.appendChild(
|
|
2971
|
-
createElement(context.document, 'span', 'ok-native-list-unread')
|
|
2972
|
-
);
|
|
2973
|
-
const title = row.title;
|
|
2974
|
-
const subtitle =
|
|
2975
|
-
row.type === 'identity'
|
|
2976
|
-
? row.subtitle
|
|
2977
|
-
: row.type === 'activity'
|
|
2978
|
-
? row.description
|
|
2979
|
-
: row.body;
|
|
2980
|
-
const column = createTextColumn(
|
|
2981
|
-
context,
|
|
2982
|
-
title,
|
|
2983
|
-
subtitle,
|
|
2984
|
-
row.type === 'identity' ? row.tertiary : undefined,
|
|
2985
|
-
row.type === 'identity' ? row.tertiaryTone : undefined,
|
|
2986
|
-
row.type === 'identity' && presentation !== 'walletSidebar'
|
|
2987
|
-
? row.badges
|
|
2988
|
-
: undefined
|
|
2989
|
-
);
|
|
2990
|
-
// OneKey patch: match existing search, subtitle fragments, and sidebar badges.
|
|
2991
|
-
if (row.type === 'identity') {
|
|
2992
|
-
const titleElement = column.firstElementChild as HTMLElement;
|
|
2993
|
-
if (row.titleMatch?.length) {
|
|
2994
|
-
const firstText = titleElement.firstChild;
|
|
2995
|
-
if (firstText) firstText.remove();
|
|
2996
|
-
const fragment = context.document.createDocumentFragment();
|
|
2997
|
-
let offset = 0;
|
|
2998
|
-
row.titleMatch.forEach(({ start, end }) => {
|
|
2999
|
-
fragment.appendChild(
|
|
3000
|
-
context.document.createTextNode(row.title.slice(offset, start))
|
|
3001
|
-
);
|
|
3002
|
-
const match = createElement(
|
|
3003
|
-
context.document,
|
|
3004
|
-
'span',
|
|
3005
|
-
'ok-native-list-info',
|
|
3006
|
-
row.title.slice(start, end)
|
|
3007
|
-
);
|
|
3008
|
-
fragment.appendChild(match);
|
|
3009
|
-
offset = end;
|
|
3010
|
-
});
|
|
3011
|
-
fragment.appendChild(
|
|
3012
|
-
context.document.createTextNode(row.title.slice(offset))
|
|
3013
|
-
);
|
|
3014
|
-
titleElement.prepend(fragment);
|
|
3015
|
-
}
|
|
3016
|
-
if (row.subtitleSegments?.length) {
|
|
3017
|
-
column.querySelector('.ok-native-list-secondary')?.remove();
|
|
3018
|
-
const segments = createElement(
|
|
3019
|
-
context.document,
|
|
3020
|
-
'span',
|
|
3021
|
-
'ok-native-list-subtitle-segments'
|
|
3022
|
-
);
|
|
3023
|
-
row.subtitleSegments.forEach((segment) => {
|
|
3024
|
-
if (segment.separatorBefore)
|
|
3025
|
-
segments.appendChild(
|
|
3026
|
-
createElement(
|
|
3027
|
-
context.document,
|
|
3028
|
-
'span',
|
|
3029
|
-
'ok-native-list-subtitle-dot'
|
|
3030
|
-
)
|
|
3031
|
-
);
|
|
3032
|
-
const text = createElement(
|
|
3033
|
-
context.document,
|
|
3034
|
-
'span',
|
|
3035
|
-
'ok-native-list-secondary',
|
|
3036
|
-
segment.text
|
|
3037
|
-
);
|
|
3038
|
-
applyValueSegments(text, segment.textSegments, 14, 20, 400);
|
|
3039
|
-
setData(text, 'tone', segment.tone);
|
|
3040
|
-
text.style.color =
|
|
3041
|
-
segment.tone === 'disabled'
|
|
3042
|
-
? 'var(--nl-disabled)'
|
|
3043
|
-
: segment.tone === 'caution'
|
|
3044
|
-
? 'var(--nl-caution)'
|
|
3045
|
-
: toneColor(segment.tone, 'secondary');
|
|
3046
|
-
segments.appendChild(text);
|
|
3047
|
-
});
|
|
3048
|
-
column.insertBefore(segments, titleElement.nextSibling);
|
|
3049
|
-
}
|
|
3050
|
-
if (presentation === 'walletSidebar' && row.badges?.length) {
|
|
3051
|
-
const badges = createElement(
|
|
3052
|
-
context.document,
|
|
3053
|
-
'span',
|
|
3054
|
-
'ok-native-list-wallet-badges'
|
|
3055
|
-
);
|
|
3056
|
-
row.badges.forEach((badge) =>
|
|
3057
|
-
badges.appendChild(createBadge(context, badge))
|
|
3058
|
-
);
|
|
3059
|
-
column.appendChild(badges);
|
|
3060
|
-
}
|
|
3061
|
-
}
|
|
3062
|
-
if (row.type === 'activity' && row.status)
|
|
3063
|
-
column.appendChild(
|
|
3064
|
-
createElement(
|
|
3065
|
-
context.document,
|
|
3066
|
-
'span',
|
|
3067
|
-
'ok-native-list-secondary',
|
|
3068
|
-
row.status
|
|
3069
|
-
)
|
|
3070
|
-
);
|
|
3071
|
-
if (row.type === 'activity' && row.footerActions?.length) {
|
|
3072
|
-
const actions = createElement(
|
|
3073
|
-
context.document,
|
|
3074
|
-
'span',
|
|
3075
|
-
'ok-native-list-actions'
|
|
3076
|
-
);
|
|
3077
|
-
row.footerActions.forEach((action, slot) => {
|
|
3078
|
-
const button = createElement(
|
|
3079
|
-
context.document,
|
|
3080
|
-
'button',
|
|
3081
|
-
'ok-native-list-action-button',
|
|
3082
|
-
action.label
|
|
3083
|
-
);
|
|
3084
|
-
button.setAttribute('type', 'button');
|
|
3085
|
-
button.toggleAttribute('disabled', Boolean(action.disabled));
|
|
3086
|
-
setData(button, 'tone', action.tone);
|
|
3087
|
-
setData(button, 'nativeListAction', action.key);
|
|
3088
|
-
markActionAnchorSource(button, 'footerAction', slot);
|
|
3089
|
-
actions.appendChild(button);
|
|
3090
|
-
});
|
|
3091
|
-
column.appendChild(actions);
|
|
3092
|
-
}
|
|
3093
|
-
body.appendChild(column);
|
|
3094
|
-
if (row.type === 'activity') {
|
|
3095
|
-
const amounts = createElement(
|
|
3096
|
-
context.document,
|
|
3097
|
-
'span',
|
|
3098
|
-
'ok-native-list-amounts'
|
|
3099
|
-
);
|
|
3100
|
-
if (row.primaryAmount)
|
|
3101
|
-
amounts.appendChild(
|
|
3102
|
-
createElement(
|
|
3103
|
-
context.document,
|
|
3104
|
-
'span',
|
|
3105
|
-
'ok-native-list-value',
|
|
3106
|
-
row.primaryAmount
|
|
3107
|
-
)
|
|
3108
|
-
);
|
|
3109
|
-
if (row.secondaryAmount)
|
|
3110
|
-
amounts.appendChild(
|
|
3111
|
-
createElement(
|
|
3112
|
-
context.document,
|
|
3113
|
-
'span',
|
|
3114
|
-
'ok-native-list-secondary',
|
|
3115
|
-
row.secondaryAmount
|
|
3116
|
-
)
|
|
3117
|
-
);
|
|
3118
|
-
body.appendChild(amounts);
|
|
3119
|
-
} else if (row.type === 'message') {
|
|
3120
|
-
body.appendChild(
|
|
3121
|
-
createElement(context.document, 'span', 'ok-native-list-time', row.time)
|
|
3122
|
-
);
|
|
3123
|
-
if (row.thumbnail) {
|
|
3124
|
-
const thumbnail = createImage(
|
|
3125
|
-
context,
|
|
3126
|
-
row.thumbnail,
|
|
3127
|
-
'ok-native-list-thumbnail'
|
|
3128
|
-
);
|
|
3129
|
-
if (thumbnail) body.appendChild(thumbnail);
|
|
1728
|
+
);
|
|
1729
|
+
element.setAttribute('type', 'button');
|
|
1730
|
+
element.setAttribute('role', 'checkbox');
|
|
1731
|
+
element.setAttribute(
|
|
1732
|
+
'aria-checked',
|
|
1733
|
+
state === 'indeterminate' ? 'mixed' : String(state === 'checked')
|
|
1734
|
+
);
|
|
1735
|
+
element.setAttribute('aria-label', 'Select');
|
|
1736
|
+
element.toggleAttribute('disabled', Boolean(accessory.disabled));
|
|
1737
|
+
setData(element, 'state', state);
|
|
1738
|
+
setData(element, 'checkboxFallback', accessory.state);
|
|
1739
|
+
setData(element, 'nativeListAction', accessory.actionKey ?? 'selection');
|
|
1740
|
+
setData(element, 'selectionScope', accessory.target?.scope ?? 'row');
|
|
1741
|
+
const row = context.snapshot.rows[context.itemIndex];
|
|
1742
|
+
if (row && 'presentation' in row && row.presentation === 'networkSelector') {
|
|
1743
|
+
setData(element, 'selector', 'networkSelector');
|
|
1744
|
+
for (const [state, name] of [
|
|
1745
|
+
['checked', 'CheckboxCheckedCustom'],
|
|
1746
|
+
['indeterminate', 'CheckboxIndeterminateCustom'],
|
|
1747
|
+
]) {
|
|
1748
|
+
const holder = createElement(context.document, 'span');
|
|
1749
|
+
applySelectorIcon(holder, name);
|
|
1750
|
+
const svg = holder.firstElementChild;
|
|
1751
|
+
if (svg) {
|
|
1752
|
+
svg.setAttribute('data-state', state);
|
|
1753
|
+
element.appendChild(svg);
|
|
1754
|
+
}
|
|
3130
1755
|
}
|
|
3131
|
-
} else {
|
|
3132
|
-
appendAccessories(body, context, row.key, row.trailing);
|
|
3133
1756
|
}
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
if (
|
|
3140
|
-
!('presentation' in row) ||
|
|
3141
|
-
!['accountSelector', 'networkSelector', 'walletSidebar'].includes(
|
|
3142
|
-
row.presentation ?? ''
|
|
3143
|
-
)
|
|
3144
|
-
)
|
|
3145
|
-
return;
|
|
3146
|
-
body.style.fontVariantNumeric = 'tabular-nums';
|
|
3147
|
-
body.querySelectorAll<HTMLElement>('span,button').forEach((text) => {
|
|
3148
|
-
text.style.fontVariantNumeric = 'tabular-nums';
|
|
3149
|
-
});
|
|
1757
|
+
if (accessory.target?.scope === 'section')
|
|
1758
|
+
setData(element, 'selectionKey', accessory.target.sectionKey);
|
|
1759
|
+
else if (accessory.target?.scope === 'row')
|
|
1760
|
+
setData(element, 'selectionKey', rowKey);
|
|
1761
|
+
return element;
|
|
3150
1762
|
}
|
|
3151
1763
|
|
|
3152
|
-
function
|
|
1764
|
+
function createIconAction(
|
|
3153
1765
|
context: RenderContext,
|
|
3154
|
-
|
|
1766
|
+
name: string,
|
|
1767
|
+
actionKey: string | undefined,
|
|
1768
|
+
disabled?: boolean,
|
|
1769
|
+
tintColor?: string
|
|
3155
1770
|
): HTMLElement {
|
|
3156
|
-
const
|
|
1771
|
+
const element = createElement(
|
|
3157
1772
|
context.document,
|
|
3158
|
-
'
|
|
3159
|
-
'ok-native-list-
|
|
1773
|
+
actionKey ? 'button' : 'span',
|
|
1774
|
+
'ok-native-list-icon-button',
|
|
1775
|
+
iconGlyph(name)
|
|
3160
1776
|
);
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
setData(memberElement, 'nativeListGroupParent', memberIndex === 0);
|
|
3170
|
-
setData(memberElement, 'nativeListSelected', member.selected);
|
|
3171
|
-
// OneKey patch: grouped members have the same selector typography as standalone wallets.
|
|
3172
|
-
// memberElement.appendChild(createIdentityActivityOrMessageRow(context, member));
|
|
3173
|
-
const memberBody = createIdentityActivityOrMessageRow(context, member);
|
|
3174
|
-
applySelectorTabularNumbers(memberBody, member);
|
|
3175
|
-
memberElement.appendChild(memberBody);
|
|
3176
|
-
// OneKey patch: group children use their own measured badge height.
|
|
3177
|
-
memberElement.style.flexBasis =
|
|
3178
|
-
String(member.height ?? 68 + (member.badges?.length ? 24 : 0)) + 'px';
|
|
3179
|
-
memberElement.style.height = memberElement.style.flexBasis;
|
|
3180
|
-
memberElement.style.opacity = String(member.opacity ?? 1);
|
|
3181
|
-
body.appendChild(memberElement);
|
|
3182
|
-
});
|
|
3183
|
-
return body;
|
|
3184
|
-
}
|
|
3185
|
-
|
|
3186
|
-
function marketFontWeight(
|
|
3187
|
-
value: MarketTextStyle['fontWeight'] | undefined,
|
|
3188
|
-
fallback: number
|
|
3189
|
-
): number {
|
|
3190
|
-
if (value === 'bold') return 700;
|
|
3191
|
-
if (value === 'semibold') return 600;
|
|
3192
|
-
if (value === 'medium') return 500;
|
|
3193
|
-
if (value === 'regular') return 400;
|
|
3194
|
-
return fallback;
|
|
1777
|
+
if (element.tagName === 'BUTTON') {
|
|
1778
|
+
element.setAttribute('type', 'button');
|
|
1779
|
+
element.toggleAttribute('disabled', Boolean(disabled));
|
|
1780
|
+
}
|
|
1781
|
+
applySelectorIcon(element, name);
|
|
1782
|
+
if (actionKey) setData(element, 'nativeListAction', actionKey);
|
|
1783
|
+
if (tintColor) element.style.color = tintColor;
|
|
1784
|
+
return element;
|
|
3195
1785
|
}
|
|
3196
1786
|
|
|
3197
|
-
function
|
|
1787
|
+
function markActionAnchorSource(
|
|
3198
1788
|
element: HTMLElement,
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
fontSize: number;
|
|
3202
|
-
lineHeight: number;
|
|
3203
|
-
weight: number;
|
|
3204
|
-
alignment: 'start' | 'center' | 'end';
|
|
3205
|
-
}>
|
|
1789
|
+
source: NativeListActionSource,
|
|
1790
|
+
slot?: number
|
|
3206
1791
|
) {
|
|
3207
|
-
element
|
|
3208
|
-
element
|
|
3209
|
-
String(style?.lineHeight ?? defaults.lineHeight) + 'px';
|
|
3210
|
-
element.style.fontWeight = String(
|
|
3211
|
-
marketFontWeight(style?.fontWeight, defaults.weight)
|
|
3212
|
-
);
|
|
3213
|
-
element.style.color = style?.color ?? '';
|
|
3214
|
-
element.style.textAlign = style?.alignment ?? defaults.alignment;
|
|
3215
|
-
element.style.whiteSpace = style?.lines === 2 ? 'normal' : 'nowrap';
|
|
3216
|
-
element.style.display = '';
|
|
3217
|
-
element.style.removeProperty('-webkit-line-clamp');
|
|
3218
|
-
element.style.removeProperty('-webkit-box-orient');
|
|
3219
|
-
if (style?.lines === 2) {
|
|
3220
|
-
element.style.display = '-webkit-box';
|
|
3221
|
-
element.style.setProperty('-webkit-line-clamp', '2');
|
|
3222
|
-
element.style.setProperty('-webkit-box-orient', 'vertical');
|
|
3223
|
-
}
|
|
1792
|
+
setData(element, 'nativeListAnchorSource', source);
|
|
1793
|
+
if (slot !== undefined) setData(element, 'nativeListAnchorSlot', slot);
|
|
3224
1794
|
}
|
|
3225
1795
|
|
|
3226
|
-
|
|
3227
|
-
const style = row.style;
|
|
3228
|
-
const layoutStyle = resolveWebMarketLayoutStyle(row);
|
|
3229
|
-
const price = element.querySelector<HTMLElement>(
|
|
3230
|
-
'.ok-native-list-market-price'
|
|
3231
|
-
);
|
|
3232
|
-
if (price) {
|
|
3233
|
-
price.textContent = row.price;
|
|
3234
|
-
applyMarketTextStyle(price, style?.price, {
|
|
3235
|
-
fontSize: 16,
|
|
3236
|
-
lineHeight: 24,
|
|
3237
|
-
weight: 500,
|
|
3238
|
-
alignment: 'end',
|
|
3239
|
-
});
|
|
3240
|
-
applyValueSegments(
|
|
3241
|
-
price,
|
|
3242
|
-
row.priceSegments,
|
|
3243
|
-
style?.price?.fontSize ?? 16,
|
|
3244
|
-
style?.price?.lineHeight ?? 24,
|
|
3245
|
-
marketFontWeight(style?.price?.fontWeight, 500)
|
|
3246
|
-
);
|
|
3247
|
-
}
|
|
3248
|
-
const change = element.querySelector<HTMLElement>(
|
|
3249
|
-
'.ok-native-list-market-change'
|
|
3250
|
-
);
|
|
3251
|
-
if (change) {
|
|
3252
|
-
change.textContent = row.change.text;
|
|
3253
|
-
setData(change, 'tone', row.change.tone);
|
|
3254
|
-
applyMarketTextStyle(change, style?.change, {
|
|
3255
|
-
fontSize: 14,
|
|
3256
|
-
lineHeight: 20,
|
|
3257
|
-
weight: 500,
|
|
3258
|
-
alignment: 'center',
|
|
3259
|
-
});
|
|
3260
|
-
applyValueSegments(
|
|
3261
|
-
change,
|
|
3262
|
-
row.change.textSegments,
|
|
3263
|
-
style?.change?.fontSize ?? 14,
|
|
3264
|
-
style?.change?.lineHeight ?? 20,
|
|
3265
|
-
marketFontWeight(style?.change?.fontWeight, 500)
|
|
3266
|
-
);
|
|
3267
|
-
change.style.width = String(layoutStyle.changeWidth) + 'px';
|
|
3268
|
-
change.style.height = String(layoutStyle.changeHeight) + 'px';
|
|
3269
|
-
change.style.borderRadius = String(layoutStyle.changeCornerRadius) + 'px';
|
|
3270
|
-
change.style.color = row.change.textColor ?? style?.change?.color ?? '';
|
|
3271
|
-
change.style.background = row.change.backgroundColor ?? '';
|
|
3272
|
-
}
|
|
3273
|
-
element.setAttribute(
|
|
3274
|
-
'aria-label',
|
|
3275
|
-
row.accessibilityLabel ??
|
|
3276
|
-
[row.title, row.subtitle, row.price, row.change.text]
|
|
3277
|
-
.filter(Boolean)
|
|
3278
|
-
.join(', ')
|
|
3279
|
-
);
|
|
3280
|
-
}
|
|
1796
|
+
// OneKey patch: the compact zero-count digits share the amount baseline.
|
|
3281
1797
|
|
|
3282
|
-
function
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
'px';
|
|
3296
|
-
body.style.gap = '0px';
|
|
3297
|
-
if (row.leadingAction) {
|
|
3298
|
-
const action = createIconAction(
|
|
1798
|
+
function createAccessory(
|
|
1799
|
+
context: RenderContext,
|
|
1800
|
+
rowKey: string,
|
|
1801
|
+
accessory: TrailingAccessory,
|
|
1802
|
+
slot: number
|
|
1803
|
+
): HTMLElement {
|
|
1804
|
+
if (accessory.kind === 'checkbox') {
|
|
1805
|
+
const element = createCheckbox(context, rowKey, accessory);
|
|
1806
|
+
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1807
|
+
return element;
|
|
1808
|
+
}
|
|
1809
|
+
if (accessory.kind === 'icon') {
|
|
1810
|
+
const element = createIconAction(
|
|
3299
1811
|
context,
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
1812
|
+
accessory.name,
|
|
1813
|
+
accessory.actionKey,
|
|
1814
|
+
accessory.disabled,
|
|
1815
|
+
accessory.tintColor
|
|
3304
1816
|
);
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
const borderColor =
|
|
3324
|
-
'borderColor' in row.leading ? row.leading.borderColor : undefined;
|
|
3325
|
-
if (borderColor) {
|
|
3326
|
-
visual.style.border = '1px solid ' + borderColor;
|
|
3327
|
-
visual.style.boxSizing = 'border-box';
|
|
3328
|
-
}
|
|
3329
|
-
visual.querySelectorAll<HTMLElement>('img').forEach((image) => {
|
|
3330
|
-
if (!image.classList.contains('ok-native-list-visual-corner')) {
|
|
3331
|
-
image.style.width = '100%';
|
|
3332
|
-
image.style.height = '100%';
|
|
3333
|
-
if (borderColor) {
|
|
3334
|
-
image.style.borderRadius = '0';
|
|
3335
|
-
image.style.clipPath =
|
|
3336
|
-
'inset(-1px round ' + String(layoutStyle.imageCornerRadius) + 'px)';
|
|
3337
|
-
}
|
|
3338
|
-
image.style.objectFit =
|
|
3339
|
-
style?.image?.contentFit ?? image.style.objectFit;
|
|
3340
|
-
} else {
|
|
3341
|
-
image.style.width = '20px';
|
|
3342
|
-
image.style.height = '20px';
|
|
3343
|
-
if (borderColor) {
|
|
3344
|
-
image.style.right = '-5px';
|
|
3345
|
-
image.style.bottom = '-5px';
|
|
3346
|
-
}
|
|
1817
|
+
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1818
|
+
setData(element, 'testid', accessory.testID);
|
|
1819
|
+
if (accessory.hoverActionKey)
|
|
1820
|
+
setData(element, 'nativeListHoverAction', accessory.hoverActionKey);
|
|
1821
|
+
if (accessory.accessibilityLabel)
|
|
1822
|
+
element.setAttribute('aria-label', accessory.accessibilityLabel);
|
|
1823
|
+
const row = context.snapshot.rows[context.itemIndex];
|
|
1824
|
+
if (
|
|
1825
|
+
row &&
|
|
1826
|
+
'presentation' in row &&
|
|
1827
|
+
row.presentation === 'accountSelector'
|
|
1828
|
+
) {
|
|
1829
|
+
setData(element, 'nativeListAnchorInset', 7);
|
|
1830
|
+
// OneKey patch: the create-address button omits IconButton's one-point border.
|
|
1831
|
+
if (hasExplicitRowHeight(row) && accessory.name === 'PlusSmallOutline') {
|
|
1832
|
+
setData(element, 'nativeListAccountControl', 'createAddress');
|
|
1833
|
+
if (!accessory.tintColor)
|
|
1834
|
+
element.style.color = 'var(--nl-icon-subdued)';
|
|
3347
1835
|
}
|
|
3348
|
-
}
|
|
3349
|
-
|
|
3350
|
-
body.appendChild(visual);
|
|
1836
|
+
}
|
|
1837
|
+
return element;
|
|
3351
1838
|
}
|
|
3352
|
-
|
|
3353
|
-
context.document,
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
main.style.gap = String(style?.lineGap ?? 0) + 'px';
|
|
3358
|
-
const titleLine = createElement(
|
|
3359
|
-
context.document,
|
|
3360
|
-
'span',
|
|
3361
|
-
'ok-native-list-market-title-line'
|
|
3362
|
-
);
|
|
3363
|
-
titleLine.style.gap = String(layoutStyle.titleBadgeGap) + 'px';
|
|
3364
|
-
const title = createElement(
|
|
1839
|
+
if (accessory.kind === 'spinner') {
|
|
1840
|
+
return createElement(context.document, 'span', 'ok-native-list-spinner');
|
|
1841
|
+
}
|
|
1842
|
+
const actionKey = 'actionKey' in accessory ? accessory.actionKey : undefined;
|
|
1843
|
+
const element = createElement(
|
|
3365
1844
|
context.document,
|
|
3366
|
-
'span',
|
|
3367
|
-
'ok-native-list-
|
|
3368
|
-
row.title
|
|
1845
|
+
actionKey ? 'button' : 'span',
|
|
1846
|
+
'ok-native-list-accessory'
|
|
3369
1847
|
);
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
if (badge.actionKey) {
|
|
3385
|
-
element.setAttribute('type', 'button');
|
|
3386
|
-
setData(element, 'nativeListAction', badge.actionKey);
|
|
3387
|
-
markActionAnchorSource(element, 'marketBadge', slot);
|
|
3388
|
-
}
|
|
3389
|
-
setData(element, 'tone', badge.tone);
|
|
3390
|
-
element.style.color =
|
|
3391
|
-
badge.textColor ??
|
|
3392
|
-
(badge.tone === 'success'
|
|
3393
|
-
? 'var(--nl-positive)'
|
|
3394
|
-
: badge.tone === 'danger'
|
|
3395
|
-
? 'var(--nl-negative)'
|
|
3396
|
-
: badge.tone === 'info'
|
|
3397
|
-
? 'var(--nl-info)'
|
|
3398
|
-
: badge.tone === 'warning'
|
|
3399
|
-
? 'var(--nl-primary)'
|
|
3400
|
-
: '');
|
|
3401
|
-
element.style.background =
|
|
3402
|
-
badge.backgroundColor ??
|
|
3403
|
-
((badge.icon || badge.iconName) && !badge.text ? 'transparent' : '');
|
|
3404
|
-
if ((badge.icon || badge.iconName) && !badge.text) {
|
|
3405
|
-
element.style.padding = '0';
|
|
3406
|
-
}
|
|
3407
|
-
if (badge.accessibilityLabel)
|
|
3408
|
-
element.setAttribute('aria-label', badge.accessibilityLabel);
|
|
3409
|
-
if (badge.icon) {
|
|
3410
|
-
const icon = createImage(context, badge.icon);
|
|
3411
|
-
if (icon) {
|
|
3412
|
-
icon.style.borderRadius = '50%';
|
|
3413
|
-
element.prepend(icon);
|
|
3414
|
-
}
|
|
3415
|
-
}
|
|
3416
|
-
if (badge.iconName === 'verified') {
|
|
3417
|
-
const icon = createElement(
|
|
3418
|
-
context.document,
|
|
3419
|
-
'span',
|
|
3420
|
-
'ok-native-list-market-badge-icon'
|
|
3421
|
-
);
|
|
3422
|
-
applySelectorIcon(icon, 'BadgeVerifiedSolid');
|
|
3423
|
-
element.prepend(icon);
|
|
3424
|
-
}
|
|
3425
|
-
titleLine.appendChild(element);
|
|
3426
|
-
});
|
|
3427
|
-
main.appendChild(titleLine);
|
|
3428
|
-
if (row.subtitlePrefix || row.subtitle || row.subtitleSegments?.length) {
|
|
3429
|
-
const subtitleLine = createElement(
|
|
3430
|
-
context.document,
|
|
3431
|
-
'span',
|
|
3432
|
-
'ok-native-list-market-subtitle-line'
|
|
3433
|
-
);
|
|
3434
|
-
subtitleLine.style.display = 'flex';
|
|
3435
|
-
subtitleLine.style.alignItems = 'center';
|
|
3436
|
-
subtitleLine.style.minWidth = '0';
|
|
3437
|
-
subtitleLine.style.overflow = 'hidden';
|
|
3438
|
-
subtitleLine.style.gap =
|
|
3439
|
-
String(row.subtitlePrefix ? row.subtitlePrefix.gap ?? 4 : 0) + 'px';
|
|
3440
|
-
if (row.subtitlePrefix) {
|
|
3441
|
-
const prefix = createElement(
|
|
1848
|
+
if (element.tagName === 'BUTTON') {
|
|
1849
|
+
element.setAttribute('type', 'button');
|
|
1850
|
+
element.classList.add('ok-native-list-icon-button');
|
|
1851
|
+
setData(element, 'nativeListAction', actionKey);
|
|
1852
|
+
}
|
|
1853
|
+
switch (accessory.kind) {
|
|
1854
|
+
case 'value':
|
|
1855
|
+
element.textContent = accessory.text;
|
|
1856
|
+
applyValueSegments(element, accessory.textSegments);
|
|
1857
|
+
if (accessory.secondary)
|
|
1858
|
+
element.classList.add('ok-native-list-accessory-secondary');
|
|
1859
|
+
break;
|
|
1860
|
+
case 'valuePair': {
|
|
1861
|
+
const primary = createElement(
|
|
3442
1862
|
context.document,
|
|
3443
1863
|
'span',
|
|
3444
|
-
|
|
3445
|
-
|
|
1864
|
+
undefined,
|
|
1865
|
+
accessory.primary
|
|
3446
1866
|
);
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
lineHeight: 16,
|
|
3450
|
-
weight: 400,
|
|
3451
|
-
alignment: 'start',
|
|
3452
|
-
});
|
|
3453
|
-
prefix.style.display = 'block';
|
|
3454
|
-
prefix.style.flex = '1 1 auto';
|
|
3455
|
-
prefix.style.minWidth = '0';
|
|
3456
|
-
prefix.style.overflow = 'hidden';
|
|
3457
|
-
prefix.style.textOverflow = 'ellipsis';
|
|
3458
|
-
prefix.style.color =
|
|
3459
|
-
row.subtitlePrefix.style?.color ?? 'var(--nl-secondary)';
|
|
3460
|
-
if (row.subtitlePrefix.maxWidth !== undefined) {
|
|
3461
|
-
prefix.style.maxWidth = String(row.subtitlePrefix.maxWidth) + 'px';
|
|
3462
|
-
}
|
|
3463
|
-
subtitleLine.appendChild(prefix);
|
|
3464
|
-
}
|
|
3465
|
-
if (row.subtitle || row.subtitleSegments?.length) {
|
|
3466
|
-
const subtitle = createElement(
|
|
1867
|
+
primary.style.color = toneColor(accessory.primaryTone, 'primary');
|
|
1868
|
+
const secondary = createElement(
|
|
3467
1869
|
context.document,
|
|
3468
1870
|
'span',
|
|
3469
|
-
'ok-native-list-
|
|
3470
|
-
|
|
3471
|
-
);
|
|
3472
|
-
applyMarketTextStyle(subtitle, style?.subtitle, {
|
|
3473
|
-
fontSize: 14,
|
|
3474
|
-
lineHeight: 20,
|
|
3475
|
-
weight: 400,
|
|
3476
|
-
alignment: 'start',
|
|
3477
|
-
});
|
|
3478
|
-
applyValueSegments(
|
|
3479
|
-
subtitle,
|
|
3480
|
-
row.subtitleSegments,
|
|
3481
|
-
style?.subtitle?.fontSize ?? 14,
|
|
3482
|
-
style?.subtitle?.lineHeight ?? 20,
|
|
3483
|
-
marketFontWeight(style?.subtitle?.fontWeight, 400)
|
|
1871
|
+
'ok-native-list-secondary',
|
|
1872
|
+
accessory.secondary
|
|
3484
1873
|
);
|
|
3485
|
-
|
|
3486
|
-
|
|
1874
|
+
secondary.style.color = toneColor(accessory.secondaryTone, 'secondary');
|
|
1875
|
+
element.replaceChildren(primary, '\n', secondary);
|
|
1876
|
+
element.classList.add('ok-native-list-amounts');
|
|
1877
|
+
break;
|
|
3487
1878
|
}
|
|
3488
|
-
|
|
1879
|
+
case 'radio':
|
|
1880
|
+
element.textContent = accessory.checked ? '●' : '○';
|
|
1881
|
+
break;
|
|
1882
|
+
case 'switch':
|
|
1883
|
+
element.textContent = accessory.value ? 'ON' : 'OFF';
|
|
1884
|
+
setData(element, 'nativeListAction', accessory.actionKey);
|
|
1885
|
+
break;
|
|
1886
|
+
case 'chevron':
|
|
1887
|
+
element.textContent = '›';
|
|
1888
|
+
break;
|
|
1889
|
+
case 'menu':
|
|
1890
|
+
element.textContent = '⋮';
|
|
1891
|
+
break;
|
|
1892
|
+
case 'drag':
|
|
1893
|
+
element.textContent = '≡';
|
|
1894
|
+
break;
|
|
1895
|
+
case 'progress':
|
|
1896
|
+
element.textContent = String(Math.round(accessory.value * 100)) + '%';
|
|
1897
|
+
break;
|
|
3489
1898
|
}
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
context.document,
|
|
3493
|
-
'span',
|
|
3494
|
-
'ok-native-list-market-trailing'
|
|
3495
|
-
);
|
|
3496
|
-
trailing.style.gap = String(layoutStyle.trailingGap) + 'px';
|
|
3497
|
-
trailing.append(
|
|
3498
|
-
createElement(context.document, 'span', 'ok-native-list-market-price'),
|
|
3499
|
-
createElement(context.document, 'span', 'ok-native-list-market-change')
|
|
3500
|
-
);
|
|
3501
|
-
body.appendChild(trailing);
|
|
3502
|
-
setMarketQuoteContent(body, row);
|
|
3503
|
-
return body;
|
|
1899
|
+
if (actionKey) markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1900
|
+
return element;
|
|
3504
1901
|
}
|
|
3505
1902
|
|
|
3506
|
-
function
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
1903
|
+
function rendererPrimitives(context: RenderContext) {
|
|
1904
|
+
return {
|
|
1905
|
+
background: resolvedTheme(context.snapshot).background,
|
|
1906
|
+
accessory: (key: string, descriptor: TrailingAccessory, slot: number) =>
|
|
1907
|
+
createAccessory(context, key, descriptor, slot),
|
|
1908
|
+
visual: (source: LeadingVisual | undefined, presentation?: string) =>
|
|
1909
|
+
createVisual(context, source, presentation),
|
|
1910
|
+
thumbnail: (source: ImageSource) =>
|
|
1911
|
+
createImage(context, source, 'ok-native-list-thumbnail'),
|
|
1912
|
+
textStyle: applyTextStyleToSlot,
|
|
1913
|
+
icon: applySelectorIcon,
|
|
1914
|
+
iconAction: (
|
|
1915
|
+
name: string,
|
|
1916
|
+
actionKey: string | undefined,
|
|
1917
|
+
disabled?: boolean,
|
|
1918
|
+
tintColor?: string
|
|
1919
|
+
) => createIconAction(context, name, actionKey, disabled, tintColor),
|
|
1920
|
+
dispose: disposeWebImageRetries,
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
export function createRowBody(
|
|
1925
|
+
context: RenderContext,
|
|
1926
|
+
row: RowModel
|
|
1927
|
+
): HTMLElement {
|
|
1928
|
+
return rowRenderer(row).create(context.document, rendererPrimitives(context));
|
|
3531
1929
|
}
|
|
3532
1930
|
|
|
3533
1931
|
export class NativeListWebEngine {
|
|
@@ -3554,7 +1952,21 @@ export class NativeListWebEngine {
|
|
|
3554
1952
|
horizontal: false,
|
|
3555
1953
|
};
|
|
3556
1954
|
private readonly mounted = new Map<number, HTMLElement>();
|
|
3557
|
-
private readonly pool: HTMLElement[] =
|
|
1955
|
+
private readonly pool: Record<RowRendererKey, HTMLElement[]> = {
|
|
1956
|
+
walletGroup: [],
|
|
1957
|
+
message: [],
|
|
1958
|
+
rail: [],
|
|
1959
|
+
mediaTile: [],
|
|
1960
|
+
action: [],
|
|
1961
|
+
system: [],
|
|
1962
|
+
activity: [],
|
|
1963
|
+
dataRow: [],
|
|
1964
|
+
metricCard: [],
|
|
1965
|
+
market: [],
|
|
1966
|
+
identity: [],
|
|
1967
|
+
sectionHeader: [],
|
|
1968
|
+
};
|
|
1969
|
+
private readonly rendererKeys = new WeakMap<HTMLElement, RowRendererKey>();
|
|
3558
1970
|
private frameHandle: number | undefined;
|
|
3559
1971
|
private resizeObserver: ResizeObserver | undefined;
|
|
3560
1972
|
private sectionIndexTransformObserver: MutationObserver | undefined;
|
|
@@ -3607,8 +2019,11 @@ export class NativeListWebEngine {
|
|
|
3607
2019
|
private lastViewportHeight = -1;
|
|
3608
2020
|
private destroyed = false;
|
|
3609
2021
|
private sectionIndexAlignStart = false;
|
|
3610
|
-
//
|
|
3611
|
-
private
|
|
2022
|
+
// Renderers report intrinsic height after browser text wrapping.
|
|
2023
|
+
private measuredRendererHeights = new Map<
|
|
2024
|
+
string,
|
|
2025
|
+
{ signature: string; height: number }
|
|
2026
|
+
>();
|
|
3612
2027
|
|
|
3613
2028
|
constructor(
|
|
3614
2029
|
host: HTMLElement,
|
|
@@ -3996,14 +2411,18 @@ export class NativeListWebEngine {
|
|
|
3996
2411
|
this.viewport.removeEventListener('pointercancel', this.handlePullEnd);
|
|
3997
2412
|
const host = this.root.parentElement;
|
|
3998
2413
|
disposeWebImageRetries(this.root);
|
|
3999
|
-
this.pool.forEach(
|
|
2414
|
+
Object.values(this.pool).forEach((elements) =>
|
|
2415
|
+
elements.forEach(disposeWebImageRetries)
|
|
2416
|
+
);
|
|
4000
2417
|
this.root.remove();
|
|
4001
2418
|
this.indexRail.remove();
|
|
4002
2419
|
this.hideReorderPreview();
|
|
4003
2420
|
this.reorderPreview.remove();
|
|
4004
2421
|
if (host) host.style.position = this.previousHostPosition;
|
|
4005
2422
|
this.mounted.clear();
|
|
4006
|
-
this.pool.
|
|
2423
|
+
Object.values(this.pool).forEach((elements) => {
|
|
2424
|
+
elements.length = 0;
|
|
2425
|
+
});
|
|
4007
2426
|
this.avatarLeases.forEach((release) => release());
|
|
4008
2427
|
this.avatarLeases.clear();
|
|
4009
2428
|
}
|
|
@@ -4013,7 +2432,7 @@ export class NativeListWebEngine {
|
|
|
4013
2432
|
selectedKeys?: ReadonlySet<string>
|
|
4014
2433
|
) {
|
|
4015
2434
|
this.cancelMarketPointer();
|
|
4016
|
-
this.
|
|
2435
|
+
this.measuredRendererHeights.clear();
|
|
4017
2436
|
this.snapshot = snapshot;
|
|
4018
2437
|
this.rows = effectiveRows(snapshot);
|
|
4019
2438
|
this.selectedKeys =
|
|
@@ -4060,6 +2479,31 @@ export class NativeListWebEngine {
|
|
|
4060
2479
|
this.indexRail.style.setProperty(name, value);
|
|
4061
2480
|
this.reorderPreview.style.setProperty(name, value);
|
|
4062
2481
|
});
|
|
2482
|
+
this.applyListStyle();
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
/**
|
|
2486
|
+
* List chrome from `snapshot.listStyle`. Every value is absent by default and
|
|
2487
|
+
* the stylesheet carries today's number as the fallback, so an untouched list
|
|
2488
|
+
* renders exactly as before. See docs/STYLE_SPEC.md §5.
|
|
2489
|
+
*/
|
|
2490
|
+
private applyListStyle() {
|
|
2491
|
+
const listStyle = this.snapshot.listStyle;
|
|
2492
|
+
const inset = listStyle?.separator?.inset;
|
|
2493
|
+
setData(this.root, 'separatorInset', inset !== undefined && inset > 0);
|
|
2494
|
+
const chrome: Readonly<Record<string, string | undefined>> = {
|
|
2495
|
+
'--nl-separator-inset':
|
|
2496
|
+
inset === undefined ? undefined : String(inset) + 'px',
|
|
2497
|
+
'--nl-separator-color': listStyle?.separator?.color,
|
|
2498
|
+
'--nl-group-radius':
|
|
2499
|
+
listStyle?.groupCornerRadius === undefined
|
|
2500
|
+
? undefined
|
|
2501
|
+
: String(listStyle.groupCornerRadius) + 'px',
|
|
2502
|
+
};
|
|
2503
|
+
Object.entries(chrome).forEach(([name, value]) => {
|
|
2504
|
+
if (value === undefined) this.root.style.removeProperty(name);
|
|
2505
|
+
else this.root.style.setProperty(name, value);
|
|
2506
|
+
});
|
|
4063
2507
|
}
|
|
4064
2508
|
|
|
4065
2509
|
private recomputeLayout = () => {
|
|
@@ -4086,7 +2530,7 @@ export class NativeListWebEngine {
|
|
|
4086
2530
|
viewportHeight !== this.lastViewportHeight)
|
|
4087
2531
|
) {
|
|
4088
2532
|
this.invalidateActionAnchor('layout');
|
|
4089
|
-
this.
|
|
2533
|
+
this.measuredRendererHeights.clear();
|
|
4090
2534
|
}
|
|
4091
2535
|
this.lastViewportWidth = viewportWidth;
|
|
4092
2536
|
this.lastViewportHeight = viewportHeight;
|
|
@@ -4094,11 +2538,14 @@ export class NativeListWebEngine {
|
|
|
4094
2538
|
const measuredSnapshot: NativeListSnapshot = {
|
|
4095
2539
|
...this.snapshot,
|
|
4096
2540
|
rows: this.snapshot.rows.map((row) =>
|
|
4097
|
-
row.
|
|
4098
|
-
row.variant === 'warning' &&
|
|
2541
|
+
row.style?.container?.height === undefined &&
|
|
4099
2542
|
row.height === undefined &&
|
|
4100
|
-
this.
|
|
4101
|
-
|
|
2543
|
+
this.measuredRendererHeights.get(row.key)?.signature ===
|
|
2544
|
+
webRowRenderSignature(row)
|
|
2545
|
+
? {
|
|
2546
|
+
...row,
|
|
2547
|
+
height: this.measuredRendererHeights.get(row.key)!.height,
|
|
2548
|
+
}
|
|
4102
2549
|
: row
|
|
4103
2550
|
),
|
|
4104
2551
|
};
|
|
@@ -4190,13 +2637,22 @@ export class NativeListWebEngine {
|
|
|
4190
2637
|
);
|
|
4191
2638
|
const desired = new Set(visible.map((item) => item.index));
|
|
4192
2639
|
this.mounted.forEach((element, index) => {
|
|
4193
|
-
|
|
2640
|
+
const nextRow = this.rows[index];
|
|
2641
|
+
const rendererKey = this.rendererKeys.get(element);
|
|
2642
|
+
if (
|
|
2643
|
+
!desired.has(index) ||
|
|
2644
|
+
!nextRow ||
|
|
2645
|
+
rendererKey !== rowRendererKey(nextRow)
|
|
2646
|
+
) {
|
|
4194
2647
|
this.invalidateActionAnchorForElement(element);
|
|
4195
2648
|
this.mounted.delete(index);
|
|
4196
|
-
|
|
2649
|
+
const recycled = element.firstElementChild
|
|
2650
|
+
? recycleRowBody(element.firstElementChild as HTMLElement)
|
|
2651
|
+
: false;
|
|
2652
|
+
if (disposeWebImageRetries(element) || recycled)
|
|
4197
2653
|
element.removeAttribute('data-render-signature');
|
|
4198
2654
|
element.remove();
|
|
4199
|
-
this.pool.push(element);
|
|
2655
|
+
if (rendererKey) this.pool[rendererKey].push(element);
|
|
4200
2656
|
}
|
|
4201
2657
|
});
|
|
4202
2658
|
|
|
@@ -4205,9 +2661,11 @@ export class NativeListWebEngine {
|
|
|
4205
2661
|
if (!row) return;
|
|
4206
2662
|
let element = this.mounted.get(layoutItem.index);
|
|
4207
2663
|
if (!element) {
|
|
2664
|
+
const rendererKey = rowRendererKey(row);
|
|
4208
2665
|
element =
|
|
4209
|
-
this.pool.pop() ??
|
|
2666
|
+
this.pool[rendererKey].pop() ??
|
|
4210
2667
|
createElement(this.document, 'div', 'ok-native-list-item');
|
|
2668
|
+
this.rendererKeys.set(element, rendererKey);
|
|
4211
2669
|
setData(element, 'nativeListAnimateReorder', false);
|
|
4212
2670
|
this.mounted.set(layoutItem.index, element);
|
|
4213
2671
|
this.content.appendChild(element);
|
|
@@ -4222,24 +2680,30 @@ export class NativeListWebEngine {
|
|
|
4222
2680
|
element.dataset.renderSignature = signature;
|
|
4223
2681
|
}
|
|
4224
2682
|
});
|
|
4225
|
-
let
|
|
2683
|
+
let measuredHeightChanged = false;
|
|
4226
2684
|
this.mounted.forEach((element, index) => {
|
|
4227
2685
|
const row = this.rows[index];
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
2686
|
+
const registered = row && rowRenderer(row);
|
|
2687
|
+
if (registered && element.firstElementChild) {
|
|
2688
|
+
const height = registered.measureRendered(
|
|
2689
|
+
element.firstElementChild as HTMLElement
|
|
2690
|
+
);
|
|
2691
|
+
if (
|
|
2692
|
+
height !== undefined &&
|
|
2693
|
+
(height !== this.measuredRendererHeights.get(row.key)?.height ||
|
|
2694
|
+
webRowRenderSignature(row) !==
|
|
2695
|
+
this.measuredRendererHeights.get(row.key)?.signature)
|
|
2696
|
+
) {
|
|
2697
|
+
this.measuredRendererHeights.set(row.key, {
|
|
2698
|
+
signature: webRowRenderSignature(row),
|
|
2699
|
+
height,
|
|
2700
|
+
});
|
|
2701
|
+
measuredHeightChanged = true;
|
|
2702
|
+
}
|
|
4233
2703
|
return;
|
|
4234
|
-
const height =
|
|
4235
|
-
element.querySelector<HTMLElement>('.ok-native-list-warning')
|
|
4236
|
-
?.offsetHeight ?? 0;
|
|
4237
|
-
if (height > 0 && height !== this.measuredWarningHeights.get(row.key)) {
|
|
4238
|
-
this.measuredWarningHeights.set(row.key, height);
|
|
4239
|
-
measuredWarningChanged = true;
|
|
4240
2704
|
}
|
|
4241
2705
|
});
|
|
4242
|
-
if (
|
|
2706
|
+
if (measuredHeightChanged) {
|
|
4243
2707
|
this.recomputeLayout();
|
|
4244
2708
|
return;
|
|
4245
2709
|
}
|
|
@@ -4261,7 +2725,13 @@ export class NativeListWebEngine {
|
|
|
4261
2725
|
overlay = false
|
|
4262
2726
|
) {
|
|
4263
2727
|
this.invalidateActionAnchorForElement(element);
|
|
4264
|
-
|
|
2728
|
+
const registered = rowRenderer(row);
|
|
2729
|
+
const existingBody = element.firstElementChild as HTMLElement | null;
|
|
2730
|
+
const reusableBody =
|
|
2731
|
+
existingBody?.dataset.nlRenderer === registered.key
|
|
2732
|
+
? existingBody
|
|
2733
|
+
: undefined;
|
|
2734
|
+
if (!reusableBody) disposeWebImageRetries(element);
|
|
4265
2735
|
const bindingEpoch = String(++this.bindingEpochCounter);
|
|
4266
2736
|
element.className = overlay
|
|
4267
2737
|
? 'ok-native-list-item ok-native-list-sticky'
|
|
@@ -4273,7 +2743,10 @@ export class NativeListWebEngine {
|
|
|
4273
2743
|
setData(element, 'nativeListRowPressEnabled', isRowPressEnabled(row));
|
|
4274
2744
|
setData(element, 'testid', row.testID);
|
|
4275
2745
|
// OneKey patch: deprecation dims a row without disabling its actions.
|
|
4276
|
-
element.style.opacity = String(
|
|
2746
|
+
element.style.opacity = String(
|
|
2747
|
+
(row.style?.container?.opacity ?? row.opacity ?? 1) *
|
|
2748
|
+
(row.disabled ? 0.5 : 1)
|
|
2749
|
+
);
|
|
4277
2750
|
setData(element, 'nativeListReorderable', this.isReorderable(row));
|
|
4278
2751
|
setData(
|
|
4279
2752
|
element,
|
|
@@ -4306,84 +2779,32 @@ export class NativeListWebEngine {
|
|
|
4306
2779
|
selectedKeys: this.selectedKeys,
|
|
4307
2780
|
itemIndex: index,
|
|
4308
2781
|
};
|
|
4309
|
-
const body = createRowBody(context, row);
|
|
4310
|
-
|
|
2782
|
+
const body = reusableBody ?? createRowBody(context, row);
|
|
2783
|
+
if (reusableBody) {
|
|
2784
|
+
resetRowContainerStyle(body);
|
|
2785
|
+
registered.bind(body, rendererPrimitives(context));
|
|
2786
|
+
}
|
|
4311
2787
|
// OneKey patch: explicit selector fields preserve original page geometry.
|
|
4312
2788
|
element.style.contain = row.backgroundFullWidth ? 'layout style' : '';
|
|
4313
2789
|
if (row.backgroundColor) body.style.backgroundColor = row.backgroundColor;
|
|
4314
|
-
|
|
2790
|
+
const restingBackground =
|
|
2791
|
+
row.style?.container?.backgroundColor ?? row.backgroundColor;
|
|
2792
|
+
if (row.backgroundFullWidth && restingBackground) {
|
|
4315
2793
|
const bleed = paddingValues(this.snapshot).horizontal;
|
|
4316
2794
|
body.style.position = 'relative';
|
|
4317
2795
|
body.style.overflow = 'visible';
|
|
4318
2796
|
body.style.boxShadow =
|
|
4319
2797
|
String(-bleed) +
|
|
4320
2798
|
'px 0 ' +
|
|
4321
|
-
|
|
2799
|
+
restingBackground +
|
|
4322
2800
|
',' +
|
|
4323
2801
|
String(bleed) +
|
|
4324
2802
|
'px 0 ' +
|
|
4325
|
-
|
|
4326
|
-
}
|
|
4327
|
-
if (row.type === 'identity' && row.height !== undefined) {
|
|
4328
|
-
const title = body.querySelector<HTMLElement>('.ok-native-list-title');
|
|
4329
|
-
if (row.presentation === 'accountSelector') {
|
|
4330
|
-
body.style.gap = '12px';
|
|
4331
|
-
body.style.borderRadius = '12px';
|
|
4332
|
-
if ('shape' in row.leading && row.leading.shape === 'rounded') {
|
|
4333
|
-
const visual = body.querySelector<HTMLElement>(
|
|
4334
|
-
'.ok-native-list-visual'
|
|
4335
|
-
);
|
|
4336
|
-
if (visual) visual.style.borderRadius = '8px';
|
|
4337
|
-
}
|
|
4338
|
-
if (title) title.style.lineHeight = '24px';
|
|
4339
|
-
}
|
|
4340
|
-
if (row.presentation === 'networkSelector') {
|
|
4341
|
-
body.style.borderRadius = '12px';
|
|
4342
|
-
const visual = body.querySelector<HTMLElement>(
|
|
4343
|
-
'.ok-native-list-visual'
|
|
4344
|
-
);
|
|
4345
|
-
if (visual) {
|
|
4346
|
-
visual.style.width = '32px';
|
|
4347
|
-
visual.style.height = '32px';
|
|
4348
|
-
visual.style.flexBasis = '32px';
|
|
4349
|
-
}
|
|
4350
|
-
if (
|
|
4351
|
-
row.leading.kind === 'network' &&
|
|
4352
|
-
!row.leading.image &&
|
|
4353
|
-
!row.leading.fallbackIcon &&
|
|
4354
|
-
row.leading.fallbackText
|
|
4355
|
-
) {
|
|
4356
|
-
const fallback = visual?.querySelector<HTMLElement>(
|
|
4357
|
-
'.ok-native-list-visual-fallback'
|
|
4358
|
-
);
|
|
4359
|
-
if (fallback) {
|
|
4360
|
-
fallback.style.fontSize = '19px';
|
|
4361
|
-
fallback.style.lineHeight = '27px';
|
|
4362
|
-
fallback.style.fontWeight = '600';
|
|
4363
|
-
fallback.style.color = 'var(--nl-inverse-text)';
|
|
4364
|
-
}
|
|
4365
|
-
}
|
|
4366
|
-
visual
|
|
4367
|
-
?.querySelectorAll<HTMLElement>('.ok-native-list-visual-main')
|
|
4368
|
-
.forEach((image) => {
|
|
4369
|
-
image.style.width = '32px';
|
|
4370
|
-
image.style.height = '32px';
|
|
4371
|
-
});
|
|
4372
|
-
if (title) {
|
|
4373
|
-
title.style.fontSize = '16px';
|
|
4374
|
-
title.style.lineHeight = '24px';
|
|
4375
|
-
title.style.fontWeight = '500';
|
|
4376
|
-
}
|
|
4377
|
-
body
|
|
4378
|
-
.querySelectorAll<HTMLElement>('.ok-native-list-accessory')
|
|
4379
|
-
.forEach((value) => {
|
|
4380
|
-
value.style.fontSize = '16px';
|
|
4381
|
-
value.style.lineHeight = '24px';
|
|
4382
|
-
value.style.fontWeight = '500';
|
|
4383
|
-
});
|
|
4384
|
-
}
|
|
2803
|
+
restingBackground;
|
|
4385
2804
|
}
|
|
4386
|
-
|
|
2805
|
+
// Template and presentation defaults must precede caller overrides.
|
|
2806
|
+
applyRowStyle(body, row);
|
|
2807
|
+
if (body.parentElement !== element) element.replaceChildren(body);
|
|
4387
2808
|
if (
|
|
4388
2809
|
row.type === 'market' &&
|
|
4389
2810
|
row.diagnostics?.imageBindActionKey &&
|
|
@@ -5254,6 +3675,8 @@ export class NativeListWebEngine {
|
|
|
5254
3675
|
action.dataset.nativeListHoverAction === 'true'
|
|
5255
3676
|
? action.dataset.nativeListAction
|
|
5256
3677
|
: action.dataset.nativeListHoverAction;
|
|
3678
|
+
// Legacy Web: hover checks only the resolved source (the member for a
|
|
3679
|
+
// WalletGroup), not the enclosing row's `disabled`.
|
|
5257
3680
|
if (sourceRow && !sourceRow.disabled && actionKey)
|
|
5258
3681
|
this.emitRowAction(sourceRow, actionKey, action, rowElement ?? undefined);
|
|
5259
3682
|
};
|
|
@@ -5298,6 +3721,9 @@ export class NativeListWebEngine {
|
|
|
5298
3721
|
(member) => member.key === memberKey
|
|
5299
3722
|
) ?? row
|
|
5300
3723
|
: row;
|
|
3724
|
+
// Legacy Web: a disabled row (or whole WalletGroup) blocks everything
|
|
3725
|
+
// above. A disabled WalletGroup member still emits its own actions, but its
|
|
3726
|
+
// member press is blocked by `isRowPressEnabled` in `handleRowPress`.
|
|
5301
3727
|
const action = target.closest<HTMLElement>('[data-native-list-action]');
|
|
5302
3728
|
if (action) {
|
|
5303
3729
|
const scope = action.dataset.selectionScope;
|
|
@@ -5781,11 +4207,11 @@ export class NativeListWebEngine {
|
|
|
5781
4207
|
const row = source?.firstElementChild;
|
|
5782
4208
|
if (!source || !row) return;
|
|
5783
4209
|
const rect = source.getBoundingClientRect();
|
|
5784
|
-
const
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
const previewRow =
|
|
5788
|
-
const previewHeight =
|
|
4210
|
+
const sourceRow = state.workingRows[state.currentIndex];
|
|
4211
|
+
const preview =
|
|
4212
|
+
sourceRow && rowRenderer(sourceRow).reorderPreview(row as HTMLElement);
|
|
4213
|
+
const previewRow = preview?.element ?? row;
|
|
4214
|
+
const previewHeight = preview?.height ?? rect.height;
|
|
5789
4215
|
state.previewOffsetX = state.startX - rect.left;
|
|
5790
4216
|
state.previewOffsetY = Math.min(
|
|
5791
4217
|
previewHeight,
|
|
@@ -5809,7 +4235,6 @@ export class NativeListWebEngine {
|
|
|
5809
4235
|
}
|
|
5810
4236
|
configureWebAvatar(image, avatar.source, avatar.uri);
|
|
5811
4237
|
});
|
|
5812
|
-
const sourceRow = state.workingRows[state.currentIndex];
|
|
5813
4238
|
const badgeText = sourceRow
|
|
5814
4239
|
? webWalletGroupReorderBadge(sourceRow)
|
|
5815
4240
|
: undefined;
|
|
@@ -6217,3 +4642,7 @@ export class NativeListWebEngine {
|
|
|
6217
4642
|
});
|
|
6218
4643
|
}
|
|
6219
4644
|
}
|
|
4645
|
+
|
|
4646
|
+
export function applyRowStyle(body: HTMLElement, row: RowModel): void {
|
|
4647
|
+
applyRowContainerStyle(body, row);
|
|
4648
|
+
}
|