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

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.
@@ -10,6 +10,7 @@ const MAX_IMAGE_HEADERS = 32;
10
10
  const MAX_HEADER_LENGTH = 4096;
11
11
  const MAX_SPACER_HEIGHT = 512;
12
12
  const MAX_SECTION_INDEX_TITLE_LENGTH = 8;
13
+ const MAX_MARKET_BADGES = 3;
13
14
  function fail(path, message) {
14
15
  throw new Error(`NativeList ${path}: ${message}`);
15
16
  }
@@ -62,6 +63,120 @@ function assertTextTone(tone, path) {
62
63
  fail(path, 'must be primary, secondary, positive, or negative');
63
64
  }
64
65
  }
66
+ function assertBoundedStyleNumber(value, path, min, max) {
67
+ if (value !== undefined && (!Number.isFinite(value) || value < min || value > max)) {
68
+ fail(path, `must be within ${min}...${max}`);
69
+ }
70
+ }
71
+ function assertMarketTextStyle(style, path) {
72
+ if (!style) return;
73
+ assertBoundedStyleNumber(style.fontSize, `${path}.fontSize`, 8, 48);
74
+ assertBoundedStyleNumber(style.lineHeight, `${path}.lineHeight`, 8, 64);
75
+ if (style.fontWeight !== undefined && !['regular', 'medium', 'semibold', 'bold'].includes(style.fontWeight)) {
76
+ fail(`${path}.fontWeight`, 'must be regular, medium, semibold, or bold');
77
+ }
78
+ if (style.alignment !== undefined && !['start', 'center', 'end'].includes(style.alignment)) {
79
+ fail(`${path}.alignment`, 'must be start, center, or end');
80
+ }
81
+ if (style.lines !== undefined && ![1, 2].includes(style.lines)) {
82
+ fail(`${path}.lines`, 'must be 1 or 2');
83
+ }
84
+ }
85
+ function assertMarketStyle(style, path) {
86
+ if (!style) return;
87
+ for (const field of ['horizontalPadding', 'verticalPadding', 'leadingGap', 'titleBadgeGap', 'trailingGap', 'contentTrailingGap', 'subtitleTrailingPadding']) {
88
+ assertBoundedStyleNumber(style[field], `${path}.${field}`, 0, 64);
89
+ }
90
+ // OneKey patch: validate the opt-in Market badge layout.
91
+ if (style.titleBadgeLayout !== undefined && style.titleBadgeLayout !== 'inline') {
92
+ fail(`${path}.titleBadgeLayout`, 'must be inline when provided');
93
+ }
94
+ assertBoundedStyleNumber(style.lineGap, `${path}.lineGap`, 0, 16);
95
+ assertBoundedStyleNumber(style.changeWidth, `${path}.changeWidth`, 1, 160);
96
+ assertBoundedStyleNumber(style.changeHeight, `${path}.changeHeight`, 1, 160);
97
+ assertBoundedStyleNumber(style.changeCornerRadius, `${path}.changeCornerRadius`, 0, 80);
98
+ if (style.image) {
99
+ assertBoundedStyleNumber(style.image.width, `${path}.image.width`, 1, 160);
100
+ assertBoundedStyleNumber(style.image.height, `${path}.image.height`, 1, 160);
101
+ assertBoundedStyleNumber(style.image.cornerRadius, `${path}.image.cornerRadius`, 0, 80);
102
+ assertVisualShape(style.image.shape, `${path}.image.shape`);
103
+ if (style.image.contentFit !== undefined && !['cover', 'contain', 'fill', 'center'].includes(style.image.contentFit)) {
104
+ fail(`${path}.image.contentFit`, 'must be cover, contain, fill, or center');
105
+ }
106
+ }
107
+ assertMarketTextStyle(style.title, `${path}.title`);
108
+ assertMarketTextStyle(style.subtitle, `${path}.subtitle`);
109
+ assertMarketTextStyle(style.price, `${path}.price`);
110
+ assertMarketTextStyle(style.change, `${path}.change`);
111
+ }
112
+ function assertMarketRow(row, path) {
113
+ if (!['token', 'stock', 'perp'].includes(row.variant)) {
114
+ fail(`${path}.variant`, 'must be token, stock, or perp');
115
+ }
116
+ assertText(row.title, `${path}.title`);
117
+ assertText(row.subtitle, `${path}.subtitle`);
118
+ // OneKey patch: validate the independently laid out Market name.
119
+ if (row.subtitlePrefix) {
120
+ assertText(row.subtitlePrefix.text, `${path}.subtitlePrefix.text`);
121
+ assertBoundedStyleNumber(row.subtitlePrefix.gap, `${path}.subtitlePrefix.gap`, 0, 64);
122
+ assertBoundedStyleNumber(row.subtitlePrefix.maxWidth, `${path}.subtitlePrefix.maxWidth`, 1, 320);
123
+ assertMarketTextStyle(row.subtitlePrefix.style, `${path}.subtitlePrefix.style`);
124
+ }
125
+ assertText(row.price, `${path}.price`);
126
+ assertText(row.change.text, `${path}.change.text`);
127
+ assertLeadingVisual(row.leading, `${path}.leading`);
128
+ const assertSegments = (segments, segmentPath) => {
129
+ segments?.forEach((segment, index) => {
130
+ assertText(segment.text, `${segmentPath}[${index}].text`);
131
+ if (segment.style !== undefined && segment.style !== 'subscript') {
132
+ fail(`${segmentPath}[${index}].style`, 'must be subscript when provided');
133
+ }
134
+ });
135
+ };
136
+ assertSegments(row.subtitleSegments, `${path}.subtitleSegments`);
137
+ assertSegments(row.priceSegments, `${path}.priceSegments`);
138
+ assertSegments(row.change.textSegments, `${path}.change.textSegments`);
139
+ if (!['positive', 'negative', 'neutral'].includes(row.change.tone)) {
140
+ fail(`${path}.change.tone`, 'must be positive, negative, or neutral');
141
+ }
142
+ if ((row.badges?.length ?? 0) > MAX_MARKET_BADGES) {
143
+ fail(`${path}.badges`, `supports at most ${MAX_MARKET_BADGES} badges`);
144
+ }
145
+ const badgeKeys = new Set();
146
+ row.badges?.forEach((badge, index) => {
147
+ const badgePath = `${path}.badges[${index}]`;
148
+ assertKey(badge.key, `${badgePath}.key`);
149
+ if (badgeKeys.has(badge.key)) {
150
+ fail(`${path}.badges`, `duplicate badge key "${badge.key}"`);
151
+ }
152
+ badgeKeys.add(badge.key);
153
+ assertText(badge.text, `${badgePath}.text`);
154
+ // OneKey patch: share typography bounds with Market text styles.
155
+ assertMarketTextStyle(badge.style, `${badgePath}.style`);
156
+ assertBoundedStyleNumber(badge.style?.height, `${badgePath}.style.height`, 1, 64);
157
+ assertBoundedStyleNumber(badge.style?.horizontalPadding, `${badgePath}.style.horizontalPadding`, 0, 32);
158
+ if (badge.iconName !== undefined && badge.iconName !== 'verified') {
159
+ fail(`${badgePath}.iconName`, 'must be verified when provided');
160
+ }
161
+ if (badge.iconName !== undefined && badge.icon !== undefined) {
162
+ fail(`${badgePath}.icon`, 'cannot be combined with iconName');
163
+ }
164
+ assertImage(badge.icon, `${badgePath}.icon`);
165
+ if (badge.tone !== undefined && !['neutral', 'info', 'success', 'warning', 'danger'].includes(badge.tone)) {
166
+ fail(`${badgePath}.tone`, 'must be neutral, info, success, warning, or danger');
167
+ }
168
+ if (!badge.text && !badge.icon && !badge.iconName) {
169
+ fail(badgePath, 'requires text, icon, or iconName');
170
+ }
171
+ if (badge.actionKey !== undefined) {
172
+ assertKey(badge.actionKey, `${badgePath}.actionKey`);
173
+ }
174
+ });
175
+ for (const [key, value] of [['pressActionKey', row.pressActionKey], ['pressInActionKey', row.pressInActionKey], ['longPressActionKey', row.longPressActionKey], ['diagnostics.imageBindActionKey', row.diagnostics?.imageBindActionKey]]) {
176
+ if (value !== undefined) assertKey(value, `${path}.${key}`);
177
+ }
178
+ assertMarketStyle(row.style, `${path}.style`);
179
+ }
65
180
  function assertSectionHeaderVariant(variant, path) {
66
181
  if (variant !== undefined && !['summary', 'gallery', 'history'].includes(variant)) {
67
182
  fail(path, 'must be summary, gallery, or history when provided');
@@ -150,7 +265,7 @@ function assertLeadingVisual(visual, path) {
150
265
  }
151
266
  }
152
267
  function assertVisual(row, path) {
153
- const visuals = row.type === 'identity' ? [row.leading] : row.type === 'rail' ? [row.visual] : row.type === 'activity' ? [row.leading, row.secondaryLeading] : row.type === 'message' ? [row.leading] : row.type === 'dataRow' ? [row.leading] : row.type === 'metricCard' ? [row.visual] : [];
268
+ const visuals = row.type === 'identity' ? [row.leading] : row.type === 'rail' ? [row.visual] : row.type === 'activity' ? [row.leading, row.secondaryLeading] : row.type === 'message' ? [row.leading] : row.type === 'dataRow' ? [row.leading] : row.type === 'market' ? [row.leading] : row.type === 'metricCard' ? [row.visual] : [];
154
269
  visuals.forEach((visual, index) => {
155
270
  assertLeadingVisual(visual, `${path}.visual[${index}]`);
156
271
  });
@@ -262,6 +377,9 @@ function assertRow(row, index, path = `rows[${index}]`) {
262
377
  fail(`${path}.badges`, `supports at most ${MAX_BADGES} badges`);
263
378
  }
264
379
  break;
380
+ case 'market':
381
+ assertMarketRow(row, path);
382
+ break;
265
383
  case 'mediaTile':
266
384
  assertImage(row.image, `${path}.image`);
267
385
  if (row.imageState !== undefined && !['empty', 'error'].includes(row.imageState)) {
@@ -327,12 +445,19 @@ function assertRow(row, index, path = `rows[${index}]`) {
327
445
  assertTrailingAccessories(row.trailing, `${path}.trailing`);
328
446
  break;
329
447
  case 'system':
448
+ const presentation = 'presentation' in row ? row.presentation : undefined;
449
+ if (presentation !== undefined && presentation !== 'market') {
450
+ fail(`${path}.presentation`, 'must be market when provided');
451
+ }
330
452
  if (
331
453
  // OneKey patch: deprecated-wallet warnings retain the original scrolling semantics.
332
454
  !['loading', 'retry', 'noMatch', 'end', 'spacer', 'warning'].includes(row.variant)) {
333
455
  fail(`${path}.variant`, 'must be loading, retry, noMatch, end, spacer, or warning');
334
456
  }
335
457
  if (row.variant === 'warning') assertText(row.title, `${path}.title`);
458
+ if (row.variant === 'loading' && row.loadingStyle !== undefined && row.loadingStyle !== 'skeleton' && row.loadingStyle !== 'spinner') {
459
+ fail(`${path}.loadingStyle`, 'must be skeleton or spinner when provided');
460
+ }
336
461
  if (row.variant !== 'spacer') {
337
462
  assertText(row.message, `${path}.message`);
338
463
  }
@@ -341,6 +466,7 @@ function assertRow(row, index, path = `rows[${index}]`) {
341
466
  }
342
467
  if (row.variant === 'retry') {
343
468
  assertKey(row.actionKey, `${path}.actionKey`);
469
+ assertText(row.actionText, `${path}.actionText`);
344
470
  }
345
471
  break;
346
472
  }
@@ -503,6 +629,24 @@ function assertPatchChanges(patch, index) {
503
629
  fail(`${path}.badges`, `supports at most ${MAX_BADGES} badges`);
504
630
  }
505
631
  break;
632
+ case 'market':
633
+ assertMarketRow({
634
+ type: 'market',
635
+ key: patch.key,
636
+ variant: 'token',
637
+ leading: {
638
+ kind: 'icon',
639
+ name: 'placeholder'
640
+ },
641
+ title: '',
642
+ price: '',
643
+ change: {
644
+ text: '',
645
+ tone: 'neutral'
646
+ },
647
+ ...patch.changes
648
+ }, path);
649
+ break;
506
650
  case 'mediaTile':
507
651
  assertImage(patch.changes.image, `${path}.image`);
508
652
  if (patch.changes.imageState !== undefined && !['empty', 'error'].includes(patch.changes.imageState)) {