@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.
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,43 @@
1
+ "use strict";
2
+
3
+ const properties = ['width', 'height', 'flex-basis', 'border-radius', 'overflow', 'object-fit', 'margin-inline-end', 'margin-bottom', 'align-self', 'border', 'box-sizing', 'clip-path', 'flex'];
4
+
5
+ /** Restores factory geometry without touching async loading visibility. */
6
+ export class RowVisualStyle {
7
+ defaults = new Map();
8
+ constructor(view) {
9
+ this.view = view;
10
+ [view, ...view.querySelectorAll('*')].forEach(element => {
11
+ this.defaults.set(element, new Map(properties.map(key => [key, element.style.getPropertyValue(key)])));
12
+ });
13
+ }
14
+ restore() {
15
+ this.defaults.forEach((style, element) => style.forEach((value, key) => {
16
+ element.style.removeProperty(key);
17
+ if (value) element.style.setProperty(key, value);
18
+ }));
19
+ }
20
+ apply(image, width, height, margin) {
21
+ this.restore();
22
+ const leading = this.view;
23
+ leading.style.width = `${width}px`;
24
+ leading.style.height = `${height}px`;
25
+ leading.style.flexBasis = `${width}px`;
26
+ leading.style.marginInlineEnd = `${margin}px`;
27
+ const radius = image?.cornerRadius !== undefined ? `${image.cornerRadius}px` : image?.shape === 'circle' ? '50%' : image?.shape === 'square' ? '0px' : image?.shape === 'rounded' ? '10px' : undefined;
28
+ if (radius !== undefined) {
29
+ leading.style.setProperty('border-radius', radius, 'important');
30
+ leading.style.overflow = leading.matches('img') ? 'hidden' : 'visible';
31
+ }
32
+ const images = leading.matches('img') ? [leading] : leading.querySelectorAll(':scope > img:not(.ok-native-list-visual-corner), :scope > .ok-native-list-visual-fallback:not(.ok-native-list-visual-corner)');
33
+ images.forEach(bitmap => {
34
+ if (bitmap !== leading) {
35
+ if (image?.width !== undefined) bitmap.style.width = '100%';
36
+ if (image?.height !== undefined) bitmap.style.height = '100%';
37
+ }
38
+ if (radius !== undefined) bitmap.style.borderRadius = radius;
39
+ if (image?.contentFit) bitmap.style.objectFit = image.contentFit === 'center' ? 'none' : image.contentFit;
40
+ });
41
+ }
42
+ }
43
+ //# sourceMappingURL=RowVisual.js.map
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ import { applyTabularNumbers, hasExplicitRowHeight } from "./RowElements.js";
4
+ import { createElement, setData, tagSlot, markActionAnchorSource, createTextColumn } from "./RowElements.js";
5
+ import { applyValueSegments } from "./RowText.js";
6
+ function createSectionHeader(document, primitives, row) {
7
+ const body = createElement(document, 'div', 'ok-native-list-row ok-native-list-section');
8
+ setData(body, 'variant', row.variant);
9
+ if (row.titleIcon) {
10
+ const titleIcon = primitives.iconAction(row.titleIcon.name, row.titleIcon.actionKey, row.titleIcon.disabled, row.titleIcon.tintColor);
11
+ markActionAnchorSource(titleIcon, 'leadingAction');
12
+ body.appendChild(titleIcon);
13
+ }
14
+ // OneKey patch: section title help has its own measurable action target.
15
+ // body.appendChild(createTextColumn(document, row.title, row.subtitle));
16
+ const column = createTextColumn(document, row.title, row.subtitle);
17
+ const title = column.firstElementChild;
18
+ title.classList.add('ok-native-list-section-title');
19
+ if (row.titleActionKey) {
20
+ setData(title, 'nativeListAction', row.titleActionKey);
21
+ markActionAnchorSource(title, 'leadingAction');
22
+ title.setAttribute('role', 'button');
23
+ title.tabIndex = 0;
24
+ title.style.alignSelf = 'flex-start';
25
+ title.style.maxWidth = '100%';
26
+ // OneKey patch: explicit network headers reserve a separate 3-point underline area.
27
+ if (row.presentation !== 'networkSelector' || !hasExplicitRowHeight(row)) {
28
+ title.style.textDecoration = 'underline dotted';
29
+ title.style.textUnderlineOffset = '6px';
30
+ }
31
+ if (row.titleActionOnHover) setData(title, 'nativeListHoverAction', true);
32
+ }
33
+ if (row.presentation === 'networkSelector' && hasExplicitRowHeight(row)) {
34
+ body.style.padding = row.variant === 'summary' ? '24px 12px 20px' : '0 12px';
35
+ body.style.backgroundColor = 'var(--nl-bg)';
36
+ body.style.gap = row.checkbox ? '12px' : '8px';
37
+ title.style.fontSize = row.variant === 'summary' ? '16px' : '14px';
38
+ title.style.lineHeight = row.variant === 'summary' ? '24px' : '20px';
39
+ title.style.fontWeight = row.variant === 'summary' || row.titleActionKey && !row.checkbox ? '500' : '600';
40
+ if (row.titleActionKey) {
41
+ const text = createElement(document, 'span', 'ok-native-list-section-title-text', row.title);
42
+ text.style.overflow = 'hidden';
43
+ text.style.textOverflow = 'ellipsis';
44
+ text.style.maxWidth = '100%';
45
+ const dotted = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
46
+ dotted.setAttribute('height', '2');
47
+ dotted.style.cssText = 'display:block;position:absolute;left:0;bottom:0;width:100%;height:2px;color:var(--nl-secondary)';
48
+ const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
49
+ for (const [key, value] of Object.entries({
50
+ x1: '1',
51
+ y1: '1',
52
+ x2: '100%',
53
+ y2: '1',
54
+ stroke: 'currentColor',
55
+ 'stroke-width': '1.5',
56
+ 'stroke-dasharray': '0,4',
57
+ 'stroke-linecap': 'round'
58
+ })) line.setAttribute(key, value);
59
+ // OneKey patch: keep both round caps inside the original full-width viewport.
60
+ const lineViewport = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
61
+ lineViewport.setAttribute('width', 'calc(100% - 1px)');
62
+ lineViewport.setAttribute('height', '2');
63
+ lineViewport.setAttribute('overflow', 'visible');
64
+ lineViewport.appendChild(line);
65
+ dotted.appendChild(lineViewport);
66
+ // OneKey patch: SVG intrinsic width must not expand the title action beyond its text.
67
+ title.style.display = 'block';
68
+ title.style.position = 'relative';
69
+ title.style.width = 'fit-content';
70
+ title.style.paddingBottom = '3px';
71
+ text.style.display = 'block';
72
+ title.replaceChildren(text, dotted);
73
+ }
74
+ }
75
+ body.appendChild(column);
76
+ if (row.value) {
77
+ const value = tagSlot(createElement(document, row.valueActionKey ? 'button' : 'span', row.valueActionKey ? 'ok-native-list-action-button ok-native-list-section-value' : 'ok-native-list-value ok-native-list-section-value', row.value), 'value');
78
+ applyValueSegments(value, row.valueSegments);
79
+ if (row.presentation === 'networkSelector' && hasExplicitRowHeight(row)) {
80
+ value.style.fontFamily = 'inherit';
81
+ value.style.fontSize = '16px';
82
+ value.style.lineHeight = '24px';
83
+ value.style.fontWeight = '500';
84
+ if (row.valueActionKey) {
85
+ value.style.color = 'var(--nl-secondary)';
86
+ value.style.padding = '0';
87
+ value.style.flexShrink = '0';
88
+ }
89
+ }
90
+ if (row.valueActionTestID) setData(value, 'testid', row.valueActionTestID);
91
+ if (row.valueActionKey) {
92
+ value.setAttribute('type', 'button');
93
+ setData(value, 'nativeListAction', row.valueActionKey);
94
+ markActionAnchorSource(value, 'trailingAccessory', 0);
95
+ }
96
+ body.appendChild(value);
97
+ }
98
+ if (row.valueIcon) {
99
+ const valueIcon = primitives.iconAction(row.valueIcon.name, row.valueIcon.actionKey, row.valueIcon.disabled, row.valueIcon.tintColor);
100
+ markActionAnchorSource(valueIcon, 'trailingAccessory', 1);
101
+ body.appendChild(valueIcon);
102
+ }
103
+ if (row.checkbox) body.appendChild(primitives.accessory(row.key, row.checkbox, 0));
104
+ return body;
105
+ }
106
+ function bind(body, row, primitives) {
107
+ const next = createSectionHeader(body.ownerDocument, primitives, row);
108
+ body.replaceChildren(...Array.from(next.childNodes));
109
+ body.className = next.className;
110
+ body.style.cssText = next.style.cssText;
111
+ if (row.presentation === 'networkSelector') applyTabularNumbers(body);
112
+ body.dataset.variant = row.variant ?? '';
113
+ body.removeAttribute('data-nl-container-background');
114
+ body.removeAttribute('data-nl-container-border');
115
+ const style = row.style;
116
+ if (!style) return;
117
+ if (style.horizontalPadding !== undefined) body.style.paddingInline = style.horizontalPadding + 'px';
118
+ if (style.verticalPadding !== undefined) body.style.paddingBlock = style.verticalPadding + 'px';
119
+ if (style.lineGap !== undefined) body.querySelectorAll(':scope > .ok-native-list-flex').forEach(column => {
120
+ column.style.rowGap = style.lineGap + 'px';
121
+ });
122
+ if (style.trailingGap !== undefined) {
123
+ const children = Array.from(body.children);
124
+ const column = children.findIndex(child => child.classList.contains('ok-native-list-flex'));
125
+ children.slice(column + 2).forEach(child => {
126
+ child.style.marginInlineStart = 'calc(' + style.trailingGap + 'px - ' + (body.style.gap || '12px') + ')';
127
+ });
128
+ }
129
+ for (const slot of ['title', 'subtitle', 'value']) if (style[slot]) body.querySelectorAll('[data-nl-slot="' + slot + '"]').forEach(node => primitives.textStyle(node, style[slot]));
130
+ }
131
+ function create(document, row, primitives) {
132
+ const body = document.createElement('div');
133
+ body.dataset.nlRenderer = 'sectionHeader';
134
+ bind(body, row, primitives);
135
+ return body;
136
+ }
137
+ export const sectionHeaderRowRenderer = {
138
+ key: 'sectionHeader',
139
+ create,
140
+ bind,
141
+ recycle: body => body.replaceChildren(),
142
+ appliesSizePreset: row => !['summary', 'gallery'].includes(row.variant ?? ''),
143
+ measure: (row, _width, layout = 'linear') => layout === 'table' ? 28 : row.presentation === 'networkSelector' ? 47 : row.variant === 'history' ? 16 : row.variant === 'summary' ? 68 : row.variant === 'gallery' ? 32 : row.checkbox ? 56 : layout === 'linear' ? 30 : 36,
144
+ measureRendered: (_body, _row) => undefined
145
+ };
146
+ //# sourceMappingURL=SectionHeaderRowRenderer.js.map
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+
3
+ import { captureInlineStyles, createElement, hasExplicitRowHeight, restoreInlineStyles, setData, tagSlot } from "./RowElements.js";
4
+ function createSystemRow(document, primitives, row) {
5
+ const body = createElement(document, 'div', 'ok-native-list-row ok-native-list-system');
6
+ setData(body, 'variant', row.variant);
7
+ if ('presentation' in row) setData(body, 'nativeListPresentation', row.presentation);
8
+ if (row.variant === 'loading' && row.loadingStyle === 'skeleton') {
9
+ body.classList.add('ok-native-list-market-skeleton');
10
+ const background = primitives.background;
11
+ const rgb = Number.parseInt(background.slice(1, 7), 16);
12
+ const dark = (rgb >> 16 & 255) * 0.299 + (rgb >> 8 & 255) * 0.587 + (rgb & 255) * 0.114 < 128;
13
+ body.style.setProperty('--nl-skeleton-base', dark ? '#111111' : '#fafafa');
14
+ body.style.setProperty('--nl-skeleton-highlight', dark ? '#333333' : '#cdcdcd');
15
+ const left = createElement(document, 'div', 'ok-native-list-skeleton-left');
16
+ const mark = (width, height, circle = false) => {
17
+ const element = createElement(document, 'span', 'ok-native-list-skeleton-mark');
18
+ element.style.width = `${width}px`;
19
+ element.style.height = `${height}px`;
20
+ if (circle) element.style.borderRadius = '50%';
21
+ return element;
22
+ };
23
+ left.appendChild(mark(32, 32, true));
24
+ const text = createElement(document, 'div', 'ok-native-list-skeleton-text');
25
+ text.appendChild(mark(80, 16));
26
+ text.appendChild(mark(60, 12));
27
+ left.appendChild(text);
28
+ body.appendChild(left);
29
+ const right = createElement(document, 'div', 'ok-native-list-skeleton-right');
30
+ right.appendChild(mark(80, 18));
31
+ right.appendChild(mark(80, 18));
32
+ body.appendChild(right);
33
+ return body;
34
+ }
35
+ if (row.variant === 'loading' && row.loadingStyle === 'spinner') {
36
+ body.style.justifyContent = 'center';
37
+ body.style.padding = '16px';
38
+ const spinner = createElement(document, 'span', 'ok-native-list-market-spinner');
39
+ spinner.setAttribute('role', 'progressbar');
40
+ // Same 20px SVG and 750ms rotation as react-native-web ActivityIndicator.
41
+ spinner.innerHTML = '<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>';
42
+ body.appendChild(spinner);
43
+ return body;
44
+ }
45
+ if ('presentation' in row && row.presentation === 'market') {
46
+ if (row.variant === 'noMatch') {
47
+ body.style.justifyContent = 'center';
48
+ body.style.padding = '32px';
49
+ const message = tagSlot(createElement(document, 'span', '', row.message), 'message');
50
+ message.style.fontSize = '16px';
51
+ message.style.lineHeight = '24px';
52
+ body.appendChild(message);
53
+ return body;
54
+ }
55
+ if (row.variant === 'end') {
56
+ body.style.justifyContent = 'center';
57
+ body.style.padding = '16px';
58
+ body.style.gap = '8px';
59
+ for (const width of [80, 4, 80]) {
60
+ const mark = createElement(document, 'span', '');
61
+ mark.style.width = String(width) + 'px';
62
+ mark.style.height = width === 4 ? '4px' : '1px';
63
+ mark.style.borderRadius = width === 4 ? '2px' : '0';
64
+ mark.style.background = 'var(--nl-separator)';
65
+ body.appendChild(mark);
66
+ }
67
+ return body;
68
+ }
69
+ }
70
+ if (row.variant === 'warning') {
71
+ body.classList.add('ok-native-list-warning');
72
+ body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
73
+ body.appendChild(tagSlot(createElement(document, 'span', 'ok-native-list-warning-title', row.title), 'title'));
74
+ body.appendChild(tagSlot(createElement(document, 'span', 'ok-native-list-warning-message', row.message), 'message'));
75
+ return body;
76
+ }
77
+ if (row.variant === 'loading') body.appendChild(createElement(document, 'span', 'ok-native-list-spinner'));
78
+ const message = row.variant === 'spacer' ? '' : row.message ?? (row.variant === 'end' ? 'End' : '');
79
+ if (message) body.appendChild(tagSlot(createElement(document, 'span', 'ok-native-list-secondary', message), 'message'));
80
+ // Legacy Web draws no retry button for any presentation: a retry row shows
81
+ // only its message and the whole row (click, Enter or Space) emits the
82
+ // retry `actionKey`. `actionText` / `style.actionText` therefore have no Web
83
+ // target; they style the native retry button only.
84
+ return body;
85
+ }
86
+ const bindings = new WeakMap();
87
+ function bind(body, row, primitives) {
88
+ // Text styles are part of the key: applyTextLayout inserts wrappers and
89
+ // rewrites text (lines: 1), which restoring inline styles cannot undo.
90
+ const content = {
91
+ ...row,
92
+ style: {
93
+ title: row.style?.title,
94
+ message: row.style?.message
95
+ }
96
+ };
97
+ const key = JSON.stringify([content, primitives.background]);
98
+ let binding = bindings.get(body);
99
+ if (!binding || binding.key !== key) {
100
+ const next = createSystemRow(body.ownerDocument, primitives, row);
101
+ body.replaceChildren(...Array.from(next.childNodes));
102
+ body.className = next.className;
103
+ body.style.cssText = next.style.cssText;
104
+ body.dataset.variant = row.variant;
105
+ body.dataset.nativeListPresentation = 'presentation' in row ? row.presentation ?? '' : '';
106
+ binding = {
107
+ key,
108
+ defaults: captureInlineStyles(body)
109
+ };
110
+ bindings.set(body, binding);
111
+ }
112
+ restoreInlineStyles(binding.defaults);
113
+ body.removeAttribute('data-nl-container-background');
114
+ body.removeAttribute('data-nl-container-border');
115
+ const style = row.style;
116
+ if (style?.horizontalPadding !== undefined) body.style.paddingInline = `${style.horizontalPadding}px`;
117
+ if (style?.verticalPadding !== undefined) body.style.paddingBlock = `${style.verticalPadding}px`;
118
+ if (style?.lineGap !== undefined && row.variant === 'warning') body.style.rowGap = `${style.lineGap}px`;
119
+ for (const slot of ['title', 'message']) {
120
+ const text = style?.[slot];
121
+ if (!text) continue;
122
+ body.querySelectorAll(`[data-nl-slot="${slot}"]`).forEach(node => primitives.textStyle(node, text, row.variant === 'warning' ? 0 : undefined));
123
+ }
124
+ }
125
+ function create(document, row, primitives) {
126
+ const body = document.createElement('div');
127
+ body.dataset.nlRenderer = 'system';
128
+ bind(body, row, primitives);
129
+ return body;
130
+ }
131
+ function measure(row, width) {
132
+ if (row.variant === 'warning') {
133
+ const textWidth = Math.max(1, width - (row.style?.horizontalPadding ?? 12) * 2);
134
+ const height = (text, style) => {
135
+ const size = style?.fontSize ?? 14;
136
+ const lines = text.split(/\r\n|[\r\n]/).reduce((total, line) => total + Math.max(1, Math.ceil(Array.from(line).reduce((length, char) => length + (char.charCodeAt(0) > 255 ? size : size / 2), 0) / textWidth)), 0);
137
+ return Math.min(style?.lines ?? Infinity, lines) * (style?.lineHeight ?? 20);
138
+ };
139
+ return (row.style?.verticalPadding ?? 14) * 2 + (row.style?.lineGap ?? 4) + height(row.title, row.style?.title) + height(row.message, row.style?.message);
140
+ }
141
+ return row.variant === 'spacer' ? row.height : row.variant === 'loading' && row.loadingStyle === 'skeleton' ? 56 : row.variant === 'loading' && row.loadingStyle === 'spinner' ? 52 : 'presentation' in row && row.presentation === 'market' ? row.variant === 'loading' ? 68 : 44 : row.variant === 'noMatch' || row.variant === 'end' ? 36 : row.variant === 'retry' ? 44 : 56;
142
+ }
143
+ export const systemRowRenderer = {
144
+ key: 'system',
145
+ appliesSizePreset: row => !['warning', 'spacer'].includes(row.variant),
146
+ create,
147
+ bind,
148
+ measure,
149
+ // Legacy Web lays out an automatic-height warning at its rendered border-box
150
+ // height (padding, both borders and wrapped text), not the estimate above.
151
+ measureRendered: (body, row) => {
152
+ if (row.variant !== 'warning' || hasExplicitRowHeight(row)) return undefined;
153
+ const height = body.offsetHeight;
154
+ return height > 0 ? height : undefined;
155
+ },
156
+ recycle: body => {
157
+ bindings.delete(body);
158
+ body.replaceChildren();
159
+ }
160
+ };
161
+ //# sourceMappingURL=SystemRowRenderer.js.map
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ import { identityRowRenderer } from "./IdentityRowRenderer.js";
4
+ import { applyRowContainerStyle, resetRowContainerStyle } from "./RowContainerStyle.js";
5
+ import { setData } from "./RowElements.js";
6
+ const membersByBody = new WeakMap();
7
+ // Members are walletSidebar identities; like the legacy engine, their preset
8
+ // height (68, +24 with badges) ignores the `size` preset adjustment.
9
+ const memberHeight = (member, width) => member.style?.container?.height ?? member.height ?? identityRowRenderer.measure(member, width);
10
+ function bind(body, row, primitives) {
11
+ const members = membersByBody.get(body);
12
+ const nextKeys = new Set([row.parent, ...row.children].map(member => member.key));
13
+ for (const [key, member] of members) {
14
+ if (!nextKeys.has(key)) {
15
+ identityRowRenderer.recycle(member.body);
16
+ member.wrapper.remove();
17
+ members.delete(key);
18
+ }
19
+ }
20
+ body.style.cssText = '';
21
+ for (const name of body.getAttributeNames()) if (name.startsWith('data-') && name !== 'data-nl-renderer') body.removeAttribute(name);
22
+ // The group's legacy 1px border is its default one-unit inset (native: a
23
+ // 1-unit padding when the parent has `height`). A style padding replaces that
24
+ // inset, so the border supplies its first unit and CSS padding the rest; the
25
+ // edge-to-content distance is then exactly the style value, as on native and
26
+ // as `measure` budgets it.
27
+ if (row.style?.horizontalPadding !== undefined) body.style.paddingInline = `${Math.max(0, row.style.horizontalPadding - 1)}px`;
28
+ if (row.style?.verticalPadding !== undefined) body.style.paddingBlock = `${Math.max(0, row.style.verticalPadding - 1)}px`;
29
+ [row.parent, ...row.children].forEach((memberRow, index) => {
30
+ let member = members.get(memberRow.key);
31
+ if (member) {
32
+ resetRowContainerStyle(member.body);
33
+ identityRowRenderer.bind(member.body, memberRow, primitives);
34
+ } else {
35
+ const wrapper = body.ownerDocument.createElement('div');
36
+ wrapper.className = 'ok-native-list-wallet-member';
37
+ const memberBody = identityRowRenderer.create(body.ownerDocument, memberRow, primitives);
38
+ wrapper.appendChild(memberBody);
39
+ member = {
40
+ wrapper,
41
+ body: memberBody
42
+ };
43
+ members.set(memberRow.key, member);
44
+ }
45
+ const {
46
+ wrapper,
47
+ body: memberBody
48
+ } = member;
49
+ setData(wrapper, 'nativeListGroupMemberKey', memberRow.key);
50
+ setData(wrapper, 'testid', memberRow.testID);
51
+ setData(wrapper, 'nativeListGroupParent', index === 0);
52
+ setData(wrapper, 'nativeListSelected', memberRow.selected);
53
+ wrapper.style.cssText = '';
54
+ wrapper.style.flexBasis = `${memberHeight(memberRow, 0)}px`;
55
+ wrapper.style.height = wrapper.style.flexBasis;
56
+ wrapper.style.opacity = String((memberRow.style?.container?.opacity ?? memberRow.opacity ?? 1) * (memberRow.disabled ? 0.5 : 1));
57
+ if (memberRow.style?.container?.cornerRadius !== undefined) wrapper.style.borderRadius = `${memberRow.style.container.cornerRadius}px`;
58
+ if (memberRow.backgroundColor) memberBody.style.backgroundColor = memberRow.backgroundColor;
59
+ applyRowContainerStyle(memberBody, memberRow);
60
+ body.appendChild(wrapper);
61
+ });
62
+ }
63
+ function create(document, row, primitives) {
64
+ const body = document.createElement('div');
65
+ body.className = 'ok-native-list-wallet-group';
66
+ body.dataset.nlRenderer = 'walletGroup';
67
+ membersByBody.set(body, new Map());
68
+ bind(body, row, primitives);
69
+ return body;
70
+ }
71
+ function recycle(body) {
72
+ const members = membersByBody.get(body);
73
+ members?.forEach(member => identityRowRenderer.recycle(member.body));
74
+ members?.clear();
75
+ body.replaceChildren();
76
+ }
77
+ export const walletGroupRowRenderer = {
78
+ key: 'walletGroup',
79
+ reorderPreview: (body, row) => {
80
+ const parent = membersByBody.get(body)?.get(row.parent.key);
81
+ return parent ? {
82
+ element: parent.body,
83
+ height: 68
84
+ } : undefined;
85
+ },
86
+ create,
87
+ bind,
88
+ recycle,
89
+ appliesSizePreset: () => false,
90
+ // Legacy group height: members, 12-unit gaps and the 1px border pair, which
91
+ // (like native's 1-unit inset) is budgeted only when the parent carries
92
+ // `height`. `style.verticalPadding` replaces that inset, as on native.
93
+ measure: (row, width) => [row.parent, ...row.children].reduce((total, member) => total + memberHeight(member, width), 0) + row.children.length * 12 + (row.style?.verticalPadding ?? (row.parent.height !== undefined ? 1 : 0)) * 2,
94
+ measureRendered: (_body, _row) => undefined
95
+ };
96
+ //# sourceMappingURL=WalletGroupRowRenderer.js.map