@onekeyfe/react-native-native-list 3.0.113 → 3.0.114

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.
@@ -3,8 +3,6 @@ import type {
3
3
  CheckboxState,
4
4
  ImageSource,
5
5
  LeadingVisual,
6
- MarketRow,
7
- MarketTextStyle,
8
6
  NativeListSnapshot,
9
7
  NativeListActionAnchor,
10
8
  NativeListActionSource,
@@ -62,10 +60,6 @@ export const WEB_REORDER_ANIMATION = {
62
60
  } as const;
63
61
 
64
62
  const REORDER_TOUCH_LONG_PRESS_MS = 120;
65
- const MARKET_LONG_PRESS_MS = 800;
66
- const MARKET_MOVE_CANCEL_PX = 10;
67
- export const WEB_MARKET_VERIFIED_PATH =
68
- 'M9.483 11.458v3.5h-1v-3.5z M10.467 2.698a2.03 2.03 0 0 1 3.065 0l1.358 1.564a.03.03 0 0 0 .028.01l2.046-.325a2.03 2.03 0 0 1 2.347 1.971l.037 2.07q0 .016.014.026l1.776 1.066a2.03 2.03 0 0 1 .532 3.019l-1.304 1.609a.03.03 0 0 0-.005.03l.675 1.956a2.03 2.03 0 0 1-1.533 2.656l-2.033.394a.03.03 0 0 0-.023.019l-.741 1.933a2.03 2.03 0 0 1-2.88 1.05l-1.811-1.006a.03.03 0 0 0-.03 0l-1.811 1.005a2.03 2.03 0 0 1-2.88-1.049l-.742-1.933a.03.03 0 0 0-.023-.019l-2.033-.394a2.03 2.03 0 0 1-1.532-2.656l.675-1.957a.03.03 0 0 0-.005-.029l-1.304-1.61a2.03 2.03 0 0 1 .532-3.018l1.776-1.066a.03.03 0 0 0 .014-.026l.035-2.07a2.03 2.03 0 0 1 2.349-1.97l2.045.324a.03.03 0 0 0 .028-.01zm1.516 3.76a.5.5 0 0 0-.447.276l-1.861 3.724H8.483a1 1 0 0 0-1 1v3.5a1 1 0 0 0 1 1h6.692a2 2 0 0 0 1.981-1.73l.341-2.5a2 2 0 0 0-1.982-2.27h-1.939l.197-1.269a1.5 1.5 0 0 0-1.481-1.731z';
69
63
  const REORDER_MOUSE_MOVE_THRESHOLD_PX = 5;
70
64
  const REORDER_EDGE_RATIO = 0.25;
71
65
  const REORDER_MAX_SPEED_ZONE_RATIO = 0.05;
@@ -114,50 +108,6 @@ export type WebListLayout = Readonly<{
114
108
  horizontal: boolean;
115
109
  }>;
116
110
 
117
- export type WebMarketLayoutStyle = Readonly<{
118
- horizontalPadding: number;
119
- verticalPadding: number;
120
- leadingGap: number;
121
- titleBadgeGap: number;
122
- trailingGap: number;
123
- imageWidth: number;
124
- imageHeight: number;
125
- imageCornerRadius: number;
126
- changeWidth: number;
127
- changeHeight: number;
128
- changeCornerRadius: number;
129
- }>;
130
-
131
- /** Resolves every reusable Market geometry field, including legacy defaults. */
132
- export function resolveWebMarketLayoutStyle(
133
- row: MarketRow
134
- ): WebMarketLayoutStyle {
135
- const style = row.style;
136
- const imageWidth = style?.image?.width ?? (row.variant === 'stock' ? 40 : 32);
137
- const imageHeight =
138
- style?.image?.height ?? (row.variant === 'stock' ? 40 : 32);
139
- return {
140
- horizontalPadding:
141
- style?.horizontalPadding ?? (row.variant === 'perp' ? 16 : 20),
142
- verticalPadding: style?.verticalPadding ?? 12,
143
- leadingGap: style?.leadingGap ?? (row.variant === 'perp' ? 8 : 14),
144
- titleBadgeGap: style?.titleBadgeGap ?? 4,
145
- trailingGap: style?.trailingGap ?? 8,
146
- imageWidth,
147
- imageHeight,
148
- imageCornerRadius:
149
- style?.image?.cornerRadius ??
150
- (style?.image?.shape === 'square'
151
- ? 0
152
- : style?.image?.shape === 'rounded'
153
- ? 8
154
- : Math.min(imageWidth, imageHeight) / 2),
155
- changeWidth: style?.changeWidth ?? 80,
156
- changeHeight: style?.changeHeight ?? 32,
157
- changeCornerRadius: style?.changeCornerRadius ?? 8,
158
- };
159
- }
160
-
161
111
  export type NativeListWebCallbacks = Readonly<{
162
112
  onRowAction?: (event: RowActionEvent) => void;
163
113
  onActionAnchorInvalidated?: (event: ActionAnchorInvalidatedEvent) => void;
@@ -500,15 +450,7 @@ export function estimateWebRowHeight(
500
450
  }
501
451
  case 'system':
502
452
  base =
503
- row.variant === 'loading' && row.loadingStyle === 'skeleton'
504
- ? 56
505
- : row.variant === 'loading' && row.loadingStyle === 'spinner'
506
- ? 52
507
- : 'presentation' in row && row.presentation === 'market'
508
- ? row.variant === 'loading'
509
- ? 68
510
- : 44
511
- : row.variant === 'noMatch' || row.variant === 'end'
453
+ row.variant === 'noMatch' || row.variant === 'end'
512
454
  ? 36
513
455
  : row.variant === 'retry'
514
456
  ? 44
@@ -520,14 +462,6 @@ export function estimateWebRowHeight(
520
462
  case 'dataRow':
521
463
  base = row.columns.some((column) => column.secondaryText) ? 60 : 56;
522
464
  break;
523
- case 'market': {
524
- const marketStyle = resolveWebMarketLayoutStyle(row);
525
- base = Math.max(
526
- row.variant === 'stock' ? 72 : 68,
527
- marketStyle.imageHeight + marketStyle.verticalPadding * 2
528
- );
529
- break;
530
- }
531
465
  case 'identity':
532
466
  base = row.tertiary ? 72 : row.subtitle ? 60 : 56;
533
467
  break;
@@ -808,30 +742,6 @@ export function webRowRenderSignature(row: RowModel): string {
808
742
  return JSON.stringify(rowWithoutSelectionState(row));
809
743
  }
810
744
 
811
- const MARKET_QUOTE_PATCH_FIELDS = new Set([
812
- 'revision',
813
- 'price',
814
- 'priceSegments',
815
- 'change',
816
- 'accessibilityLabel',
817
- ]);
818
-
819
- export function isWebMarketQuotePatch(patch: RowPatch): boolean {
820
- return (
821
- patch.type === 'market' &&
822
- Object.keys(patch.changes).every((key) =>
823
- MARKET_QUOTE_PATCH_FIELDS.has(key)
824
- )
825
- );
826
- }
827
-
828
- /** Number of Market image-binding passes caused by one Web patch transaction. */
829
- export function webMarketImageBindDeltaForPatches(
830
- patches: readonly RowPatch[]
831
- ): 0 | 1 {
832
- return patches.length > 0 && patches.every(isWebMarketQuotePatch) ? 0 : 1;
833
- }
834
-
835
745
  // OneKey patch: selector names must shrink before the sidebar clips their contents.
836
746
  export const WEB_LIST_CSS = `
837
747
  [data-native-list-selector="walletSidebar"] .ok-native-list-title{max-width:100%;min-width:0}
@@ -888,14 +798,11 @@ export const WEB_LIST_CSS = `
888
798
  .ok-native-list-media{display:block;padding:0 5px;background:transparent;border-radius:16px}.ok-native-list-media-image{display:block;width:100%;aspect-ratio:1;border-radius:10px;background:var(--nl-strong);object-fit:cover}.ok-native-list-media-image[data-state="empty"]{background:transparent}.ok-native-list-media-image[data-state="error"]{display:flex;align-items:center;justify-content:center;color:var(--nl-icon-subdued);font-size:24px}.ok-native-list-media-meta{padding-top:7px}.ok-native-list-media-subtitle-row{display:flex;align-items:center;gap:6px}.ok-native-list-media-subtitle{flex:1;min-width:0;font-size:12px;color:var(--nl-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-media-network{width:14px;height:14px;border-radius:50%}.ok-native-list-media-title{font-size:16px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-media-close{position:absolute;right:9px;top:4px;border:0;background:color-mix(in srgb,var(--nl-inverse) 72%,transparent);color:var(--nl-inverse-text);width:24px;height:24px;border-radius:50%;font:18px/20px inherit;cursor:pointer}
889
799
  .ok-native-list-metric{display:flex;flex-direction:column;align-items:flex-start;padding:12px;border-radius:12px;gap:5px;background:var(--nl-row)}.ok-native-list-metric-value{font-size:22px;line-height:28px;font-weight:700}.ok-native-list-composite{display:flex;flex-direction:column;align-items:stretch;padding:14px;border-radius:12px;gap:12px;background:var(--nl-subdued)}.ok-native-list-composite-heading{font-size:14px;letter-spacing:1px;color:var(--nl-secondary)}.ok-native-list-composite-row{display:flex;gap:12px}.ok-native-list-composite-cell{flex:1;min-width:0}.ok-native-list-composite-cell[data-shaded="true"]{padding:10px;border-radius:10px;background:color-mix(in srgb,var(--nl-primary) 5%,transparent)}.ok-native-list-composite-value{font-size:18px;font-weight:600}.ok-native-list-divider{height:1px;background:var(--nl-separator)}.ok-native-list-progress{height:4px;border-radius:2px;overflow:hidden;background:var(--nl-negative)}.ok-native-list-progress>span{display:block;height:100%;border-radius:2px;background:var(--nl-positive)}
890
800
  .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}
891
- .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)}
892
- .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}
893
801
  .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-index-rail{position:absolute;z-index:6;top:0;right:0;bottom:0;width:${SECTION_INDEX_RAIL_WIDTH}px;touch-action:none;cursor:pointer}.ok-native-list-index-rail[hidden]{display:none}.ok-native-list-index-button{appearance:none;position:absolute;left:6px;display:flex;width:20px;height:16px;align-items:center;justify-content:center;padding:0;transform:translateY(-50%);border:0;border-radius:8px;background:transparent;color:var(--nl-secondary);font:600 10px/1 inherit;cursor:pointer}.ok-native-list-index-button[data-active="true"]{background:var(--nl-accent);color:var(--nl-inverse-text)}.ok-native-list-index-button:focus-visible{outline:2px solid var(--nl-accent);outline-offset:1px}.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)}
894
802
  .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)}
895
803
  .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)}
896
804
  .ok-native-list-subtitle-segments{display:flex;align-items:center;min-width:0;max-width:100%;height:20px}.ok-native-list-subtitle-segments>.ok-native-list-secondary{flex:0 1 auto;min-width:0}.ok-native-list-subtitle-dot{flex:0 0 4px;width:4px;height:4px;margin:0 6px;border-radius:50%;background:var(--nl-disabled)}.ok-native-list-wallet-row>.ok-native-list-flex{flex:0 1 auto;width:100%;align-items:center}.ok-native-list-wallet-badges{display:flex;gap:4px;justify-content:center;margin-top:4px;height:20px;max-width:100%}.ok-native-list-wallet-badges>.ok-native-list-badge{background:var(--nl-strong);color:var(--nl-secondary);font-size:12px;line-height:16px;height:20px;box-sizing:border-box;padding:2px 4px}.ok-native-list-visual-overlay{position:absolute;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border-radius:50%;overflow:hidden;line-height:1;font-size:10px}.ok-native-list-visual-overlay img,.ok-native-list-visual-overlay svg{width:100%;height:100%;object-fit:contain}
897
- .ok-native-list-row.ok-native-list-market-skeleton{padding:12px 20px;gap:0}.ok-native-list-skeleton-left{display:flex;align-items:center;gap:12px;flex:1}.ok-native-list-skeleton-text{display:flex;flex-direction:column;gap:4px}.ok-native-list-skeleton-right{display:flex;align-items:center;gap:8px}.ok-native-list-skeleton-mark{display:block;flex-shrink:0;border-radius:8px;animation:ok-native-list-skeleton 1.5s linear infinite alternate}@keyframes ok-native-list-skeleton{from{background-color:var(--nl-skeleton-base)}to{background-color:var(--nl-skeleton-highlight)}}.ok-native-list-market-spinner{display:block;width:20px;height:20px;flex-shrink:0;color:var(--nl-icon);animation:ok-native-list-spin .75s linear infinite}
898
- @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)}}
805
+ @media (prefers-reduced-motion:reduce){.ok-native-list-index-preview,.ok-native-list-refresh{transition:none}.ok-native-list-spinner{animation:none}}
899
806
  /* OneKey patch: selector controls follow their original semantic colors and geometry. */
900
807
  .ok-native-list-checkbox[data-selector="networkSelector"]{padding:0;border-radius:4px;border-color:var(--nl-checkbox-border,var(--nl-separator));background:var(--nl-checkbox-icon,var(--nl-inverse-text))}
901
808
  .ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
@@ -1373,17 +1280,6 @@ const selectorIcons: Readonly<
1373
1280
  },
1374
1281
  ],
1375
1282
  },
1376
- BadgeVerifiedSolid: {
1377
- viewBox: '0 0 24 24',
1378
- paths: [
1379
- {
1380
- d: WEB_MARKET_VERIFIED_PATH,
1381
- fill: 'currentColor',
1382
- fillRule: 'evenodd',
1383
- opacity: 1,
1384
- },
1385
- ],
1386
- },
1387
1283
  };
1388
1284
  function applySelectorIcon(element: HTMLElement, name: string) {
1389
1285
  const icon = selectorIcons[name];
@@ -1439,7 +1335,6 @@ function visualFromRow(row: RowModel): LeadingVisual | undefined {
1439
1335
  if (row.type === 'activity') return row.leading;
1440
1336
  if (row.type === 'message') return row.leading;
1441
1337
  if (row.type === 'dataRow') return row.leading;
1442
- if (row.type === 'market') return row.leading;
1443
1338
  if (row.type === 'metricCard') return row.visual;
1444
1339
  return undefined;
1445
1340
  }
@@ -2194,98 +2089,6 @@ function createSystemRow(
2194
2089
  'ok-native-list-row ok-native-list-system'
2195
2090
  );
2196
2091
  setData(body, 'variant', row.variant);
2197
- if ('presentation' in row)
2198
- setData(body, 'nativeListPresentation', row.presentation);
2199
- if (row.variant === 'loading' && row.loadingStyle === 'skeleton') {
2200
- body.classList.add('ok-native-list-market-skeleton');
2201
- const background = resolvedTheme(context.snapshot).background;
2202
- const rgb = Number.parseInt(background.slice(1, 7), 16);
2203
- const dark =
2204
- ((rgb >> 16) & 255) * 0.299 +
2205
- ((rgb >> 8) & 255) * 0.587 +
2206
- (rgb & 255) * 0.114 <
2207
- 128;
2208
- body.style.setProperty('--nl-skeleton-base', dark ? '#111111' : '#fafafa');
2209
- body.style.setProperty(
2210
- '--nl-skeleton-highlight',
2211
- dark ? '#333333' : '#cdcdcd'
2212
- );
2213
- const left = createElement(
2214
- context.document,
2215
- 'div',
2216
- 'ok-native-list-skeleton-left'
2217
- );
2218
- const mark = (width: number, height: number, circle = false) => {
2219
- const element = createElement(
2220
- context.document,
2221
- 'span',
2222
- 'ok-native-list-skeleton-mark'
2223
- );
2224
- element.style.width = `${width}px`;
2225
- element.style.height = `${height}px`;
2226
- if (circle) element.style.borderRadius = '50%';
2227
- return element;
2228
- };
2229
- left.appendChild(mark(32, 32, true));
2230
- const text = createElement(
2231
- context.document,
2232
- 'div',
2233
- 'ok-native-list-skeleton-text'
2234
- );
2235
- text.appendChild(mark(80, 16));
2236
- text.appendChild(mark(60, 12));
2237
- left.appendChild(text);
2238
- body.appendChild(left);
2239
- const right = createElement(
2240
- context.document,
2241
- 'div',
2242
- 'ok-native-list-skeleton-right'
2243
- );
2244
- right.appendChild(mark(80, 18));
2245
- right.appendChild(mark(80, 18));
2246
- body.appendChild(right);
2247
- return body;
2248
- }
2249
- if (row.variant === 'loading' && row.loadingStyle === 'spinner') {
2250
- body.style.justifyContent = 'center';
2251
- body.style.padding = '16px';
2252
- const spinner = createElement(
2253
- context.document,
2254
- 'span',
2255
- 'ok-native-list-market-spinner'
2256
- );
2257
- spinner.setAttribute('role', 'progressbar');
2258
- // Same 20px SVG and 750ms rotation as react-native-web ActivityIndicator.
2259
- spinner.innerHTML =
2260
- '<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>';
2261
- body.appendChild(spinner);
2262
- return body;
2263
- }
2264
- if ('presentation' in row && row.presentation === 'market') {
2265
- if (row.variant === 'noMatch') {
2266
- body.style.justifyContent = 'center';
2267
- body.style.padding = '32px';
2268
- const message = createElement(context.document, 'span', '', row.message);
2269
- message.style.fontSize = '16px';
2270
- message.style.lineHeight = '24px';
2271
- body.appendChild(message);
2272
- return body;
2273
- }
2274
- if (row.variant === 'end') {
2275
- body.style.justifyContent = 'center';
2276
- body.style.padding = '16px';
2277
- body.style.gap = '8px';
2278
- for (const width of [80, 4, 80]) {
2279
- const mark = createElement(context.document, 'span', '');
2280
- mark.style.width = String(width) + 'px';
2281
- mark.style.height = width === 4 ? '4px' : '1px';
2282
- mark.style.borderRadius = width === 4 ? '2px' : '0';
2283
- mark.style.background = 'var(--nl-separator)';
2284
- body.appendChild(mark);
2285
- }
2286
- return body;
2287
- }
2288
- }
2289
2092
  if (row.variant === 'warning') {
2290
2093
  body.classList.add('ok-native-list-warning');
2291
2094
  body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
@@ -2981,266 +2784,6 @@ function createWalletGroupRow(
2981
2784
  return body;
2982
2785
  }
2983
2786
 
2984
- function marketFontWeight(
2985
- value: MarketTextStyle['fontWeight'] | undefined,
2986
- fallback: number
2987
- ): number {
2988
- if (value === 'bold') return 700;
2989
- if (value === 'semibold') return 600;
2990
- if (value === 'medium') return 500;
2991
- if (value === 'regular') return 400;
2992
- return fallback;
2993
- }
2994
-
2995
- function applyMarketTextStyle(
2996
- element: HTMLElement,
2997
- style: MarketTextStyle | undefined,
2998
- defaults: Readonly<{
2999
- fontSize: number;
3000
- lineHeight: number;
3001
- weight: number;
3002
- alignment: 'start' | 'center' | 'end';
3003
- }>
3004
- ) {
3005
- element.style.fontSize = String(style?.fontSize ?? defaults.fontSize) + 'px';
3006
- element.style.lineHeight =
3007
- String(style?.lineHeight ?? defaults.lineHeight) + 'px';
3008
- element.style.fontWeight = String(
3009
- marketFontWeight(style?.fontWeight, defaults.weight)
3010
- );
3011
- element.style.color = style?.color ?? '';
3012
- element.style.textAlign = style?.alignment ?? defaults.alignment;
3013
- element.style.whiteSpace = style?.lines === 2 ? 'normal' : 'nowrap';
3014
- element.style.display = '';
3015
- element.style.removeProperty('-webkit-line-clamp');
3016
- element.style.removeProperty('-webkit-box-orient');
3017
- if (style?.lines === 2) {
3018
- element.style.display = '-webkit-box';
3019
- element.style.setProperty('-webkit-line-clamp', '2');
3020
- element.style.setProperty('-webkit-box-orient', 'vertical');
3021
- }
3022
- }
3023
-
3024
- function setMarketQuoteContent(element: HTMLElement, row: MarketRow) {
3025
- const style = row.style;
3026
- const layoutStyle = resolveWebMarketLayoutStyle(row);
3027
- const price = element.querySelector<HTMLElement>(
3028
- '.ok-native-list-market-price'
3029
- );
3030
- if (price) {
3031
- price.textContent = row.price;
3032
- applyMarketTextStyle(price, style?.price, {
3033
- fontSize: 16,
3034
- lineHeight: 24,
3035
- weight: 500,
3036
- alignment: 'end',
3037
- });
3038
- applyValueSegments(
3039
- price,
3040
- row.priceSegments,
3041
- style?.price?.fontSize ?? 16,
3042
- style?.price?.lineHeight ?? 24,
3043
- marketFontWeight(style?.price?.fontWeight, 500)
3044
- );
3045
- }
3046
- const change = element.querySelector<HTMLElement>(
3047
- '.ok-native-list-market-change'
3048
- );
3049
- if (change) {
3050
- change.textContent = row.change.text;
3051
- setData(change, 'tone', row.change.tone);
3052
- applyMarketTextStyle(change, style?.change, {
3053
- fontSize: 14,
3054
- lineHeight: 20,
3055
- weight: 500,
3056
- alignment: 'center',
3057
- });
3058
- applyValueSegments(
3059
- change,
3060
- row.change.textSegments,
3061
- style?.change?.fontSize ?? 14,
3062
- style?.change?.lineHeight ?? 20,
3063
- marketFontWeight(style?.change?.fontWeight, 500)
3064
- );
3065
- change.style.width = String(layoutStyle.changeWidth) + 'px';
3066
- change.style.height = String(layoutStyle.changeHeight) + 'px';
3067
- change.style.borderRadius = String(layoutStyle.changeCornerRadius) + 'px';
3068
- change.style.color = row.change.textColor ?? style?.change?.color ?? '';
3069
- change.style.background = row.change.backgroundColor ?? '';
3070
- }
3071
- element.setAttribute(
3072
- 'aria-label',
3073
- row.accessibilityLabel ??
3074
- [row.title, row.subtitle, row.price, row.change.text]
3075
- .filter(Boolean)
3076
- .join(', ')
3077
- );
3078
- }
3079
-
3080
- function createMarketRow(context: RenderContext, row: MarketRow): HTMLElement {
3081
- const body = createElement(
3082
- context.document,
3083
- 'div',
3084
- 'ok-native-list-row ok-native-list-market'
3085
- );
3086
- setData(body, 'variant', row.variant);
3087
- const style = row.style;
3088
- const layoutStyle = resolveWebMarketLayoutStyle(row);
3089
- body.style.padding =
3090
- String(layoutStyle.verticalPadding) +
3091
- 'px ' +
3092
- String(layoutStyle.horizontalPadding) +
3093
- 'px';
3094
- body.style.gap = '0px';
3095
- const visual = createVisual(context, row.leading);
3096
- if (visual) {
3097
- const width = layoutStyle.imageWidth;
3098
- const height = layoutStyle.imageHeight;
3099
- visual.style.width = String(width) + 'px';
3100
- visual.style.height = String(height) + 'px';
3101
- visual.style.flexBasis = String(width) + 'px';
3102
- visual.style.borderRadius = String(layoutStyle.imageCornerRadius) + 'px';
3103
- const borderColor = 'borderColor' in row.leading ? row.leading.borderColor : undefined;
3104
- if (borderColor) {
3105
- visual.style.border = '1px solid ' + borderColor;
3106
- visual.style.boxSizing = 'border-box';
3107
- }
3108
- visual.querySelectorAll<HTMLElement>('img').forEach((image) => {
3109
- if (!image.classList.contains('ok-native-list-visual-corner')) {
3110
- image.style.width = '100%';
3111
- image.style.height = '100%';
3112
- if (borderColor) {
3113
- image.style.borderRadius = '0';
3114
- image.style.clipPath = 'inset(-1px round ' + String(layoutStyle.imageCornerRadius) + 'px)';
3115
- }
3116
- image.style.objectFit =
3117
- style?.image?.contentFit ?? image.style.objectFit;
3118
- } else {
3119
- image.style.width = '20px';
3120
- image.style.height = '20px';
3121
- if (borderColor) {
3122
- image.style.right = '-5px';
3123
- image.style.bottom = '-5px';
3124
- }
3125
- }
3126
- });
3127
- visual.style.marginRight = String(layoutStyle.leadingGap) + 'px';
3128
- body.appendChild(visual);
3129
- }
3130
- const main = createElement(
3131
- context.document,
3132
- 'span',
3133
- 'ok-native-list-market-main'
3134
- );
3135
- main.style.gap = String(style?.lineGap ?? 0) + 'px';
3136
- const titleLine = createElement(
3137
- context.document,
3138
- 'span',
3139
- 'ok-native-list-market-title-line'
3140
- );
3141
- titleLine.style.gap = String(layoutStyle.titleBadgeGap) + 'px';
3142
- const title = createElement(
3143
- context.document,
3144
- 'span',
3145
- 'ok-native-list-market-title',
3146
- row.title
3147
- );
3148
- applyMarketTextStyle(title, style?.title, {
3149
- fontSize: 16,
3150
- lineHeight: 24,
3151
- weight: 500,
3152
- alignment: 'start',
3153
- });
3154
- titleLine.appendChild(title);
3155
- row.badges?.forEach((badge, slot) => {
3156
- const element = createElement(
3157
- context.document,
3158
- badge.actionKey ? 'button' : 'span',
3159
- 'ok-native-list-market-badge',
3160
- badge.text
3161
- );
3162
- if (badge.actionKey) {
3163
- element.setAttribute('type', 'button');
3164
- setData(element, 'nativeListAction', badge.actionKey);
3165
- markActionAnchorSource(element, 'marketBadge', slot);
3166
- }
3167
- setData(element, 'tone', badge.tone);
3168
- element.style.color =
3169
- badge.textColor ??
3170
- (badge.tone === 'success'
3171
- ? 'var(--nl-positive)'
3172
- : badge.tone === 'danger'
3173
- ? 'var(--nl-negative)'
3174
- : badge.tone === 'info'
3175
- ? 'var(--nl-info)'
3176
- : badge.tone === 'warning'
3177
- ? 'var(--nl-primary)'
3178
- : '');
3179
- element.style.background =
3180
- badge.backgroundColor ??
3181
- ((badge.icon || badge.iconName) && !badge.text ? 'transparent' : '');
3182
- if ((badge.icon || badge.iconName) && !badge.text) {
3183
- element.style.padding = '0';
3184
- }
3185
- if (badge.accessibilityLabel)
3186
- element.setAttribute('aria-label', badge.accessibilityLabel);
3187
- if (badge.icon) {
3188
- const icon = createImage(context, badge.icon);
3189
- if (icon) {
3190
- icon.style.borderRadius = '50%';
3191
- element.prepend(icon);
3192
- }
3193
- }
3194
- if (badge.iconName === 'verified') {
3195
- const icon = createElement(
3196
- context.document,
3197
- 'span',
3198
- 'ok-native-list-market-badge-icon'
3199
- );
3200
- applySelectorIcon(icon, 'BadgeVerifiedSolid');
3201
- element.prepend(icon);
3202
- }
3203
- titleLine.appendChild(element);
3204
- });
3205
- main.appendChild(titleLine);
3206
- if (row.subtitle || row.subtitleSegments?.length) {
3207
- const subtitle = createElement(
3208
- context.document,
3209
- 'span',
3210
- 'ok-native-list-market-subtitle',
3211
- row.subtitle
3212
- );
3213
- applyMarketTextStyle(subtitle, style?.subtitle, {
3214
- fontSize: 14,
3215
- lineHeight: 20,
3216
- weight: 400,
3217
- alignment: 'start',
3218
- });
3219
- applyValueSegments(
3220
- subtitle,
3221
- row.subtitleSegments,
3222
- style?.subtitle?.fontSize ?? 14,
3223
- style?.subtitle?.lineHeight ?? 20,
3224
- marketFontWeight(style?.subtitle?.fontWeight, 400)
3225
- );
3226
- main.appendChild(subtitle);
3227
- }
3228
- body.appendChild(main);
3229
- const trailing = createElement(
3230
- context.document,
3231
- 'span',
3232
- 'ok-native-list-market-trailing'
3233
- );
3234
- trailing.style.gap = String(layoutStyle.trailingGap) + 'px';
3235
- trailing.append(
3236
- createElement(context.document, 'span', 'ok-native-list-market-price'),
3237
- createElement(context.document, 'span', 'ok-native-list-market-change')
3238
- );
3239
- body.appendChild(trailing);
3240
- setMarketQuoteContent(body, row);
3241
- return body;
3242
- }
3243
-
3244
2787
  function createRowBody(context: RenderContext, row: RowModel): HTMLElement {
3245
2788
  switch (row.type) {
3246
2789
  case 'walletGroup':
@@ -3259,8 +2802,6 @@ function createRowBody(context: RenderContext, row: RowModel): HTMLElement {
3259
2802
  return createMetricRow(context, row);
3260
2803
  case 'dataRow':
3261
2804
  return createDataRow(context, row);
3262
- case 'market':
3263
- return createMarketRow(context, row);
3264
2805
  case 'identity':
3265
2806
  case 'activity':
3266
2807
  case 'message':
@@ -3328,16 +2869,6 @@ export class NativeListWebEngine {
3328
2869
  );
3329
2870
  private actionAnchorCounter = 0;
3330
2871
  private bindingEpochCounter = 0;
3331
- private marketPointer:
3332
- | Readonly<{
3333
- pointerId: number;
3334
- rowKey: string;
3335
- startX: number;
3336
- startY: number;
3337
- timer: number;
3338
- }>
3339
- | undefined;
3340
- private marketLongPressFired = false;
3341
2872
  private lastViewportWidth = -1;
3342
2873
  private lastViewportHeight = -1;
3343
2874
  private destroyed = false;
@@ -3428,10 +2959,6 @@ export class NativeListWebEngine {
3428
2959
  passive: true,
3429
2960
  });
3430
2961
  this.root.addEventListener('click', this.handleClick);
3431
- this.root.addEventListener('pointerdown', this.handleMarketPointerDown);
3432
- this.root.addEventListener('pointermove', this.handleMarketPointerMove);
3433
- this.root.addEventListener('pointerup', this.handleMarketPointerEnd);
3434
- this.root.addEventListener('pointercancel', this.handleMarketPointerEnd);
3435
2962
  // OneKey patch: preserve web tooltip hover for section titles.
3436
2963
  this.root.addEventListener('pointerover', this.handleTitlePointerOver);
3437
2964
  this.root.addEventListener('pointerout', this.handleTitlePointerOut);
@@ -3507,6 +3034,7 @@ export class NativeListWebEngine {
3507
3034
  applyPatches(patches: readonly RowPatch[]) {
3508
3035
  if (patches.length === 0) return;
3509
3036
  const next = applyRowPatches(this.snapshot, patches);
3037
+ this.invalidateActionAnchor('snapshot');
3510
3038
  const selection = new Set(this.selectedKeys);
3511
3039
  patches.forEach((patch) => {
3512
3040
  const selected =
@@ -3514,29 +3042,6 @@ export class NativeListWebEngine {
3514
3042
  if (selected === true) selection.add(patch.key);
3515
3043
  else if (selected === false) selection.delete(patch.key);
3516
3044
  });
3517
- if (webMarketImageBindDeltaForPatches(patches) === 0) {
3518
- this.snapshot = next;
3519
- this.rows = effectiveRows(next);
3520
- this.selectedKeys = selection;
3521
- patches.forEach((patch) => {
3522
- const index = this.rows.findIndex((row) => row.key === patch.key);
3523
- const row = this.rows[index];
3524
- const element = this.mounted.get(index);
3525
- if (row?.type === 'market' && element) {
3526
- setMarketQuoteContent(element, row);
3527
- element.dataset.renderSignature = webRowRenderSignature(row);
3528
- }
3529
- if (
3530
- row?.type === 'market' &&
3531
- this.sticky.dataset.nativeListRowKey === row.key
3532
- ) {
3533
- setMarketQuoteContent(this.sticky, row);
3534
- this.sticky.dataset.renderSignature = webRowRenderSignature(row);
3535
- }
3536
- });
3537
- return;
3538
- }
3539
- this.invalidateActionAnchor('snapshot');
3540
3045
  this.setSnapshot(next, selection);
3541
3046
  }
3542
3047
 
@@ -3675,11 +3180,6 @@ export class NativeListWebEngine {
3675
3180
  );
3676
3181
  this.viewport.removeEventListener('scroll', this.handleScroll);
3677
3182
  this.root.removeEventListener('click', this.handleClick);
3678
- this.cancelMarketPointer();
3679
- this.root.removeEventListener('pointerdown', this.handleMarketPointerDown);
3680
- this.root.removeEventListener('pointermove', this.handleMarketPointerMove);
3681
- this.root.removeEventListener('pointerup', this.handleMarketPointerEnd);
3682
- this.root.removeEventListener('pointercancel', this.handleMarketPointerEnd);
3683
3183
  this.root.removeEventListener('pointerover', this.handleTitlePointerOver);
3684
3184
  this.root.removeEventListener('pointerout', this.handleTitlePointerOut);
3685
3185
  this.root.removeEventListener('keydown', this.handleKeyDown);
@@ -3730,7 +3230,6 @@ export class NativeListWebEngine {
3730
3230
  snapshot: NativeListSnapshot,
3731
3231
  selectedKeys?: ReadonlySet<string>
3732
3232
  ) {
3733
- this.cancelMarketPointer();
3734
3233
  this.measuredWarningHeights.clear();
3735
3234
  this.snapshot = snapshot;
3736
3235
  this.rows = effectiveRows(snapshot);
@@ -4081,17 +3580,6 @@ export class NativeListWebEngine {
4081
3580
  }
4082
3581
  }
4083
3582
  element.replaceChildren(body);
4084
- if (
4085
- row.type === 'market' &&
4086
- row.diagnostics?.imageBindActionKey &&
4087
- body.querySelector('img')
4088
- ) {
4089
- this.callbacks.onRowAction?.({
4090
- rowKey: row.key,
4091
- actionKey: row.diagnostics.imageBindActionKey,
4092
- sectionKey: row.sectionKey,
4093
- });
4094
- }
4095
3583
  }
4096
3584
 
4097
3585
  private renderFooter() {
@@ -4614,8 +4102,6 @@ export class NativeListWebEngine {
4614
4102
  ? row.actionKey
4615
4103
  : row.type === 'system' && row.variant === 'retry'
4616
4104
  ? row.actionKey
4617
- : row.type === 'market' && row.pressActionKey
4618
- ? row.pressActionKey
4619
4105
  : 'press';
4620
4106
  if (rowElement && sourceElement) {
4621
4107
  const anchor = this.createActionAnchor(sourceElement, rowElement, 'row');
@@ -4630,64 +4116,6 @@ export class NativeListWebEngine {
4630
4116
  }
4631
4117
  }
4632
4118
 
4633
- private cancelMarketPointer() {
4634
- const state = this.marketPointer;
4635
- if (!state) return;
4636
- this.document.defaultView?.clearTimeout(state.timer);
4637
- this.marketPointer = undefined;
4638
- }
4639
-
4640
- private handleMarketPointerDown = (event: PointerEvent) => {
4641
- if (event.button !== 0 || !(event.target instanceof Element)) return;
4642
- this.marketLongPressFired = false;
4643
- if (event.target.closest('[data-native-list-action]')) return;
4644
- const rowElement = event.target.closest<HTMLElement>(
4645
- '[data-native-list-row-key]'
4646
- );
4647
- const row = this.rowAtElement(rowElement);
4648
- if (row?.type !== 'market' || row.disabled) return;
4649
- this.cancelMarketPointer();
4650
- if (row.pressInActionKey)
4651
- this.emitRowAction(
4652
- row,
4653
- row.pressInActionKey,
4654
- rowElement ?? undefined,
4655
- rowElement ?? undefined
4656
- );
4657
- if (!row.longPressActionKey || !rowElement) return;
4658
- markActionAnchorSource(rowElement, 'row');
4659
- const timer = this.document.defaultView?.setTimeout(() => {
4660
- const current = this.marketPointer;
4661
- if (!current || current.pointerId !== event.pointerId) return;
4662
- this.marketPointer = undefined;
4663
- this.marketLongPressFired = true;
4664
- this.emitRowAction(row, row.longPressActionKey!, rowElement, rowElement);
4665
- }, MARKET_LONG_PRESS_MS);
4666
- if (timer === undefined) return;
4667
- this.marketPointer = {
4668
- pointerId: event.pointerId,
4669
- rowKey: row.key,
4670
- startX: event.clientX,
4671
- startY: event.clientY,
4672
- timer,
4673
- };
4674
- };
4675
-
4676
- private handleMarketPointerMove = (event: PointerEvent) => {
4677
- const state = this.marketPointer;
4678
- if (!state || state.pointerId !== event.pointerId) return;
4679
- if (
4680
- Math.abs(event.clientX - state.startX) > MARKET_MOVE_CANCEL_PX ||
4681
- Math.abs(event.clientY - state.startY) > MARKET_MOVE_CANCEL_PX
4682
- )
4683
- this.cancelMarketPointer();
4684
- };
4685
-
4686
- private handleMarketPointerEnd = (event: PointerEvent) => {
4687
- if (this.marketPointer?.pointerId === event.pointerId)
4688
- this.cancelMarketPointer();
4689
- };
4690
-
4691
4119
  // OneKey patch: hover opens the same anchored help action as native taps.
4692
4120
  private handleTitlePointerOver = (event: PointerEvent) => {
4693
4121
  const target = event.target;
@@ -4739,8 +4167,7 @@ export class NativeListWebEngine {
4739
4167
  };
4740
4168
 
4741
4169
  private handleClick = (event: Event) => {
4742
- if (this.marketLongPressFired || Date.now() < this.suppressClickUntil) {
4743
- this.marketLongPressFired = false;
4170
+ if (Date.now() < this.suppressClickUntil) {
4744
4171
  event.preventDefault();
4745
4172
  event.stopPropagation();
4746
4173
  return;
@@ -4913,7 +4340,6 @@ export class NativeListWebEngine {
4913
4340
  }
4914
4341
 
4915
4342
  private handleScroll = () => {
4916
- this.cancelMarketPointer();
4917
4343
  this.invalidateActionAnchor('scroll');
4918
4344
  this.scheduleFrame();
4919
4345
  };