@onekeyfe/react-native-native-list 3.0.157-alpha.249 → 3.0.157-alpha.251
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -5
- package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +711 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActionRenderer.kt +169 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +243 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +20 -6
- package/android/src/main/java/com/onekey/nativelist/NativeListDataRowRenderer.kt +487 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListIdentityRenderer.kt +820 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListImageSlot.kt +147 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +453 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMarketRenderer.kt +997 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMediaTileRenderer.kt +234 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMessageRenderer.kt +232 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMetricCardRenderer.kt +551 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +24 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +475 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRailRenderer.kt +143 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRegistry.kt +42 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +415 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListResolvedText.kt +163 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowHost.kt +70 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +748 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSystemRenderer.kt +464 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListTextView.kt +25 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +174 -104
- package/android/src/main/java/com/onekey/nativelist/NativeListWalletGroupRenderer.kt +407 -0
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListSelectorBackgroundColorTest.kt +34 -0
- package/docs/DESIGN.md +518 -9
- package/docs/MIGRATION_BASELINE.md +117 -0
- package/docs/ROW_TEMPLATES.md +359 -0
- package/docs/SPEC.md +358 -0
- package/docs/STYLE_SPEC.md +978 -0
- package/docs/images/list-capabilities.svg +39 -0
- package/docs/images/row-action.svg +17 -0
- package/docs/images/row-activity.svg +24 -0
- package/docs/images/row-data.svg +24 -0
- package/docs/images/row-identity.svg +25 -0
- package/docs/images/row-market.svg +23 -0
- package/docs/images/row-media-tile.svg +26 -0
- package/docs/images/row-message.svg +20 -0
- package/docs/images/row-metric-card.svg +33 -0
- package/docs/images/row-rail.svg +18 -0
- package/docs/images/row-section-header.svg +19 -0
- package/docs/images/row-style-regions.svg +30 -0
- package/docs/images/row-system.svg +30 -0
- package/docs/images/row-wallet-group.svg +26 -0
- package/ios/NativeListAccessoryStack.swift +680 -0
- package/ios/NativeListActionRenderer.swift +108 -0
- package/ios/NativeListActivityRenderer.swift +179 -0
- package/ios/NativeListDataRowRenderer.swift +444 -0
- package/ios/NativeListIdentityRenderer.swift +685 -0
- package/ios/NativeListImageSlot.swift +140 -0
- package/ios/NativeListLeadingVisual.swift +372 -0
- package/ios/NativeListMarketRenderer.swift +698 -0
- package/ios/NativeListMediaTileRenderer.swift +184 -0
- package/ios/NativeListMessageRenderer.swift +168 -0
- package/ios/NativeListMetricCardRenderer.swift +420 -0
- package/ios/NativeListModels.swift +32 -0
- package/ios/NativeListRailRenderer.swift +152 -0
- package/ios/NativeListRendererCell.swift +311 -0
- package/ios/NativeListRendererRegistry.swift +50 -0
- package/ios/NativeListResolvedText.swift +122 -0
- package/ios/NativeListRowHost.swift +63 -0
- package/ios/NativeListSectionHeaderRenderer.swift +708 -0
- package/ios/NativeListSystemRenderer.swift +568 -0
- package/ios/NativeListTextLabel.swift +42 -0
- package/ios/NativeListTextStyles.swift +236 -0
- package/ios/NativeListWalletGroupRenderer.swift +255 -0
- package/ios/RNCNativeListView.swift +111 -180
- package/lib/module/models.js +54 -0
- package/lib/module/validation.js +324 -26
- package/lib/module/web/NativeListWebEngine.js +148 -936
- package/lib/module/web/templates/ActionRowRenderer.js +97 -0
- package/lib/module/web/templates/ActivityRowRenderer.js +95 -0
- package/lib/module/web/templates/DataRowRenderer.js +145 -0
- package/lib/module/web/templates/IdentityRowRenderer.js +289 -0
- package/lib/module/web/templates/MarketRowRenderer.js +310 -0
- package/lib/module/web/templates/MediaTileRowRenderer.js +132 -0
- package/lib/module/web/templates/MessageRowRenderer.js +165 -0
- package/lib/module/web/templates/MetricCardRowRenderer.js +172 -0
- package/lib/module/web/templates/RailRowRenderer.js +98 -0
- package/lib/module/web/templates/RowContainerStyle.js +100 -0
- package/lib/module/web/templates/RowElements.js +93 -0
- package/lib/module/web/templates/RowRendererRegistry.js +70 -0
- package/lib/module/web/templates/RowText.js +121 -0
- package/lib/module/web/templates/RowVisual.js +43 -0
- package/lib/module/web/templates/SectionHeaderRowRenderer.js +146 -0
- package/lib/module/web/templates/SystemRowRenderer.js +161 -0
- package/lib/module/web/templates/WalletGroupRowRenderer.js +96 -0
- package/lib/typescript/src/models.d.ts +166 -13
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +18 -16
- package/lib/typescript/src/web/templates/ActionRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/ActivityRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/DataRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/IdentityRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/MarketRowRenderer.d.ts +30 -0
- package/lib/typescript/src/web/templates/MediaTileRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/MessageRowRenderer.d.ts +44 -0
- package/lib/typescript/src/web/templates/MetricCardRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/RailRowRenderer.d.ts +28 -0
- package/lib/typescript/src/web/templates/RowContainerStyle.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowElements.d.ts +38 -0
- package/lib/typescript/src/web/templates/RowRendererRegistry.d.ts +83 -0
- package/lib/typescript/src/web/templates/RowText.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowVisual.d.ts +20 -0
- package/lib/typescript/src/web/templates/SectionHeaderRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/SystemRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/WalletGroupRowRenderer.d.ts +20 -0
- package/package.json +3 -3
- package/src/models.ts +281 -19
- package/src/validation.ts +501 -46
- package/src/web/NativeListWebEngine.ts +361 -1932
- package/src/web/templates/ActionRowRenderer.ts +123 -0
- package/src/web/templates/ActivityRowRenderer.ts +159 -0
- package/src/web/templates/DataRowRenderer.ts +212 -0
- package/src/web/templates/IdentityRowRenderer.ts +527 -0
- package/src/web/templates/MarketRowRenderer.ts +467 -0
- package/src/web/templates/MediaTileRowRenderer.ts +182 -0
- package/src/web/templates/MessageRowRenderer.ts +306 -0
- package/src/web/templates/MetricCardRowRenderer.ts +337 -0
- package/src/web/templates/RailRowRenderer.ts +136 -0
- package/src/web/templates/RowContainerStyle.ts +131 -0
- package/src/web/templates/RowElements.ts +160 -0
- package/src/web/templates/RowRendererRegistry.ts +111 -0
- package/src/web/templates/RowText.ts +181 -0
- package/src/web/templates/RowVisual.ts +115 -0
- package/src/web/templates/SectionHeaderRowRenderer.ts +243 -0
- package/src/web/templates/SystemRowRenderer.ts +282 -0
- package/src/web/templates/WalletGroupRowRenderer.ts +131 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +0 -4538
- package/ios/NativeListCell.swift +0 -4300
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { NativeListTextStyle } from '../../models';
|
|
2
|
+
import { createElement } from './RowElements';
|
|
3
|
+
export function applyValueSegments(
|
|
4
|
+
element: HTMLElement,
|
|
5
|
+
segments:
|
|
6
|
+
| readonly Readonly<{ text: string; style?: 'subscript' }>[]
|
|
7
|
+
| undefined,
|
|
8
|
+
fontSize = 16,
|
|
9
|
+
lineHeight = 24,
|
|
10
|
+
weight = 500
|
|
11
|
+
) {
|
|
12
|
+
if (!segments?.length) return;
|
|
13
|
+
element.textContent = '';
|
|
14
|
+
element.style.fontSize = String(fontSize) + 'px';
|
|
15
|
+
element.style.lineHeight = String(lineHeight) + 'px';
|
|
16
|
+
element.style.fontWeight = String(weight);
|
|
17
|
+
segments.forEach((segment) => {
|
|
18
|
+
const span = createElement(
|
|
19
|
+
element.ownerDocument,
|
|
20
|
+
'span',
|
|
21
|
+
undefined,
|
|
22
|
+
segment.text
|
|
23
|
+
);
|
|
24
|
+
if (segment.style === 'subscript') {
|
|
25
|
+
span.dataset.nlSegment = 'subscript';
|
|
26
|
+
applySubscriptMetrics(span, fontSize);
|
|
27
|
+
}
|
|
28
|
+
element.appendChild(span);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// Legacy subscript metrics: 60% of the field size on a field-size line box.
|
|
32
|
+
function applySubscriptMetrics(span: HTMLElement, fontSize: number) {
|
|
33
|
+
span.style.fontSize = String(Math.ceil(fontSize * 0.6)) + 'px';
|
|
34
|
+
span.style.lineHeight = String(fontSize) + 'px';
|
|
35
|
+
}
|
|
36
|
+
export function applyTextLayout(
|
|
37
|
+
element: HTMLElement,
|
|
38
|
+
style: NativeListTextStyle,
|
|
39
|
+
defaultLines?: number
|
|
40
|
+
): void {
|
|
41
|
+
if (
|
|
42
|
+
style.lines === undefined &&
|
|
43
|
+
style.truncate === undefined &&
|
|
44
|
+
style.verticalAlignment === undefined &&
|
|
45
|
+
style.offsetY === undefined &&
|
|
46
|
+
defaultLines === undefined
|
|
47
|
+
)
|
|
48
|
+
return;
|
|
49
|
+
let content = element.querySelector<HTMLElement>(
|
|
50
|
+
':scope > .ok-native-list-text-content'
|
|
51
|
+
);
|
|
52
|
+
// Line clamps are only ever written inline by templates (no stylesheet rule
|
|
53
|
+
// sets them), so no computed-style read is needed; this also keeps the result
|
|
54
|
+
// identical for attached and detached rows.
|
|
55
|
+
const inheritedClamp = Number(
|
|
56
|
+
element.style.getPropertyValue('-webkit-line-clamp')
|
|
57
|
+
);
|
|
58
|
+
const lines = style.lines ?? defaultLines ?? (inheritedClamp || 1);
|
|
59
|
+
if (
|
|
60
|
+
!content &&
|
|
61
|
+
(style.verticalAlignment !== undefined ||
|
|
62
|
+
style.offsetY !== undefined ||
|
|
63
|
+
element.classList.contains('ok-native-list-market-change'))
|
|
64
|
+
) {
|
|
65
|
+
content = element.ownerDocument.createElement('span');
|
|
66
|
+
content.className = 'ok-native-list-text-content';
|
|
67
|
+
content.append(...Array.from(element.childNodes));
|
|
68
|
+
element.appendChild(content);
|
|
69
|
+
element.style.display = 'flex';
|
|
70
|
+
element.style.flexDirection = 'column';
|
|
71
|
+
element.style.removeProperty('-webkit-line-clamp');
|
|
72
|
+
element.style.removeProperty('-webkit-box-orient');
|
|
73
|
+
content.style.minWidth = '0';
|
|
74
|
+
content.style.flex = '0 1 auto';
|
|
75
|
+
content.style.width = '100%';
|
|
76
|
+
}
|
|
77
|
+
const text = content ?? element;
|
|
78
|
+
if (style.verticalAlignment !== undefined) {
|
|
79
|
+
element.style.justifyContent = {
|
|
80
|
+
top: 'flex-start',
|
|
81
|
+
center: 'center',
|
|
82
|
+
bottom: 'flex-end',
|
|
83
|
+
}[style.verticalAlignment];
|
|
84
|
+
}
|
|
85
|
+
if (style.offsetY !== undefined)
|
|
86
|
+
text.style.transform = `translateY(${style.offsetY}px)`;
|
|
87
|
+
if (
|
|
88
|
+
style.lines === undefined &&
|
|
89
|
+
style.truncate === undefined &&
|
|
90
|
+
defaultLines === undefined &&
|
|
91
|
+
!inheritedClamp
|
|
92
|
+
) {
|
|
93
|
+
if (content) {
|
|
94
|
+
// Inherit the slot's resolved wrapping/truncation from CSS or inline style.
|
|
95
|
+
content.style.whiteSpace = 'inherit';
|
|
96
|
+
content.style.textOverflow = 'inherit';
|
|
97
|
+
content.style.overflow = 'hidden';
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (lines === 1) {
|
|
102
|
+
const walker = element.ownerDocument.createTreeWalker(
|
|
103
|
+
text,
|
|
104
|
+
4 /* SHOW_TEXT */
|
|
105
|
+
);
|
|
106
|
+
let previousCarriageReturn = false;
|
|
107
|
+
while (walker.nextNode()) {
|
|
108
|
+
const value = walker.currentNode.nodeValue ?? '';
|
|
109
|
+
if (!value) continue;
|
|
110
|
+
// A CRLF pair may straddle two styled runs.
|
|
111
|
+
const textValue =
|
|
112
|
+
previousCarriageReturn && value.startsWith('\n')
|
|
113
|
+
? value.slice(1)
|
|
114
|
+
: value;
|
|
115
|
+
walker.currentNode.nodeValue = textValue.replace(/\r\n|[\r\n]/g, ' ');
|
|
116
|
+
previousCarriageReturn = value.endsWith('\r');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
text.style.whiteSpace = lines === 1 ? 'nowrap' : 'pre-wrap';
|
|
120
|
+
text.style.overflow = 'hidden';
|
|
121
|
+
text.style.textOverflow = style.truncate === 'clip' ? 'clip' : 'ellipsis';
|
|
122
|
+
text.style.removeProperty('-webkit-line-clamp');
|
|
123
|
+
text.style.removeProperty('-webkit-box-orient');
|
|
124
|
+
text.style.maxHeight = '';
|
|
125
|
+
if (lines > 1 && style.truncate !== 'clip') {
|
|
126
|
+
text.style.display = '-webkit-box';
|
|
127
|
+
text.style.setProperty('-webkit-line-clamp', String(lines));
|
|
128
|
+
text.style.setProperty('-webkit-box-orient', 'vertical');
|
|
129
|
+
} else {
|
|
130
|
+
text.style.display = 'block';
|
|
131
|
+
if (lines > 1) {
|
|
132
|
+
// Rows are styled before mounting, when computed typography is unavailable.
|
|
133
|
+
// Resolve omitted line height in CSS after the template rules take effect.
|
|
134
|
+
text.style.maxHeight =
|
|
135
|
+
style.lineHeight !== undefined
|
|
136
|
+
? `${lines * style.lineHeight}px`
|
|
137
|
+
: `${lines}lh`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export function applyTextStyleToSlot(
|
|
142
|
+
element: HTMLElement,
|
|
143
|
+
style: NativeListTextStyle,
|
|
144
|
+
defaultLines?: number
|
|
145
|
+
): void {
|
|
146
|
+
if (style.fontSize !== undefined)
|
|
147
|
+
element.style.fontSize = String(style.fontSize) + 'px';
|
|
148
|
+
if (style.lineHeight !== undefined)
|
|
149
|
+
element.style.lineHeight = String(style.lineHeight) + 'px';
|
|
150
|
+
if (style.fontWeight !== undefined)
|
|
151
|
+
element.style.fontWeight = String(fontWeight(style.fontWeight, 400));
|
|
152
|
+
if (style.color !== undefined) element.style.color = style.color;
|
|
153
|
+
// Explicit overrides also apply to rich text runs, but never to sibling badges.
|
|
154
|
+
// Subscript segments keep their legacy size relative to the field size.
|
|
155
|
+
element.querySelectorAll<HTMLElement>('span').forEach((run) => {
|
|
156
|
+
const subscript = run.dataset.nlSegment === 'subscript';
|
|
157
|
+
if (style.color !== undefined) run.style.color = style.color;
|
|
158
|
+
if (style.fontSize !== undefined) {
|
|
159
|
+
if (subscript) applySubscriptMetrics(run, style.fontSize);
|
|
160
|
+
else run.style.fontSize = String(style.fontSize) + 'px';
|
|
161
|
+
}
|
|
162
|
+
if (style.fontWeight !== undefined)
|
|
163
|
+
run.style.fontWeight = String(fontWeight(style.fontWeight, 400));
|
|
164
|
+
if (style.lineHeight !== undefined && !subscript)
|
|
165
|
+
run.style.lineHeight = String(style.lineHeight) + 'px';
|
|
166
|
+
if (style.lines !== undefined || style.truncate !== undefined)
|
|
167
|
+
run.style.whiteSpace = 'inherit';
|
|
168
|
+
});
|
|
169
|
+
if (style.alignment !== undefined) element.style.textAlign = style.alignment;
|
|
170
|
+
applyTextLayout(element, style, defaultLines);
|
|
171
|
+
}
|
|
172
|
+
export function fontWeight(
|
|
173
|
+
value: NativeListTextStyle['fontWeight'] | undefined,
|
|
174
|
+
fallback: number
|
|
175
|
+
): number {
|
|
176
|
+
if (value === 'bold') return 700;
|
|
177
|
+
if (value === 'semibold') return 600;
|
|
178
|
+
if (value === 'medium') return 500;
|
|
179
|
+
if (value === 'regular') return 400;
|
|
180
|
+
return fallback;
|
|
181
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TrailingAccessory,
|
|
3
|
+
ImageSource,
|
|
4
|
+
LeadingVisual,
|
|
5
|
+
NativeListTextStyle,
|
|
6
|
+
NativeListImageStyle,
|
|
7
|
+
} from '../../models';
|
|
8
|
+
|
|
9
|
+
export type RowPrimitives = Readonly<{
|
|
10
|
+
background: string;
|
|
11
|
+
icon: (element: HTMLElement, name: string) => void;
|
|
12
|
+
iconAction: (
|
|
13
|
+
name: string,
|
|
14
|
+
actionKey: string | undefined,
|
|
15
|
+
disabled?: boolean,
|
|
16
|
+
tintColor?: string
|
|
17
|
+
) => HTMLElement;
|
|
18
|
+
accessory: (
|
|
19
|
+
rowKey: string,
|
|
20
|
+
descriptor: TrailingAccessory,
|
|
21
|
+
slot: number
|
|
22
|
+
) => HTMLElement;
|
|
23
|
+
visual: (
|
|
24
|
+
source: LeadingVisual | undefined,
|
|
25
|
+
presentation?: string
|
|
26
|
+
) => HTMLElement | undefined;
|
|
27
|
+
thumbnail: (source: ImageSource) => HTMLElement | undefined;
|
|
28
|
+
textStyle: (
|
|
29
|
+
element: HTMLElement,
|
|
30
|
+
style: NativeListTextStyle,
|
|
31
|
+
defaultLines?: number
|
|
32
|
+
) => void;
|
|
33
|
+
dispose: (element: HTMLElement) => void;
|
|
34
|
+
}>;
|
|
35
|
+
|
|
36
|
+
const properties = [
|
|
37
|
+
'width',
|
|
38
|
+
'height',
|
|
39
|
+
'flex-basis',
|
|
40
|
+
'border-radius',
|
|
41
|
+
'overflow',
|
|
42
|
+
'object-fit',
|
|
43
|
+
'margin-inline-end',
|
|
44
|
+
'margin-bottom',
|
|
45
|
+
'align-self',
|
|
46
|
+
'border',
|
|
47
|
+
'box-sizing',
|
|
48
|
+
'clip-path',
|
|
49
|
+
'flex',
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/** Restores factory geometry without touching async loading visibility. */
|
|
53
|
+
export class RowVisualStyle {
|
|
54
|
+
private readonly defaults = new Map<HTMLElement, Map<string, string>>();
|
|
55
|
+
constructor(private readonly view: HTMLElement) {
|
|
56
|
+
[view, ...view.querySelectorAll<HTMLElement>('*')].forEach((element) => {
|
|
57
|
+
this.defaults.set(
|
|
58
|
+
element,
|
|
59
|
+
new Map(
|
|
60
|
+
properties.map((key) => [key, element.style.getPropertyValue(key)])
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
restore() {
|
|
66
|
+
this.defaults.forEach((style, element) =>
|
|
67
|
+
style.forEach((value, key) => {
|
|
68
|
+
element.style.removeProperty(key);
|
|
69
|
+
if (value) element.style.setProperty(key, value);
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
apply(
|
|
74
|
+
image: NativeListImageStyle | undefined,
|
|
75
|
+
width: number,
|
|
76
|
+
height: number,
|
|
77
|
+
margin: number
|
|
78
|
+
) {
|
|
79
|
+
this.restore();
|
|
80
|
+
const leading = this.view;
|
|
81
|
+
leading.style.width = `${width}px`;
|
|
82
|
+
leading.style.height = `${height}px`;
|
|
83
|
+
leading.style.flexBasis = `${width}px`;
|
|
84
|
+
leading.style.marginInlineEnd = `${margin}px`;
|
|
85
|
+
const radius =
|
|
86
|
+
image?.cornerRadius !== undefined
|
|
87
|
+
? `${image.cornerRadius}px`
|
|
88
|
+
: image?.shape === 'circle'
|
|
89
|
+
? '50%'
|
|
90
|
+
: image?.shape === 'square'
|
|
91
|
+
? '0px'
|
|
92
|
+
: image?.shape === 'rounded'
|
|
93
|
+
? '10px'
|
|
94
|
+
: undefined;
|
|
95
|
+
if (radius !== undefined) {
|
|
96
|
+
leading.style.setProperty('border-radius', radius, 'important');
|
|
97
|
+
leading.style.overflow = leading.matches('img') ? 'hidden' : 'visible';
|
|
98
|
+
}
|
|
99
|
+
const images = leading.matches('img')
|
|
100
|
+
? [leading]
|
|
101
|
+
: leading.querySelectorAll<HTMLElement>(
|
|
102
|
+
':scope > img:not(.ok-native-list-visual-corner), :scope > .ok-native-list-visual-fallback:not(.ok-native-list-visual-corner)'
|
|
103
|
+
);
|
|
104
|
+
images.forEach((bitmap) => {
|
|
105
|
+
if (bitmap !== leading) {
|
|
106
|
+
if (image?.width !== undefined) bitmap.style.width = '100%';
|
|
107
|
+
if (image?.height !== undefined) bitmap.style.height = '100%';
|
|
108
|
+
}
|
|
109
|
+
if (radius !== undefined) bitmap.style.borderRadius = radius;
|
|
110
|
+
if (image?.contentFit)
|
|
111
|
+
bitmap.style.objectFit =
|
|
112
|
+
image.contentFit === 'center' ? 'none' : image.contentFit;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { applyTabularNumbers, hasExplicitRowHeight } from './RowElements';
|
|
2
|
+
import type { SectionHeaderRow } from '../../models';
|
|
3
|
+
import {
|
|
4
|
+
createElement,
|
|
5
|
+
setData,
|
|
6
|
+
tagSlot,
|
|
7
|
+
markActionAnchorSource,
|
|
8
|
+
createTextColumn,
|
|
9
|
+
} from './RowElements';
|
|
10
|
+
import { applyValueSegments } from './RowText';
|
|
11
|
+
import type { RowPrimitives } from './RowVisual';
|
|
12
|
+
function createSectionHeader(
|
|
13
|
+
document: Document,
|
|
14
|
+
primitives: RowPrimitives,
|
|
15
|
+
row: SectionHeaderRow
|
|
16
|
+
): HTMLElement {
|
|
17
|
+
const body = createElement(
|
|
18
|
+
document,
|
|
19
|
+
'div',
|
|
20
|
+
'ok-native-list-row ok-native-list-section'
|
|
21
|
+
);
|
|
22
|
+
setData(body, 'variant', row.variant);
|
|
23
|
+
if (row.titleIcon) {
|
|
24
|
+
const titleIcon = primitives.iconAction(
|
|
25
|
+
row.titleIcon.name,
|
|
26
|
+
row.titleIcon.actionKey,
|
|
27
|
+
row.titleIcon.disabled,
|
|
28
|
+
row.titleIcon.tintColor
|
|
29
|
+
);
|
|
30
|
+
markActionAnchorSource(titleIcon, 'leadingAction');
|
|
31
|
+
body.appendChild(titleIcon);
|
|
32
|
+
}
|
|
33
|
+
// OneKey patch: section title help has its own measurable action target.
|
|
34
|
+
// body.appendChild(createTextColumn(document, row.title, row.subtitle));
|
|
35
|
+
const column = createTextColumn(document, row.title, row.subtitle);
|
|
36
|
+
const title = column.firstElementChild as HTMLElement;
|
|
37
|
+
title.classList.add('ok-native-list-section-title');
|
|
38
|
+
if (row.titleActionKey) {
|
|
39
|
+
setData(title, 'nativeListAction', row.titleActionKey);
|
|
40
|
+
markActionAnchorSource(title, 'leadingAction');
|
|
41
|
+
title.setAttribute('role', 'button');
|
|
42
|
+
title.tabIndex = 0;
|
|
43
|
+
title.style.alignSelf = 'flex-start';
|
|
44
|
+
title.style.maxWidth = '100%';
|
|
45
|
+
// OneKey patch: explicit network headers reserve a separate 3-point underline area.
|
|
46
|
+
if (row.presentation !== 'networkSelector' || !hasExplicitRowHeight(row)) {
|
|
47
|
+
title.style.textDecoration = 'underline dotted';
|
|
48
|
+
title.style.textUnderlineOffset = '6px';
|
|
49
|
+
}
|
|
50
|
+
if (row.titleActionOnHover) setData(title, 'nativeListHoverAction', true);
|
|
51
|
+
}
|
|
52
|
+
if (row.presentation === 'networkSelector' && hasExplicitRowHeight(row)) {
|
|
53
|
+
body.style.padding =
|
|
54
|
+
row.variant === 'summary' ? '24px 12px 20px' : '0 12px';
|
|
55
|
+
body.style.backgroundColor = 'var(--nl-bg)';
|
|
56
|
+
body.style.gap = row.checkbox ? '12px' : '8px';
|
|
57
|
+
title.style.fontSize = row.variant === 'summary' ? '16px' : '14px';
|
|
58
|
+
title.style.lineHeight = row.variant === 'summary' ? '24px' : '20px';
|
|
59
|
+
title.style.fontWeight =
|
|
60
|
+
row.variant === 'summary' || (row.titleActionKey && !row.checkbox)
|
|
61
|
+
? '500'
|
|
62
|
+
: '600';
|
|
63
|
+
if (row.titleActionKey) {
|
|
64
|
+
const text = createElement(
|
|
65
|
+
document,
|
|
66
|
+
'span',
|
|
67
|
+
'ok-native-list-section-title-text',
|
|
68
|
+
row.title
|
|
69
|
+
);
|
|
70
|
+
text.style.overflow = 'hidden';
|
|
71
|
+
text.style.textOverflow = 'ellipsis';
|
|
72
|
+
text.style.maxWidth = '100%';
|
|
73
|
+
const dotted = document.createElementNS(
|
|
74
|
+
'http://www.w3.org/2000/svg',
|
|
75
|
+
'svg'
|
|
76
|
+
);
|
|
77
|
+
dotted.setAttribute('height', '2');
|
|
78
|
+
dotted.style.cssText =
|
|
79
|
+
'display:block;position:absolute;left:0;bottom:0;width:100%;height:2px;color:var(--nl-secondary)';
|
|
80
|
+
const line = document.createElementNS(
|
|
81
|
+
'http://www.w3.org/2000/svg',
|
|
82
|
+
'line'
|
|
83
|
+
);
|
|
84
|
+
for (const [key, value] of Object.entries({
|
|
85
|
+
x1: '1',
|
|
86
|
+
y1: '1',
|
|
87
|
+
x2: '100%',
|
|
88
|
+
y2: '1',
|
|
89
|
+
stroke: 'currentColor',
|
|
90
|
+
'stroke-width': '1.5',
|
|
91
|
+
'stroke-dasharray': '0,4',
|
|
92
|
+
'stroke-linecap': 'round',
|
|
93
|
+
}))
|
|
94
|
+
line.setAttribute(key, value);
|
|
95
|
+
// OneKey patch: keep both round caps inside the original full-width viewport.
|
|
96
|
+
const lineViewport = document.createElementNS(
|
|
97
|
+
'http://www.w3.org/2000/svg',
|
|
98
|
+
'svg'
|
|
99
|
+
);
|
|
100
|
+
lineViewport.setAttribute('width', 'calc(100% - 1px)');
|
|
101
|
+
lineViewport.setAttribute('height', '2');
|
|
102
|
+
lineViewport.setAttribute('overflow', 'visible');
|
|
103
|
+
lineViewport.appendChild(line);
|
|
104
|
+
dotted.appendChild(lineViewport);
|
|
105
|
+
// OneKey patch: SVG intrinsic width must not expand the title action beyond its text.
|
|
106
|
+
title.style.display = 'block';
|
|
107
|
+
title.style.position = 'relative';
|
|
108
|
+
title.style.width = 'fit-content';
|
|
109
|
+
title.style.paddingBottom = '3px';
|
|
110
|
+
text.style.display = 'block';
|
|
111
|
+
title.replaceChildren(text, dotted);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
body.appendChild(column);
|
|
115
|
+
if (row.value) {
|
|
116
|
+
const value = tagSlot(
|
|
117
|
+
createElement(
|
|
118
|
+
document,
|
|
119
|
+
row.valueActionKey ? 'button' : 'span',
|
|
120
|
+
row.valueActionKey
|
|
121
|
+
? 'ok-native-list-action-button ok-native-list-section-value'
|
|
122
|
+
: 'ok-native-list-value ok-native-list-section-value',
|
|
123
|
+
row.value
|
|
124
|
+
),
|
|
125
|
+
'value'
|
|
126
|
+
);
|
|
127
|
+
applyValueSegments(value, row.valueSegments);
|
|
128
|
+
if (row.presentation === 'networkSelector' && hasExplicitRowHeight(row)) {
|
|
129
|
+
value.style.fontFamily = 'inherit';
|
|
130
|
+
value.style.fontSize = '16px';
|
|
131
|
+
value.style.lineHeight = '24px';
|
|
132
|
+
value.style.fontWeight = '500';
|
|
133
|
+
if (row.valueActionKey) {
|
|
134
|
+
value.style.color = 'var(--nl-secondary)';
|
|
135
|
+
value.style.padding = '0';
|
|
136
|
+
value.style.flexShrink = '0';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (row.valueActionTestID) setData(value, 'testid', row.valueActionTestID);
|
|
140
|
+
if (row.valueActionKey) {
|
|
141
|
+
value.setAttribute('type', 'button');
|
|
142
|
+
setData(value, 'nativeListAction', row.valueActionKey);
|
|
143
|
+
markActionAnchorSource(value, 'trailingAccessory', 0);
|
|
144
|
+
}
|
|
145
|
+
body.appendChild(value);
|
|
146
|
+
}
|
|
147
|
+
if (row.valueIcon) {
|
|
148
|
+
const valueIcon = primitives.iconAction(
|
|
149
|
+
row.valueIcon.name,
|
|
150
|
+
row.valueIcon.actionKey,
|
|
151
|
+
row.valueIcon.disabled,
|
|
152
|
+
row.valueIcon.tintColor
|
|
153
|
+
);
|
|
154
|
+
markActionAnchorSource(valueIcon, 'trailingAccessory', 1);
|
|
155
|
+
body.appendChild(valueIcon);
|
|
156
|
+
}
|
|
157
|
+
if (row.checkbox)
|
|
158
|
+
body.appendChild(primitives.accessory(row.key, row.checkbox, 0));
|
|
159
|
+
return body;
|
|
160
|
+
}
|
|
161
|
+
function bind(
|
|
162
|
+
body: HTMLElement,
|
|
163
|
+
row: SectionHeaderRow,
|
|
164
|
+
primitives: RowPrimitives
|
|
165
|
+
) {
|
|
166
|
+
const next = createSectionHeader(body.ownerDocument, primitives, row);
|
|
167
|
+
body.replaceChildren(...Array.from(next.childNodes));
|
|
168
|
+
body.className = next.className;
|
|
169
|
+
body.style.cssText = next.style.cssText;
|
|
170
|
+
if (row.presentation === 'networkSelector') applyTabularNumbers(body);
|
|
171
|
+
body.dataset.variant = row.variant ?? '';
|
|
172
|
+
body.removeAttribute('data-nl-container-background');
|
|
173
|
+
body.removeAttribute('data-nl-container-border');
|
|
174
|
+
const style = row.style;
|
|
175
|
+
if (!style) return;
|
|
176
|
+
if (style.horizontalPadding !== undefined)
|
|
177
|
+
body.style.paddingInline = style.horizontalPadding + 'px';
|
|
178
|
+
if (style.verticalPadding !== undefined)
|
|
179
|
+
body.style.paddingBlock = style.verticalPadding + 'px';
|
|
180
|
+
if (style.lineGap !== undefined)
|
|
181
|
+
body
|
|
182
|
+
.querySelectorAll<HTMLElement>(':scope > .ok-native-list-flex')
|
|
183
|
+
.forEach((column) => {
|
|
184
|
+
column.style.rowGap = style.lineGap + 'px';
|
|
185
|
+
});
|
|
186
|
+
if (style.trailingGap !== undefined) {
|
|
187
|
+
const children = Array.from(body.children) as HTMLElement[];
|
|
188
|
+
const column = children.findIndex((child) =>
|
|
189
|
+
child.classList.contains('ok-native-list-flex')
|
|
190
|
+
);
|
|
191
|
+
children.slice(column + 2).forEach((child) => {
|
|
192
|
+
child.style.marginInlineStart =
|
|
193
|
+
'calc(' +
|
|
194
|
+
style.trailingGap +
|
|
195
|
+
'px - ' +
|
|
196
|
+
(body.style.gap || '12px') +
|
|
197
|
+
')';
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
for (const slot of ['title', 'subtitle', 'value'] as const)
|
|
201
|
+
if (style[slot])
|
|
202
|
+
body
|
|
203
|
+
.querySelectorAll<HTMLElement>('[data-nl-slot="' + slot + '"]')
|
|
204
|
+
.forEach((node) => primitives.textStyle(node, style[slot]!));
|
|
205
|
+
}
|
|
206
|
+
function create(
|
|
207
|
+
document: Document,
|
|
208
|
+
row: SectionHeaderRow,
|
|
209
|
+
primitives: RowPrimitives
|
|
210
|
+
) {
|
|
211
|
+
const body = document.createElement('div');
|
|
212
|
+
body.dataset.nlRenderer = 'sectionHeader';
|
|
213
|
+
bind(body, row, primitives);
|
|
214
|
+
return body;
|
|
215
|
+
}
|
|
216
|
+
export const sectionHeaderRowRenderer = {
|
|
217
|
+
key: 'sectionHeader' as const,
|
|
218
|
+
create,
|
|
219
|
+
bind,
|
|
220
|
+
recycle: (body: HTMLElement) => body.replaceChildren(),
|
|
221
|
+
appliesSizePreset: (row: SectionHeaderRow) =>
|
|
222
|
+
!['summary', 'gallery'].includes(row.variant ?? ''),
|
|
223
|
+
measure: (row: SectionHeaderRow, _width: number, layout = 'linear') =>
|
|
224
|
+
layout === 'table'
|
|
225
|
+
? 28
|
|
226
|
+
: row.presentation === 'networkSelector'
|
|
227
|
+
? 47
|
|
228
|
+
: row.variant === 'history'
|
|
229
|
+
? 16
|
|
230
|
+
: row.variant === 'summary'
|
|
231
|
+
? 68
|
|
232
|
+
: row.variant === 'gallery'
|
|
233
|
+
? 32
|
|
234
|
+
: row.checkbox
|
|
235
|
+
? 56
|
|
236
|
+
: layout === 'linear'
|
|
237
|
+
? 30
|
|
238
|
+
: 36,
|
|
239
|
+
measureRendered: (
|
|
240
|
+
_body: HTMLElement,
|
|
241
|
+
_row: SectionHeaderRow
|
|
242
|
+
): number | undefined => undefined,
|
|
243
|
+
};
|