@onekeyfe/react-native-native-list 3.0.157-alpha.248 → 3.0.157-alpha.250

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.
Files changed (130) hide show
  1. package/README.md +21 -5
  2. package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +711 -0
  3. package/android/src/main/java/com/onekey/nativelist/NativeListActionRenderer.kt +169 -0
  4. package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +243 -0
  5. package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +20 -6
  6. package/android/src/main/java/com/onekey/nativelist/NativeListDataRowRenderer.kt +487 -0
  7. package/android/src/main/java/com/onekey/nativelist/NativeListIdentityRenderer.kt +820 -0
  8. package/android/src/main/java/com/onekey/nativelist/NativeListImageSlot.kt +147 -0
  9. package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +453 -0
  10. package/android/src/main/java/com/onekey/nativelist/NativeListMarketRenderer.kt +997 -0
  11. package/android/src/main/java/com/onekey/nativelist/NativeListMediaTileRenderer.kt +234 -0
  12. package/android/src/main/java/com/onekey/nativelist/NativeListMessageRenderer.kt +232 -0
  13. package/android/src/main/java/com/onekey/nativelist/NativeListMetricCardRenderer.kt +551 -0
  14. package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +24 -0
  15. package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +475 -0
  16. package/android/src/main/java/com/onekey/nativelist/NativeListRailRenderer.kt +143 -0
  17. package/android/src/main/java/com/onekey/nativelist/NativeListRendererRegistry.kt +42 -0
  18. package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +415 -0
  19. package/android/src/main/java/com/onekey/nativelist/NativeListResolvedText.kt +163 -0
  20. package/android/src/main/java/com/onekey/nativelist/NativeListRowHost.kt +70 -0
  21. package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +748 -0
  22. package/android/src/main/java/com/onekey/nativelist/NativeListSystemRenderer.kt +464 -0
  23. package/android/src/main/java/com/onekey/nativelist/NativeListTextView.kt +25 -0
  24. package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +174 -104
  25. package/android/src/main/java/com/onekey/nativelist/NativeListWalletGroupRenderer.kt +407 -0
  26. package/android/src/test/java/com/margelo/nitro/nativelist/NativeListSelectorBackgroundColorTest.kt +34 -0
  27. package/docs/DESIGN.md +518 -9
  28. package/docs/MIGRATION_BASELINE.md +117 -0
  29. package/docs/ROW_TEMPLATES.md +359 -0
  30. package/docs/SPEC.md +358 -0
  31. package/docs/STYLE_SPEC.md +978 -0
  32. package/docs/images/list-capabilities.svg +39 -0
  33. package/docs/images/row-action.svg +17 -0
  34. package/docs/images/row-activity.svg +24 -0
  35. package/docs/images/row-data.svg +24 -0
  36. package/docs/images/row-identity.svg +25 -0
  37. package/docs/images/row-market.svg +23 -0
  38. package/docs/images/row-media-tile.svg +26 -0
  39. package/docs/images/row-message.svg +20 -0
  40. package/docs/images/row-metric-card.svg +33 -0
  41. package/docs/images/row-rail.svg +18 -0
  42. package/docs/images/row-section-header.svg +19 -0
  43. package/docs/images/row-style-regions.svg +30 -0
  44. package/docs/images/row-system.svg +30 -0
  45. package/docs/images/row-wallet-group.svg +26 -0
  46. package/ios/NativeListAccessoryStack.swift +680 -0
  47. package/ios/NativeListActionRenderer.swift +108 -0
  48. package/ios/NativeListActivityRenderer.swift +179 -0
  49. package/ios/NativeListDataRowRenderer.swift +444 -0
  50. package/ios/NativeListIdentityRenderer.swift +685 -0
  51. package/ios/NativeListImageSlot.swift +140 -0
  52. package/ios/NativeListLeadingVisual.swift +372 -0
  53. package/ios/NativeListMarketRenderer.swift +698 -0
  54. package/ios/NativeListMediaTileRenderer.swift +184 -0
  55. package/ios/NativeListMessageRenderer.swift +168 -0
  56. package/ios/NativeListMetricCardRenderer.swift +420 -0
  57. package/ios/NativeListModels.swift +32 -0
  58. package/ios/NativeListRailRenderer.swift +152 -0
  59. package/ios/NativeListRendererCell.swift +311 -0
  60. package/ios/NativeListRendererRegistry.swift +50 -0
  61. package/ios/NativeListResolvedText.swift +122 -0
  62. package/ios/NativeListRowHost.swift +63 -0
  63. package/ios/NativeListSectionHeaderRenderer.swift +708 -0
  64. package/ios/NativeListSystemRenderer.swift +568 -0
  65. package/ios/NativeListTextLabel.swift +42 -0
  66. package/ios/NativeListTextStyles.swift +236 -0
  67. package/ios/NativeListWalletGroupRenderer.swift +255 -0
  68. package/ios/RNCNativeListView.swift +111 -180
  69. package/lib/module/models.js +54 -0
  70. package/lib/module/validation.js +324 -26
  71. package/lib/module/web/NativeListWebEngine.js +148 -936
  72. package/lib/module/web/templates/ActionRowRenderer.js +97 -0
  73. package/lib/module/web/templates/ActivityRowRenderer.js +95 -0
  74. package/lib/module/web/templates/DataRowRenderer.js +145 -0
  75. package/lib/module/web/templates/IdentityRowRenderer.js +289 -0
  76. package/lib/module/web/templates/MarketRowRenderer.js +310 -0
  77. package/lib/module/web/templates/MediaTileRowRenderer.js +132 -0
  78. package/lib/module/web/templates/MessageRowRenderer.js +165 -0
  79. package/lib/module/web/templates/MetricCardRowRenderer.js +172 -0
  80. package/lib/module/web/templates/RailRowRenderer.js +98 -0
  81. package/lib/module/web/templates/RowContainerStyle.js +100 -0
  82. package/lib/module/web/templates/RowElements.js +93 -0
  83. package/lib/module/web/templates/RowRendererRegistry.js +70 -0
  84. package/lib/module/web/templates/RowText.js +121 -0
  85. package/lib/module/web/templates/RowVisual.js +43 -0
  86. package/lib/module/web/templates/SectionHeaderRowRenderer.js +146 -0
  87. package/lib/module/web/templates/SystemRowRenderer.js +161 -0
  88. package/lib/module/web/templates/WalletGroupRowRenderer.js +96 -0
  89. package/lib/typescript/src/models.d.ts +166 -13
  90. package/lib/typescript/src/web/NativeListWebEngine.d.ts +18 -16
  91. package/lib/typescript/src/web/templates/ActionRowRenderer.d.ts +15 -0
  92. package/lib/typescript/src/web/templates/ActivityRowRenderer.d.ts +15 -0
  93. package/lib/typescript/src/web/templates/DataRowRenderer.d.ts +15 -0
  94. package/lib/typescript/src/web/templates/IdentityRowRenderer.d.ts +16 -0
  95. package/lib/typescript/src/web/templates/MarketRowRenderer.d.ts +30 -0
  96. package/lib/typescript/src/web/templates/MediaTileRowRenderer.d.ts +15 -0
  97. package/lib/typescript/src/web/templates/MessageRowRenderer.d.ts +44 -0
  98. package/lib/typescript/src/web/templates/MetricCardRowRenderer.d.ts +15 -0
  99. package/lib/typescript/src/web/templates/RailRowRenderer.d.ts +28 -0
  100. package/lib/typescript/src/web/templates/RowContainerStyle.d.ts +9 -0
  101. package/lib/typescript/src/web/templates/RowElements.d.ts +38 -0
  102. package/lib/typescript/src/web/templates/RowRendererRegistry.d.ts +83 -0
  103. package/lib/typescript/src/web/templates/RowText.d.ts +9 -0
  104. package/lib/typescript/src/web/templates/RowVisual.d.ts +20 -0
  105. package/lib/typescript/src/web/templates/SectionHeaderRowRenderer.d.ts +15 -0
  106. package/lib/typescript/src/web/templates/SystemRowRenderer.d.ts +16 -0
  107. package/lib/typescript/src/web/templates/WalletGroupRowRenderer.d.ts +20 -0
  108. package/package.json +3 -3
  109. package/src/models.ts +281 -19
  110. package/src/validation.ts +501 -46
  111. package/src/web/NativeListWebEngine.ts +361 -1932
  112. package/src/web/templates/ActionRowRenderer.ts +123 -0
  113. package/src/web/templates/ActivityRowRenderer.ts +159 -0
  114. package/src/web/templates/DataRowRenderer.ts +212 -0
  115. package/src/web/templates/IdentityRowRenderer.ts +527 -0
  116. package/src/web/templates/MarketRowRenderer.ts +467 -0
  117. package/src/web/templates/MediaTileRowRenderer.ts +182 -0
  118. package/src/web/templates/MessageRowRenderer.ts +306 -0
  119. package/src/web/templates/MetricCardRowRenderer.ts +337 -0
  120. package/src/web/templates/RailRowRenderer.ts +136 -0
  121. package/src/web/templates/RowContainerStyle.ts +131 -0
  122. package/src/web/templates/RowElements.ts +160 -0
  123. package/src/web/templates/RowRendererRegistry.ts +111 -0
  124. package/src/web/templates/RowText.ts +181 -0
  125. package/src/web/templates/RowVisual.ts +115 -0
  126. package/src/web/templates/SectionHeaderRowRenderer.ts +243 -0
  127. package/src/web/templates/SystemRowRenderer.ts +282 -0
  128. package/src/web/templates/WalletGroupRowRenderer.ts +131 -0
  129. package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +0 -4538
  130. package/ios/NativeListCell.swift +0 -4300
@@ -0,0 +1,117 @@
1
+ # Renderer migration baseline
2
+
3
+ Inventory captured at `a75666930` on 2026-09-22. This records existing behavior,
4
+ not a new public API. Keep each rule until its owning migration explicitly
5
+ replaces the caller contract. Renaming keys must not be an accidental side effect
6
+ of the Message extraction.
7
+
8
+ ## Complete implicit key inventory
9
+
10
+ The audit covered the TS wrapper/validation/selection/scrolling, Web engine,
11
+ Swift models/cell/container, and Kotlin models/row/adapter/container. Searches
12
+ included key/sectionKey/column-key comparisons, prefix/substring tests and named
13
+ sets. Generated bindings and examples do not define renderer semantics.
14
+
15
+ | Rule | Existing behavior and source | Disposition |
16
+ | --- | --- | --- |
17
+ | `history-` prefix | iOS `NativeListCell.bindSectionHeader` and `RNCNativeListView.rowHeight`: row key **or** section key implies history title/height. Web `estimateWebRowHeight`: same two keys imply 16-unit header height; its rendering still follows the explicit variant. Android `bindSectionHeader`/`applySize`: only **section key** implies uppercase 12/16 title, 0 padding and 16-unit minimum height. Explicit `variant: history` works independently. | Stage 4 moved these defaults into the SectionHeader renderers. Both example history headers and the validation fixture already set `variant: history`; no implicit history-header caller remains in this repository. Stage 6 audited the app-monorepo callers and removes the compatibility fallback; only the explicit variant selects history styling. |
18
+ | `token-`, `balance-token-`, exact `linear-custom-token` | Android `NativeListRowView.bind` suppresses `separator: true` for these keys across row types. iOS/Web have no equivalent key exception. | Removed in stage 6 after auditing examples and app-monorepo: no matching caller sets `separator: true`. Separators now obey the explicit field on every platform. |
19
+ | exact section keys `linear-tokens`, `action-tokens` | Android `bindSectionHeader`/`applySize` applies token-manager 14/20 regular typography, horizontal 12/top 10/bottom 0 padding and 30-unit minimum height (subject to earlier explicit presentation/variant branches). No matching iOS/Web rule. | Stage 4 migrated both example callers to an explicit 30-unit container height, bottom alignment, 12-unit horizontal / zero vertical padding and regular 14/20 title. Stage 6 verified external consumers and removes the fallback. Renaming either key no longer changes typography or geometry. |
20
+ | exact tail keys `market-loading-more`, `market-load-more-retry`, `market-end` | Android `NativeListView.isMarketPaginationUpdate` drops those trailing rows before checking a stable Market prefix when either snapshot has loadMore; this keeps the scroll anchor during pagination. It is a container update optimization, not a row renderer. | Preserve in the container. Replace with explicit structural-row recognition in a separately validated pagination change. |
21
+ | exact column key `asset` | Web `createDataRow` adds row badges only to that table column. Native table binders attach row badges to the first column instead. | Retained as a documented DataRow compatibility rule. No app-monorepo DataRow caller was found in the stage 6 audit; changing badge placement requires a separate explicit API/caller migration. |
22
+
23
+ There are no other business-key-dependent decisions in the audited production
24
+ paths. Equality for identity/diffing, selection targets, section membership,
25
+ scroll targets, reorder membership, action lookup, image recycling keys and
26
+ stale-callback guards is intentional identity usage, not a business-key rule.
27
+ Keyboard event keys and style-property whitelist keys are also unrelated.
28
+
29
+ ## Stage 6 consumer audit
30
+
31
+ Audited on 2026-09-23: local app-monorepo `67fcc71204` and `origin/x`
32
+ `62c645f906`. NativeList imports/builders in AccountSelector, UnifiedNetworkSelector
33
+ and Market have no history/token key styling dependencies. Repository token rows
34
+ omit `separator` (false); history headers specify `variant: history`; token
35
+ headers already specify their height, alignment, spacing and typography.
36
+ No external checkout changes were needed. This is a source audit of these refs,
37
+ not a claim about all published consumers.
38
+
39
+ The two retained rules above are the container pagination optimization and
40
+ DataRow badge-column ownership. Neither chooses a renderer or maps `row.style`
41
+ fields. List event/selection/reorder identities continue to use keys normally.
42
+
43
+ ## Default geometry and precedence
44
+
45
+ [STYLE_SPEC.md sections 8–9](STYLE_SPEC.md) inventory all twelve templates' row
46
+ heights, typography, spacing, image sizes and existing platform differences.
47
+ Preserve those unstyled defaults when extracting view ownership. Explicit
48
+ `style.container.height` wins over `row.height`; compact WalletGroup reorder
49
+ height remains a temporary container override. Style removal restores defaults.
50
+ No overflow fitting or font shrinking is introduced.
51
+
52
+ Message baseline: native 28-unit leading/64-unit thumbnail, title/body 14/20,
53
+ time 12/16; iOS column gaps 2 plus a 2-unit timestamp inset, Android body/time
54
+ margins 2/4. Web retains its existing horizontal timestamp, 40-unit leading,
55
+ 64-unit thumbnail, 15/20 title, 13/18 body, 11/16 timestamp and 8/12 padding.
56
+ Explicit native style values use logical units; Android legacy defaults/model
57
+ heights retain NativeListScale, while explicit styles use display density.
58
+
59
+ The old iOS/Web Message estimators used different fallback metrics from their
60
+ views (including 20 horizontal padding and 14/20 time). Stage 2 must correct this
61
+ as an explicit measurement change, separate from view extraction; explicit
62
+ heights and the unstyled visual defaults above stay unchanged.
63
+
64
+ ## Special update and lifecycle inventory
65
+
66
+ | Path | Required invariant |
67
+ | --- | --- |
68
+ | Full snapshot/patch | Stable key identifies data; incompatible renderer family replaces the view. Bind A → B is correct without recycling. |
69
+ | Message | Renderer classifies no-op, content/style, asset and replacement work. Unchanged image descriptors retain requests/views; changed or removed assets cancel old callbacks/retries. |
70
+ | Market quote | Preserve price/priceSegments/change/accessibility partial updates and explicit rich text styles. Theme/layout/non-quote changes still require full binding. |
71
+ | Selection echo/summary | Preserve native immediate feedback, latest descriptor/action context and fixed-height summary updates without resetting images. Unknown/mixed payloads keep full binding. |
72
+ | Async image completion | Request identity and binding lifetime reject stale writes; bounded retries/fallbacks cannot cross recycle/disposal. |
73
+ | Action anchors | Rebind/recycle invalidates old epoch-owned source anchors. Selection-only presentation updates retain their current owner. |
74
+ | WalletGroup/reorder | Keep member events, compact 68-unit drag appearance, expansion restoration and bounded member-host retention. Message extraction does not change these paths. |
75
+ | Containers | Header/footer, sections/index, scrolling, table/grid/horizontal allocation and pagination remain list-owned. |
76
+
77
+ ## Acceptance baseline
78
+
79
+ The existing 150 package tests and seven Android tests, together with the dated
80
+ Message runtime cases in [DESIGN.md](DESIGN.md), establish the pre-migration
81
+ baseline. Native title/body/time bounds were captured before text extraction.
82
+ The Message fixture covers explicit/model height, style set/change/clear, blank
83
+ body/time, same-key Message/Identity changes, images, end/top scrolling, 41-row
84
+ mixed swaps, empty/repopulate and the fixed footer on all three platforms.
85
+ Full native acceptance of the later templates remains a gate for stages 3–5,
86
+ not an implied result of finishing this inventory.
87
+
88
+ ## Rail extraction baseline (stage 3)
89
+
90
+ Rail keeps iOS title/badge gap 8 versus Android/Web 6. Android's default status
91
+ margin is 0 even though its historical width reserves 6; iOS/Web use 6. Default
92
+ height remains iOS/Web 40 and Android's scaled minimum 28. Native text is 12,
93
+ with 16-unit title/badge line metrics; Android status keeps its natural line
94
+ height. Web retains 12/11/13 for title/badge/status. Leading size is 20 and
95
+ padding is 4. These are existing differences, not different style property APIs.
96
+ Horizontal sizing retains the legacy allowances (including iOS's old 6-unit
97
+ badge-gap estimate inside its trailing budget and Android's status allowance)
98
+ and now applies explicit resolved style metrics. Style removal restores the
99
+ baseline dimensions. Rail does not show persistent row selection; press and
100
+ reorder feedback remain container-owned.
101
+
102
+ ## Stage 4 caller audit
103
+
104
+ The 2026-09-23 search covered all tracked source and examples.
105
+ `example/react-native/pages/NativeListExamplePage.tsx` has two history headers;
106
+ both already supply `variant: history`. Other `history-` occurrences identify
107
+ Activity section membership or explicitly styled validation fixtures. The two
108
+ Token Manager headers now declare their geometry and typography through the
109
+ shared rowStyle contract. Bottom alignment puts the 20-unit title at the bottom
110
+ of its 30-unit row without requiring a new asymmetric-padding property.
111
+ Those explicit style values use logical units on all platforms, replacing
112
+ Android's old scaled default at these caller sites.
113
+
114
+ Stage 6 completed the external-consumer source audit described above and removed
115
+ the native/Web header key fallbacks. Stage 5 also migrated WalletGroup members
116
+ to independent Identity hosts. The historical defaults in this baseline remain
117
+ useful when reviewing explicitly styled caller behavior.
@@ -0,0 +1,359 @@
1
+ # NativeList row template catalog
2
+
3
+ This catalog defines the **12 types in `RowModel`** on the consolidated spec
4
+ branch. Each template owns a fixed internal structure. Its `style` customizes
5
+ named fields inside that structure; it does not define a new layout or enable a
6
+ list feature. See [STYLE_SPEC.md](STYLE_SPEC.md) for tokens, numeric bounds,
7
+ layout-safety rules, common capabilities and implementation gaps.
8
+
9
+ The diagrams are **schematics, not device screenshots or pixel specifications**.
10
+ Blue areas denote content fields; green areas denote accessories/actions; dashed
11
+ areas are optional. They illustrate slot relationships, not literal native view
12
+ names. Legacy platform dimensions remain in STYLE_SPEC §4/§6. A diagram showing
13
+ an optional field does not mean every variant displays it.
14
+
15
+ All rows have a stable `key` and discriminant `type`. Shared `RowBase` metadata
16
+ includes `height`, `size`, `density`, `sectionKey`, `groupId`, `groupPosition`,
17
+ selection/disabled state and separator intent. These are model/layout inputs,
18
+ not a freeform style object. Every template also accepts `style.container.height`
19
+ to override `row.height`; clearing it restores the original height/measurement.
20
+ The style changes the row allocation without changing its internal slot order.
21
+ Declaring `sectionKey` never makes a business
22
+ template the owner of sections or the indexed bar.
23
+
24
+ | Type | Purpose | Fixed structure |
25
+ | --- | --- | --- |
26
+ | [identity](#identity) | Asset, account, wallet or network | Leading visual + identity text + trailing accessories; named selector variants |
27
+ | [walletGroup](#walletgroup) | Wallet family in the sidebar | Parent wallet followed by child wallets |
28
+ | [rail](#rail) | Compact navigation/status item | Compact visual + title + optional status/badge |
29
+ | [activity](#activity) | Transaction/activity item | Identity/description + amounts + optional row-local actions |
30
+ | [message](#message) | Notification | Title/body/time + optional leading visual/thumbnail |
31
+ | [dataRow](#datarow) | Comparable values | Two to four stable weighted columns |
32
+ | [market](#market) | Token/stock/perpetual quote | Asset identity + price + change block |
33
+ | [mediaTile](#mediatile) | Gallery or browser preview | Media area over caption metadata |
34
+ | [metricCard](#metriccard) | KPI or portfolio summary | Label/value card or named composite metrics arrangement |
35
+ | [sectionHeader](#sectionheader) | Structural section heading | Header text + optional summary value/controls |
36
+ | [action](#action) | A row-level command | Label + optional icon/value/controls |
37
+ | [system](#system) | Loading, retry, warning, empty/end or spacer | Variant-specific bounded status content |
38
+
39
+ The style roles below form the shared configurable contract on Web, iOS and
40
+ Android. **Template** means structure and content fields; **row style** means
41
+ allowlisted parameters applied to those existing fields. Each template exposes
42
+ only applicable box/image parameters, listed in [STYLE_SPEC §4.1](STYLE_SPEC.md#41-shared-configurable-properties).
43
+ All templates accept the shared `style.container` surface (background, opacity,
44
+ radius, border and content vertical alignment). All text roles share the same
45
+ typography, 1–3 line limit, truncation, alignment and optical-offset properties; supported
46
+ image roles share the same dimensions/shape/fit properties. An absent optional
47
+ field is not created by styling it. Native rendered acceptance is tracked
48
+ separately from source implementation in STYLE_SPEC §9.
49
+
50
+ ## identity
51
+
52
+ ![Identity: leading visual, title and optional secondary text, badges and trailing accessories](images/row-identity.svg)
53
+
54
+ - **Use:** an identifiable asset, account, wallet, network or setting.
55
+ - **Required data:** `leading`, `title`; optional `subtitle`, `tertiary`, `badges`,
56
+ `trailing`, `leadingAction`, match ranges and structured subtitle segments.
57
+ - **Variants:** default horizontal row; `accountSelector` and `networkSelector`
58
+ preserve selector control geometry; `walletSidebar` uses a compact, centered
59
+ wallet presentation. A variant is explicit model data, never inferred from font size.
60
+ Selector control geometry applies on all platforms when the row has an
61
+ explicit height from either `style.container.height` or the legacy `row.height`.
62
+ - **Separator:** the default native separator inset is 60 for identity rows
63
+ and 12 for other templates (Web 0).
64
+ - **Platform default:** without `subtitleLines` or `style.subtitle.lines`, the
65
+ subtitle shows one line on iOS and Web but two on Android (STYLE_SPEC §6.2).
66
+ - **Text style roles:** `title`, `subtitle`, `tertiary`, `badge`, `value`,
67
+ `valueSecondary`. The last two refer to value accessories in `trailing`; `badge`
68
+ refers to badge text. `value`/`valueSecondary` select the first/second value
69
+ accessory, ignoring intervening controls. A `valuePair` is one accessory, so
70
+ its style applies to both text runs. They are semantic roles, not extra top-level data fields.
71
+ - **Layout boundary:** reserve visual and accessory slots; text compresses within
72
+ its own column. Styling cannot move a checkbox/menu into the title column,
73
+ reorder accessories or convert a horizontal row into the sidebar presentation.
74
+ - **Verification:** Web style ordering and removal have DOM regression coverage
75
+ for both selector presentations. Rendered geometry remains to be verified.
76
+
77
+ ## walletGroup
78
+
79
+ ![Wallet group: parent wallet and child wallet members inside one composite container](images/row-wallet-group.svg)
80
+
81
+ - **Use:** one wallet family in the wallet sidebar, as a single composite row.
82
+ - **Required data:** `parent: IdentityRow`, nonempty `children: IdentityRow[]`.
83
+ Every member must use `presentation: 'walletSidebar'`; `parent.key` must equal
84
+ the group row's `key`, and member keys must be unique within the group.
85
+ - **Default appearance:** the group border is drawn beneath member content.
86
+ Native groups ignore the row-level `backgroundColor` (legacy): the fill is
87
+ `style.container.backgroundColor` or the theme `subduedBackground`. Legacy Web
88
+ still applies `backgroundColor` inline, so use `style.container.backgroundColor`
89
+ for a cross-platform fill. `style.container` background, border and radius
90
+ override the group fill, border and radius on every platform.
91
+ - **Drag:** only `draggable: false` excludes a member from starting the group
92
+ drag; disabled members can start it. The compact allocation is 68 on iOS/Web
93
+ and `max(68, parent height + 2 × vertical inset)` on Android.
94
+ - **Style surface:** group `style` exposes the shared container appearance and horizontal/vertical padding. Text styles belong to
95
+ `parent.style` or the individual `children[i].style`; there is no inherited
96
+ group `title`/`value` text style. Measured group height is the sum of member
97
+ heights, 12-unit member gaps and twice the vertical inset. The default inset
98
+ is 1 unit (the group border) when the parent member carries `height`, else 0;
99
+ `style.verticalPadding` / `horizontalPadding` replace it rather than adding
100
+ to it, and bind uses the same value as measurement on every platform.
101
+ iOS/Android ignore the group's own `row.height` (legacy; `style.container.height`
102
+ still wins); Web honors it.
103
+ - **Member lifecycle:** each member uses an independent Identity renderer, reused
104
+ by member key. Removed members release their images/actions immediately.
105
+ Press and accessory events use the member key; group dragging remains atomic.
106
+ Optional trailing controls require sufficient caller-supplied member height.
107
+ - **Layout boundary:** preserve parent-first member order and wallet member
108
+ structure. Local padding cannot change ownership, member count or drag identity.
109
+ Group `lineGap` does not override the text spacing inside member rows.
110
+ - **Common-capability boundary:** this is not a generic section and does not
111
+ control header/footer placement. General grouped cards use `groupId` and
112
+ `groupPosition`; do not conflate those with this composite template.
113
+
114
+ ## rail
115
+
116
+ ![Rail: compact visual, title, optional badge and status](images/row-rail.svg)
117
+
118
+ - **Use:** a compact navigation or status item, including horizontal rails.
119
+ - **Required data:** `visual`, `title`; optional `badge`, `status` and `draggable`.
120
+ Status is one of `none`, `online`, `warning`, `error`.
121
+ - **Text style roles:** `title`, `badge`, `status` where rendered. Status can be a
122
+ platform-specific indicator rather than a text label; accepting a text style
123
+ does not prove that path has a visible effect.
124
+ - **Layout boundary:** retain the compact visual/title/accessory structure.
125
+ Row styling cannot enable horizontal scrolling or reorder for the whole list;
126
+ orientation and reorder orchestration belong to the container.
127
+ - **Current divergence:** default height is 40 on iOS/Web and 28 on Android.
128
+ This catalog does not change those defaults.
129
+
130
+ ## activity
131
+
132
+ ![Activity: leading visual and description, trailing amounts, optional actions within the row](images/row-activity.svg)
133
+
134
+ - **Use:** a transaction/activity record with amounts and optional commands.
135
+ - **Required data:** `leading`, `title`; optional `secondaryLeading`,
136
+ `description`, `status`, `primaryAmount`, `secondaryAmount`, `footerActions`.
137
+ At most three footer actions are accepted, each with a unique key.
138
+ - **Text style roles:** `title`, `description`, `status`, `primaryAmount`,
139
+ `secondaryAmount`. `footerActions` do not gain a freeform style surface.
140
+ - **Layout boundary:** amounts remain in the amount column, description stays
141
+ in its text region, actions stay in the row's action area. Adding actions is a
142
+ model/height choice, not a typography trick.
143
+ - **Common-capability boundary:** `footerActions` are inside this activity row.
144
+ The list footer is independently configured through the container.
145
+
146
+ ## message
147
+
148
+ ![Message: title and timestamp over body text, with optional leading visual and thumbnail](images/row-message.svg)
149
+
150
+ - **Use:** a notification or message preview.
151
+ - **Required data:** `title`, `body`, `time`; optional `leading`, `thumbnail`,
152
+ `unread`. `bodyLines` is the legacy fallback for one, two or three body lines.
153
+ - **Text style roles:** `title`, `body`, `time`. `style.body.lines` accepts one, two or three and takes precedence over `bodyLines`.
154
+ - **Layout boundary:** time and thumbnail keep their allocated regions; body
155
+ text wraps/truncates within the message area. Styling cannot displace the
156
+ timestamp, grow over the next row, or turn the preview into unbounded content.
157
+ - **Current divergence:** leading-image size and body typography differ across
158
+ platforms. Larger line boxes need explicit height and visual verification.
159
+
160
+ ## dataRow
161
+
162
+ ![Data row: optional index and visual, stable columns with primary and secondary text, optional checkbox](images/row-data.svg)
163
+
164
+ - **Use:** compare values in a linear list or table.
165
+ - **Required data:** `columns` with two to four entries. Each column has `key`,
166
+ `text`, optional secondary text, `weight` (1/2/3), alignment and tones.
167
+ Optional row fields include `leading`, `index`, badges, checkbox and favorite state.
168
+ - **Text style roles:** `columns` styles primary column text; `columnSecondary`
169
+ styles secondary column text; `index` styles the ordinal. These are collective
170
+ semantic roles, not arbitrary per-native-label selectors.
171
+ - **Layout boundary:** column order/count/weights are data, shared table column
172
+ alignment is layout. Text styles cannot change those or move favorite/checkbox
173
+ controls into a data column. Default heights (legacy, per platform): linear
174
+ 56, or 60 with secondary text (Android 64); table 60 with secondary text,
175
+ otherwise 48 on iOS/Web and 52 on Android (STYLE_SPEC §6.1).
176
+ - **Linear layout per platform (legacy defaults):**
177
+ - *iOS and Android, unstyled:* one label per column holding the primary text,
178
+ up to two inline badge runs and the secondary text on a second line.
179
+ `secondaryLeadingText` is not rendered. On Android, `disabled`/`caution`
180
+ tones render as primary text (legacy tone mapping).
181
+ - *iOS, styled:* the same single label. `columns`/`columnSecondary` apply
182
+ font, weight, color, line height and alignment to their text runs/lines;
183
+ `lines`, `truncate`, `verticalAlignment` and `offsetY` act on the whole
184
+ label. Badge pills keep the legacy two-space padding inside their
185
+ background; `titleBadgeGap` adds an exact, unfilled gap between the title
186
+ and the first pill. Unstyled rows are unchanged.
187
+ - *Android, text-styled:* only `style.columns`, `columnSecondary`, `lineGap`
188
+ or `titleBadgeGap` switch a row off the legacy layout (single label per
189
+ column in linear; fixed 40dp column blocks with 20/16dp lines in table).
190
+ The separate column view is then used (primary line with pill badges,
191
+ secondary line with secondary leading text), so each role styles its own
192
+ view. Container, padding, image, `leadingGap` and `index` styles keep the
193
+ legacy text layout.
194
+ - *Web:* `secondaryLeadingText` precedes the primary text on the same line,
195
+ badges follow it, and secondary text is directly below.
196
+ - Table layout uses the column view on every platform (Android unstyled:
197
+ the fixed legacy column geometry above).
198
+ - **Style isolation:** primary and secondary text use independent style targets in
199
+ linear and table layouts on all three platforms. Column badges keep their own typography.
200
+
201
+ ## market
202
+
203
+ ![Market: asset visual and title/subtitle/badges, followed by price and a bounded change block](images/row-market.svg)
204
+
205
+ - **Use:** a recycled market quote row with already formatted/localized values.
206
+ - **Required data:** `variant: token | stock | perp`, `leading`, `title`, `price`,
207
+ `change` (text and tone). Optional subtitle segments/prefix, badges, leading
208
+ action and press/press-in/long-press action keys remain data.
209
+ - **Text style roles:** `title`, `subtitle`, `price`, `change`.
210
+ - **Additional local parameters:** `titleBadgeLayout: 'inline'`,
211
+ `contentTrailingGap`, `subtitleTrailingPadding`, `changeWidth`, `changeHeight`,
212
+ `changeCornerRadius`, plus box/image metrics. Badge models and subtitle prefix
213
+ have their own existing style fields; they do not create arbitrary child views.
214
+ A `subscript` segment is `ceil(0.6 × field fontSize)` on a `fontSize` line box
215
+ (legacy), including under an explicit `fontSize`. Web uses a `fontSize` line box;
216
+ iOS/Android keep the field line height, as their legacy renderers did.
217
+ - **Layout boundary:** price and change keep their regions; the localized name
218
+ compresses independently from volume where supported. Styling does not change
219
+ token/stock/perp structure or affect sections, index navigation or pagination.
220
+
221
+ ## mediaTile
222
+
223
+ ![Media tile: image and optional badge/network/close overlays above title and subtitle](images/row-media-tile.svg)
224
+
225
+ - **Use:** a gallery tile or browser preview.
226
+ - **Required data:** `variant: gallery | browserPreview`, `title`. Optional
227
+ image/image-state, subtitle, badge, network image and close-action key.
228
+ - **Text style roles:** `title`, `subtitle`, `badge`.
229
+ - **Layout boundary:** media stays above caption metadata; network/close/badge
230
+ overlays keep their template anchors. A text style cannot change the grid
231
+ column count, tile span or move the caption over the image.
232
+ - **Common-capability boundary:** grid columns and list scrolling belong to
233
+ `snapshot.layout`, not to `MediaTileRowStyle`. Primary-image overrides are
234
+ supported on all three platforms; network/close overlays retain their anchors.
235
+
236
+ ## metricCard
237
+
238
+ ![Metric card: standard label and large value; named composite variant with bounded metric cells](images/row-metric-card.svg)
239
+
240
+ - **Use:** a single KPI or a fixed portfolio activity/performance summary.
241
+ - **Required data:** `title`, `value`; optional subtitle, trend/tone, visual, badge,
242
+ metrics and progress. The model still requires `value` for composite variants.
243
+ - **Variants:** default/`standard` shows a large value; `activity` and `performance`
244
+ use the fixed composite arrangement. `metrics`, when supplied, contains two to
245
+ five entries; each entry has key, label and value. Progress is bounded to 0…1.
246
+ - **Text style roles:** `title` is the small label on the standard card; `value`
247
+ is the large number; `subtitle` and `trend` have their own roles. Do not map them
248
+ by shared UIKit/Android view names, which are different from these meanings.
249
+ In `activity`/`performance`, only `title` maps to the composite heading. The
250
+ other standard-card roles do not address `metrics[].label` or `metrics[].value`.
251
+ - **Layout boundary:** styles cannot change the number/order of metric cells or
252
+ turn the standard card into a composite card. Composite subfield mapping needs
253
+ explicit coverage; do not assume `style.value` reaches every nested metric.
254
+ - **Style boundary:** nested metric fields have no declared local text-style roles on any platform.
255
+ The standard card example alone cannot validate composite heading styling.
256
+
257
+ ## sectionHeader
258
+
259
+ ![Section header: title/subtitle and optional summary value, help or selection control](images/row-section-header.svg)
260
+
261
+ - **Use:** a structural section heading or list summary, independent of the
262
+ business templates in the section.
263
+ - **Required data:** `sectionKey`, `title`; optional subtitle, value, title/value
264
+ icons/actions, checkbox, `sticky`, `indexTitle`. Variants: default, `summary`,
265
+ `gallery`, `history`; `presentation: 'networkSelector'` is also available.
266
+ - **Text style roles:** `title`, `subtitle`, `value`.
267
+ - **Layout boundary:** preserve heading/value/control regions. `summary` does
268
+ not accept a checkbox and is not sticky. Pinning and index-entry generation are
269
+ container behavior, not a text-style property.
270
+ - **Common-capability boundary:** `sectionHeader` is the current serialized
271
+ heading descriptor, not a header feature attached to `identity` or another
272
+ content template. `indexTitle` supplies the shared indexed bar's label.
273
+ - **Pinned rendering:** the container reuses the ordinary header renderer on all
274
+ platforms, including headers with a value or checkbox. Summary is non-sticky.
275
+
276
+ ## action
277
+
278
+ ![Action: optional icon, command title, optional trailing value/accessories or checkbox](images/row-action.svg)
279
+
280
+ - **Use:** a row-level command, including content used in a fixed footer.
281
+ - **Required data:** `title`, `actionKey`; optional tone (`primary`, `neutral`,
282
+ `danger`), icon, checkbox and trailing accessories. `accountSelector` is a
283
+ named presentation variant.
284
+ - **Text style roles:** `title`, `value` (a trailing value accessory).
285
+ - **Layout boundary:** preserve icon/text/control ordering and action hit areas.
286
+ Styling cannot create a new command or change action routing.
287
+ - **Common-capability boundary:** the same action descriptor can live in
288
+ `rows`, `fixedFooter` or `emptyState`. The container decides placement and
289
+ visibility; the action template only renders its content.
290
+
291
+ ## system
292
+
293
+ ![System variants: loading indicator, retry message and action, warning, no-match/end text and explicit spacer](images/row-system.svg)
294
+
295
+ - **Use:** bounded status content rather than a business record.
296
+ - **Variants and required data:** `loading` has optional message and
297
+ skeleton/spinner choice; `retry` requires message/action key with optional
298
+ action text; `warning` requires title/message; `noMatch` requires message;
299
+ `end` has optional message; `spacer` requires explicit height.
300
+ - **Text style roles:** `title` for a visible title, `message` for status copy,
301
+ `actionText` for the native retry button text. Web (legacy) draws no retry
302
+ button for any presentation: a Web retry row is message-only and the row
303
+ press (click, Enter or Space) emits `actionKey`, so `actionText` and
304
+ `style.actionText` have no Web target (native only). On Android the Market
305
+ retry/noMatch message and the retry `actionText` ellipsize at the end by
306
+ default; an explicit `lines` or `truncate` (including `clip`) wins. A spacer has no text slot; skeleton/spinner styling
307
+ does not become arbitrary drawing through these text roles.
308
+ - **Height:** without `row.height`/`style.container.height`, Web lays out a
309
+ warning at its rendered height (padding, both borders, wrapped text), as the
310
+ legacy engine did; native measures its text.
311
+ - **Layout boundary:** keep each variant's indicator/text/action structure and
312
+ bounded height. Styling cannot convert loading into retry, turn a spacer into
313
+ content, or hide adjacent rows.
314
+ - **Common-capability boundary:** a system row can be regular content,
315
+ `emptyState` or `fixedFooter`. Refresh/pagination state remains on the list;
316
+ a loading row alone does not enable either capability.
317
+
318
+ ## Composition example: shared sections, footer and indexed bar
319
+
320
+ This uses existing public fields. Both content templates share one section;
321
+ neither implements its own header, footer, scrolling or indexed bar. There is no
322
+ new header prop in this example: the heading is a structural row.
323
+
324
+ ```ts
325
+ import type { NativeListSnapshot } from '@onekeyfe/react-native-native-list';
326
+
327
+ const snapshot: NativeListSnapshot = {
328
+ schemaVersion: 1,
329
+ generation: 1,
330
+ layout: { kind: 'sectioned', stickyHeaders: true },
331
+ capabilities: { sectionIndex: { enabled: true } },
332
+ rows: [
333
+ {
334
+ type: 'sectionHeader', key: 'section-a', sectionKey: 'a',
335
+ title: 'Assets', indexTitle: 'A',
336
+ },
337
+ {
338
+ type: 'identity', key: 'asset-btc', sectionKey: 'a',
339
+ leading: { kind: 'icon', name: 'StarOutline' }, title: 'Bitcoin',
340
+ style: { title: { token: '$bodyMd' } },
341
+ },
342
+ {
343
+ type: 'market', key: 'quote-eth', sectionKey: 'a', variant: 'token',
344
+ leading: { kind: 'token', fallbackText: 'ETH' }, title: 'Ethereum',
345
+ price: '$2,400', change: { text: '+2.4%', tone: 'positive' },
346
+ },
347
+ ],
348
+ fixedFooter: {
349
+ type: 'action', key: 'continue', title: 'Continue', actionKey: 'continue',
350
+ },
351
+ };
352
+ ```
353
+
354
+ `listRef.current?.scrollToKey({ key: 'quote-eth', animated: true })` addresses the
355
+ stable row key through the shared list API. Changing the quote's content template
356
+ while preserving a valid key/section does not introduce a new scroll API.
357
+
358
+ For completion criteria and the source audit, return to
359
+ [STYLE_SPEC §6–§9](STYLE_SPEC.md#65-consolidated-gap-audit).