@hero-design/rn 8.99.0 β†’ 8.99.2

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 (26) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/CHANGELOG.md +12 -0
  3. package/es/index.js +14 -5
  4. package/lib/index.js +14 -5
  5. package/package.json +1 -1
  6. package/src/components/Select/MultiSelect/OptionList.tsx +6 -4
  7. package/src/components/Select/MultiSelect/__tests__/OptionList.spec.tsx +45 -0
  8. package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +40 -0
  9. package/src/components/Select/MultiSelect/__tests__/utils.spec.ts +31 -0
  10. package/src/components/Select/MultiSelect/index.tsx +3 -2
  11. package/src/components/Select/MultiSelect/utils.ts +12 -0
  12. package/src/components/StatusScreens/Empty/__tests__/__snapshots__/index.spec.tsx.snap +120 -0
  13. package/src/components/StatusScreens/Empty/__tests__/index.spec.tsx +21 -1
  14. package/src/components/StatusScreens/Empty/index.tsx +1 -1
  15. package/src/components/StatusScreens/Error/__tests__/__snapshots__/index.spec.tsx.snap +134 -0
  16. package/src/components/StatusScreens/Error/__tests__/index.spec.tsx +14 -0
  17. package/src/components/StatusScreens/Error/index.tsx +1 -1
  18. package/src/components/StatusScreens/Success/__tests__/__snapshots__/index.spec.tsx.snap +134 -0
  19. package/src/components/StatusScreens/Success/__tests__/index.spec.tsx +13 -0
  20. package/src/components/StatusScreens/Success/index.tsx +1 -1
  21. package/stats/8.99.1/rn-stats.html +4842 -0
  22. package/stats/8.99.2/rn-stats.html +4842 -0
  23. package/types/components/Select/MultiSelect/utils.d.ts +2 -0
  24. package/types/components/StatusScreens/Empty/index.d.ts +1 -1
  25. package/types/components/StatusScreens/Error/index.d.ts +1 -1
  26. package/types/components/StatusScreens/Success/index.d.ts +1 -1
@@ -1,4 +1,4 @@
1
- (node:3214) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
1
+ (node:3078) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
2
2
  (Use `node --trace-warnings ...` to show where the warning was created)
3
3
  
4
4
  src/index.ts β†’ lib/index.js, es/index.js...
@@ -10,9 +10,9 @@
10
10
     ~~~~~~~~~~~~~~~~~~~
11
11
  
12
12
  (!) [plugin node-resolve] preferring built-in module 'events' over local alternative at '/home/runner/work/hero-design/hero-design/node_modules/events/events.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning.or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.
13
- created lib/index.js, es/index.js in 54.1s
13
+ created lib/index.js, es/index.js in 55.4s
14
14
  
15
15
  /home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_AU.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_CA.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/index.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/types.ts β†’ ., ....
16
16
  (!) Generated empty chunks
17
17
  "locales/types" and "locales/types"
18
- created ., . in 21.2s
18
+ created ., . in 20.7s
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @hero-design/rn
2
2
 
3
+ ## 8.99.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3811](https://github.com/Thinkei/hero-design/pull/3811) [`4a35bdd6c7cf89d87faeef60e385818df2963a62`](https://github.com/Thinkei/hero-design/commit/4a35bdd6c7cf89d87faeef60e385818df2963a62) Thanks [@vinhphan-eh](https://github.com/vinhphan-eh)! - [Select.Multi] Support display object value
8
+
9
+ ## 8.99.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#3816](https://github.com/Thinkei/hero-design/pull/3816) [`9ac2c1cabacfc6b8a5453dfe770e147484532579`](https://github.com/Thinkei/hero-design/commit/9ac2c1cabacfc6b8a5453dfe770e147484532579) Thanks [@ttkien](https://github.com/ttkien)! - [Empty][success][Error] support title with React Element
14
+
3
15
  ## 8.99.0
4
16
 
5
17
  ### Minor Changes
package/es/index.js CHANGED
@@ -19957,6 +19957,15 @@ var Option$2 = function Option(_ref) {
19957
19957
  return highlighted === true ? /*#__PURE__*/React__default.createElement(List.Item, props) : /*#__PURE__*/React__default.createElement(List.BasicItem, props);
19958
19958
  };
19959
19959
 
19960
+ var isOptionSelected = function isOptionSelected(value, option) {
19961
+ if (typeof option.value === 'string') {
19962
+ return value.includes(option.value);
19963
+ }
19964
+ return value.some(function (v) {
19965
+ return _deepCompareValue(v, option.value);
19966
+ });
19967
+ };
19968
+
19960
19969
  var _excluded$d = ["keyExtractor", "loading", "onEndReached", "onPress", "onQueryChange", "sections", "renderOption", "value", "sectionListRef"];
19961
19970
  var OptionList$1 = function OptionList(_ref) {
19962
19971
  var keyExtractor = _ref.keyExtractor,
@@ -19971,14 +19980,14 @@ var OptionList$1 = function OptionList(_ref) {
19971
19980
  rest = _objectWithoutProperties(_ref, _excluded$d);
19972
19981
  var renderItem = function renderItem(info) {
19973
19982
  var item = info.item;
19974
- var selected = value.includes(info.item.value);
19983
+ var selected = isOptionSelected(value, item);
19975
19984
  var onItemPress = function onItemPress() {
19976
- if (value.includes(info.item.value)) {
19985
+ if (isOptionSelected(value, item)) {
19977
19986
  onPress(value.filter(function (val) {
19978
- return val !== info.item.value;
19987
+ return !_deepCompareValue(val, item.value);
19979
19988
  }));
19980
19989
  } else {
19981
- onPress([].concat(_toConsumableArray(value), [info.item.value]));
19990
+ onPress([].concat(_toConsumableArray(value), [item.value]));
19982
19991
  }
19983
19992
  };
19984
19993
  return renderOption ? renderOption(_objectSpread2(_objectSpread2({}, info), {}, {
@@ -20045,7 +20054,7 @@ function MultiSelect(_ref) {
20045
20054
  var sections = toSections(options);
20046
20055
  var flatOptions = toFlatOptions(options);
20047
20056
  var displayedValue = flatOptions.filter(function (opt) {
20048
- return value.includes(opt.value);
20057
+ return isOptionSelected(value, opt);
20049
20058
  }).map(function (opt) {
20050
20059
  return opt.text;
20051
20060
  }).join(', ');
package/lib/index.js CHANGED
@@ -19986,6 +19986,15 @@ var Option$2 = function Option(_ref) {
19986
19986
  return highlighted === true ? /*#__PURE__*/React__namespace.default.createElement(List.Item, props) : /*#__PURE__*/React__namespace.default.createElement(List.BasicItem, props);
19987
19987
  };
19988
19988
 
19989
+ var isOptionSelected = function isOptionSelected(value, option) {
19990
+ if (typeof option.value === 'string') {
19991
+ return value.includes(option.value);
19992
+ }
19993
+ return value.some(function (v) {
19994
+ return _deepCompareValue(v, option.value);
19995
+ });
19996
+ };
19997
+
19989
19998
  var _excluded$d = ["keyExtractor", "loading", "onEndReached", "onPress", "onQueryChange", "sections", "renderOption", "value", "sectionListRef"];
19990
19999
  var OptionList$1 = function OptionList(_ref) {
19991
20000
  var keyExtractor = _ref.keyExtractor,
@@ -20000,14 +20009,14 @@ var OptionList$1 = function OptionList(_ref) {
20000
20009
  rest = _objectWithoutProperties(_ref, _excluded$d);
20001
20010
  var renderItem = function renderItem(info) {
20002
20011
  var item = info.item;
20003
- var selected = value.includes(info.item.value);
20012
+ var selected = isOptionSelected(value, item);
20004
20013
  var onItemPress = function onItemPress() {
20005
- if (value.includes(info.item.value)) {
20014
+ if (isOptionSelected(value, item)) {
20006
20015
  onPress(value.filter(function (val) {
20007
- return val !== info.item.value;
20016
+ return !_deepCompareValue(val, item.value);
20008
20017
  }));
20009
20018
  } else {
20010
- onPress([].concat(_toConsumableArray(value), [info.item.value]));
20019
+ onPress([].concat(_toConsumableArray(value), [item.value]));
20011
20020
  }
20012
20021
  };
20013
20022
  return renderOption ? renderOption(_objectSpread2(_objectSpread2({}, info), {}, {
@@ -20074,7 +20083,7 @@ function MultiSelect(_ref) {
20074
20083
  var sections = toSections(options);
20075
20084
  var flatOptions = toFlatOptions(options);
20076
20085
  var displayedValue = flatOptions.filter(function (opt) {
20077
- return value.includes(opt.value);
20086
+ return isOptionSelected(value, opt);
20078
20087
  }).map(function (opt) {
20079
20088
  return opt.text;
20080
20089
  }).join(', ');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn",
3
- "version": "8.99.0",
3
+ "version": "8.99.2",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -4,6 +4,8 @@ import BaseOptionList, { BaseOptionListProps } from '../BaseOptionList';
4
4
  import Option from './Option';
5
5
  import type { MultiSelectProps } from '.';
6
6
  import type { OptionType, SectionType } from '../types';
7
+ import { deepCompareValue } from '../helpers';
8
+ import { isOptionSelected } from './utils';
7
9
 
8
10
  type OptionListProps<V, T extends OptionType<V>> = Pick<
9
11
  MultiSelectProps<V, T>,
@@ -31,12 +33,12 @@ const OptionList = <V, T extends OptionType<V>>({
31
33
  }: OptionListProps<V, T>) => {
32
34
  const renderItem = (info: SectionListRenderItemInfo<T, SectionType>) => {
33
35
  const { item } = info;
34
- const selected = value.includes(info.item.value);
36
+ const selected = isOptionSelected(value, item);
35
37
  const onItemPress = () => {
36
- if (value.includes(info.item.value)) {
37
- onPress(value.filter((val) => val !== info.item.value));
38
+ if (isOptionSelected(value, item)) {
39
+ onPress(value.filter((val) => !deepCompareValue(val, item.value)));
38
40
  } else {
39
- onPress([...value, info.item.value]);
41
+ onPress([...value, item.value]);
40
42
  }
41
43
  };
42
44
 
@@ -14,6 +14,16 @@ const sections = [
14
14
  },
15
15
  ];
16
16
 
17
+ const sectionsWithObjectValue = [
18
+ { category: 'A', data: [{ text: 'A1', value: { id: 'a1' } }] },
19
+ {
20
+ category: 'B',
21
+ data: [
22
+ { text: 'B1', value: { id: 'b1' } },
23
+ { text: 'B2', value: { id: 'b2' } },
24
+ ],
25
+ },
26
+ ];
17
27
  describe('OptionList', () => {
18
28
  it('renders correctly', () => {
19
29
  const pressFn = jest.fn();
@@ -64,3 +74,38 @@ describe('OptionList', () => {
64
74
  expect(toJSON()).toMatchSnapshot();
65
75
  });
66
76
  });
77
+
78
+ describe('OptionList with object value', () => {
79
+ it('renders correctly', () => {
80
+ const pressFn = jest.fn();
81
+ const { getByText } = renderWithTheme(
82
+ <OptionList
83
+ value={[{ id: 'a1' }]}
84
+ sections={sectionsWithObjectValue}
85
+ onPress={pressFn}
86
+ keyExtractor={(opt) => opt.value.id}
87
+ />
88
+ );
89
+
90
+ expect(getByText('A1')).toBeVisible();
91
+ expect(getByText('B1')).toBeVisible();
92
+ expect(getByText('B2')).toBeVisible();
93
+ });
94
+
95
+ it('trigger onPress correctly on select value', () => {
96
+ const pressFn = jest.fn();
97
+ const { getByText } = renderWithTheme(
98
+ <OptionList
99
+ value={[{ id: 'a1' }]}
100
+ sections={sectionsWithObjectValue}
101
+ onPress={pressFn}
102
+ />
103
+ );
104
+
105
+ fireEvent.press(getByText('B1'));
106
+ expect(pressFn).toHaveBeenCalledWith([{ id: 'a1' }, { id: 'b1' }]);
107
+
108
+ fireEvent.press(getByText('A1'));
109
+ expect(pressFn).toHaveBeenCalledWith([]);
110
+ });
111
+ });
@@ -32,6 +32,11 @@ const sections = [
32
32
  },
33
33
  ];
34
34
 
35
+ const objectOptions = [
36
+ { text: 'Monday', value: { id: 'mon' } },
37
+ { text: 'Tuesday', value: { id: 'tue' } },
38
+ ];
39
+
35
40
  type CustomOptionType = {
36
41
  text: string;
37
42
  value: string;
@@ -341,6 +346,22 @@ describe('rendering', () => {
341
346
  expect(getByText('Monday')).toBeTruthy();
342
347
  expect(toJSON()).toMatchSnapshot();
343
348
  });
349
+
350
+ it('renders correctly when receives object value', () => {
351
+ const { getByText, getByTestId } = renderWithTheme(
352
+ <MultiSelect
353
+ value={[{ id: 'mon' }]}
354
+ options={objectOptions}
355
+ onConfirm={jest.fn()}
356
+ footerLabel="Confirm"
357
+ label="Allow notifications"
358
+ />
359
+ );
360
+
361
+ fireEvent.press(getByTestId('text-input'));
362
+ expect(getByText('Monday')).toBeVisible();
363
+ expect(getByText('Tuesday')).toBeVisible();
364
+ });
344
365
  });
345
366
 
346
367
  describe('behavior', () => {
@@ -379,4 +400,23 @@ describe('behavior', () => {
379
400
 
380
401
  expect(onPress).toBeCalledTimes(0);
381
402
  });
403
+
404
+ it('calls confirm with correct value when receives object value', () => {
405
+ const onPress = jest.fn();
406
+ const { getByText, getByTestId } = renderWithTheme(
407
+ <MultiSelect
408
+ value={[{ id: 'mon' }]}
409
+ options={objectOptions}
410
+ onConfirm={onPress}
411
+ footerLabel="Confirm"
412
+ label="Allow notifications"
413
+ />
414
+ );
415
+
416
+ fireEvent.press(getByTestId('text-input'));
417
+ fireEvent.press(getByText('Tuesday'));
418
+ fireEvent.press(getByText('Confirm'));
419
+
420
+ expect(onPress).toBeCalledWith([{ id: 'mon' }, { id: 'tue' }]);
421
+ });
382
422
  });
@@ -0,0 +1,31 @@
1
+ import { isOptionSelected } from '../utils';
2
+
3
+ describe('isOptionSelected', () => {
4
+ it('should return true when string value is selected', () => {
5
+ const selectedValues = ['option1', 'option2'];
6
+ const option = { value: 'option1', text: 'Option 1' };
7
+
8
+ expect(isOptionSelected(selectedValues, option)).toBe(true);
9
+ });
10
+
11
+ it('should return false when string value is not selected', () => {
12
+ const selectedValues = ['option1', 'option2'];
13
+ const option = { value: 'option3', text: 'Option 3' };
14
+
15
+ expect(isOptionSelected(selectedValues, option)).toBe(false);
16
+ });
17
+
18
+ it('should return true when object value is selected', () => {
19
+ const selectedValues = [{ id: 1 }, { id: 2 }];
20
+ const option = { value: { id: 1 }, text: 'Option 1' };
21
+
22
+ expect(isOptionSelected(selectedValues, option)).toBe(true);
23
+ });
24
+
25
+ it('should return false when object value is not selected', () => {
26
+ const selectedValues = [{ id: 1 }, { id: 2 }];
27
+ const option = { value: { id: 3 }, text: 'Option 3' };
28
+
29
+ expect(isOptionSelected(selectedValues, option)).toBe(false);
30
+ });
31
+ });
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import type {
3
- SectionList,
4
3
  TextInputProps as NativeTextInputProps,
4
+ SectionList,
5
5
  } from 'react-native';
6
6
  import { TouchableOpacity, View } from 'react-native';
7
7
  import BottomSheet from '../../BottomSheet';
@@ -17,6 +17,7 @@ import {
17
17
  import { StyledSearchBar } from '../StyledSelect';
18
18
  import type { OptionType, SectionType, SelectProps } from '../types';
19
19
  import OptionList from './OptionList';
20
+ import { isOptionSelected } from './utils';
20
21
 
21
22
  export interface MultiSelectProps<V, T extends OptionType<V> = OptionType<V>>
22
23
  extends SelectProps<V, T> {
@@ -83,7 +84,7 @@ function MultiSelect<V, T extends OptionType<V>>({
83
84
  const sections = toSections(options);
84
85
  const flatOptions = toFlatOptions(options);
85
86
  const displayedValue = flatOptions
86
- .filter((opt) => value.includes(opt.value))
87
+ .filter((opt) => isOptionSelected(value, opt))
87
88
  .map((opt) => opt.text)
88
89
  .join(', ');
89
90
  const rawValue = value.length > 0 ? value.join(', ') : '';
@@ -0,0 +1,12 @@
1
+ import { deepCompareValue } from '../helpers';
2
+ import { OptionType } from '../types';
3
+
4
+ export const isOptionSelected = <V, T extends OptionType<V>>(
5
+ value: V[],
6
+ option: T
7
+ ): boolean => {
8
+ if (typeof option.value === 'string') {
9
+ return value.includes(option.value);
10
+ }
11
+ return value.some((v) => deepCompareValue(v, option.value));
12
+ };
@@ -101,6 +101,126 @@ exports[`Empty renders empty state content correctly 1`] = `
101
101
  </View>
102
102
  `;
103
103
 
104
+ exports[`Empty renders empty state content correctly with title is a React Element 1`] = `
105
+ <View
106
+ style={
107
+ {
108
+ "flex": 1,
109
+ }
110
+ }
111
+ >
112
+ <View
113
+ style={
114
+ [
115
+ {
116
+ "alignItems": "center",
117
+ "display": "flex",
118
+ "flex": 1,
119
+ "flexDirection": "column",
120
+ "justifyContent": "center",
121
+ "padding": 16,
122
+ },
123
+ undefined,
124
+ ]
125
+ }
126
+ >
127
+ <Text
128
+ allowFontScaling={false}
129
+ style={
130
+ [
131
+ {
132
+ "color": "#001f23",
133
+ "fontFamily": "Saiga-Medium",
134
+ "fontSize": 24,
135
+ "letterSpacing": 0.24,
136
+ "lineHeight": 32,
137
+ },
138
+ [
139
+ {
140
+ "color": "#001f23",
141
+ "marginBottom": 8,
142
+ "textAlign": "center",
143
+ },
144
+ undefined,
145
+ ],
146
+ ]
147
+ }
148
+ themeIntent="body"
149
+ themeLevel="h4"
150
+ themeTypeface="playful"
151
+ themeVariant="light"
152
+ >
153
+ <Text
154
+ allowFontScaling={false}
155
+ style={
156
+ [
157
+ {
158
+ "color": "#001f23",
159
+ "fontFamily": "BeVietnamPro-Regular",
160
+ "fontSize": 42,
161
+ "letterSpacing": 0,
162
+ "lineHeight": 50,
163
+ },
164
+ undefined,
165
+ ]
166
+ }
167
+ themeIntent="body"
168
+ themeLevel="h1"
169
+ themeTypeface="neutral"
170
+ >
171
+ You have no notification at this time
172
+ </Text>
173
+ </Text>
174
+ <Text
175
+ allowFontScaling={false}
176
+ style={
177
+ [
178
+ {
179
+ "color": "#001f23",
180
+ "fontFamily": "BeVietnamPro-Regular",
181
+ "fontSize": 14,
182
+ "letterSpacing": 0.48,
183
+ "lineHeight": 22,
184
+ },
185
+ [
186
+ {
187
+ "color": "#4d6265",
188
+ "textAlign": "center",
189
+ },
190
+ undefined,
191
+ ],
192
+ ]
193
+ }
194
+ themeIntent="body"
195
+ themeTypeface="neutral"
196
+ themeVariant="small"
197
+ >
198
+ We'll notify you later.
199
+ </Text>
200
+ </View>
201
+ <View
202
+ pointerEvents="box-none"
203
+ position="bottom"
204
+ style={
205
+ [
206
+ {
207
+ "bottom": 0,
208
+ "elevation": 9999,
209
+ "flexDirection": "column-reverse",
210
+ "left": 0,
211
+ "paddingHorizontal": 24,
212
+ "paddingVertical": 16,
213
+ "position": "absolute",
214
+ "right": 0,
215
+ "top": 0,
216
+ },
217
+ undefined,
218
+ ]
219
+ }
220
+ />
221
+ </View>
222
+ `;
223
+
104
224
  exports[`Empty renders empty state with icon correctly 1`] = `
105
225
  <View
106
226
  style={
@@ -3,10 +3,11 @@ import { Image } from 'react-native';
3
3
 
4
4
  import renderWithTheme from '../../../../testHelpers/renderWithTheme';
5
5
  import Empty from '..';
6
+ import Typography from '../../../Typography';
6
7
 
7
8
  describe('Empty', () => {
8
9
  it('renders empty state content correctly', () => {
9
- const { toJSON } = renderWithTheme(
10
+ const { toJSON, getByText } = renderWithTheme(
10
11
  <Empty
11
12
  title="You have no notification at this time"
12
13
  description="We'll notify you later."
@@ -14,6 +15,25 @@ describe('Empty', () => {
14
15
  );
15
16
 
16
17
  expect(toJSON()).toMatchSnapshot();
18
+ expect(getByText('You have no notification at this time')).toBeTruthy();
19
+ expect(getByText("We'll notify you later.")).toBeTruthy();
20
+ });
21
+
22
+ it('renders empty state content correctly with title is a React Element', () => {
23
+ const { toJSON, getByText } = renderWithTheme(
24
+ <Empty
25
+ title={
26
+ <Typography.Title>
27
+ You have no notification at this time
28
+ </Typography.Title>
29
+ }
30
+ description="We'll notify you later."
31
+ />
32
+ );
33
+
34
+ expect(toJSON()).toMatchSnapshot();
35
+ expect(getByText('You have no notification at this time')).toBeTruthy();
36
+ expect(getByText("We'll notify you later.")).toBeTruthy();
17
37
  });
18
38
 
19
39
  it('renders empty state with image correctly', () => {
@@ -23,7 +23,7 @@ interface EmptyProps {
23
23
  /**
24
24
  * Empty's title.
25
25
  */
26
- title: string;
26
+ title: string | ReactElement;
27
27
  /**
28
28
  * Empty's description.
29
29
  */
@@ -904,3 +904,137 @@ exports[`Error renders title only correctly 1`] = `
904
904
  />
905
905
  </View>
906
906
  `;
907
+
908
+ exports[`Error renders title only correctly with title is a React Element 1`] = `
909
+ <View
910
+ style={
911
+ {
912
+ "flex": 1,
913
+ }
914
+ }
915
+ >
916
+ <View
917
+ style={
918
+ [
919
+ {
920
+ "backgroundColor": "#f6f6f7",
921
+ "display": "flex",
922
+ "flex": 1,
923
+ "flexDirection": "column",
924
+ },
925
+ undefined,
926
+ ]
927
+ }
928
+ themeVariant="in-page"
929
+ >
930
+ <View
931
+ style={
932
+ [
933
+ {
934
+ "alignItems": "center",
935
+ "display": "flex",
936
+ "flex": 1,
937
+ "flexDirection": "column",
938
+ "justifyContent": "center",
939
+ "padding": 24,
940
+ },
941
+ undefined,
942
+ ]
943
+ }
944
+ >
945
+ <Text
946
+ allowFontScaling={false}
947
+ style={
948
+ [
949
+ {
950
+ "color": "#001f23",
951
+ "fontFamily": "Saiga-Medium",
952
+ "fontSize": 24,
953
+ "letterSpacing": 0.24,
954
+ "lineHeight": 32,
955
+ },
956
+ [
957
+ {
958
+ "color": "#001f23",
959
+ "marginBottom": 8,
960
+ "textAlign": "center",
961
+ },
962
+ undefined,
963
+ ],
964
+ ]
965
+ }
966
+ themeIntent="body"
967
+ themeLevel="h4"
968
+ themeTypeface="playful"
969
+ >
970
+ <Text
971
+ allowFontScaling={false}
972
+ style={
973
+ [
974
+ {
975
+ "color": "#001f23",
976
+ "fontFamily": "BeVietnamPro-Regular",
977
+ "fontSize": 42,
978
+ "letterSpacing": 0,
979
+ "lineHeight": 50,
980
+ },
981
+ undefined,
982
+ ]
983
+ }
984
+ themeIntent="body"
985
+ themeLevel="h1"
986
+ themeTypeface="neutral"
987
+ >
988
+ We’re sorry, something went wrong
989
+ </Text>
990
+ </Text>
991
+ <Text
992
+ allowFontScaling={false}
993
+ style={
994
+ [
995
+ {
996
+ "color": "#001f23",
997
+ "fontFamily": "Saiga-Regular",
998
+ "fontSize": 18,
999
+ "letterSpacing": 0.54,
1000
+ "lineHeight": 26,
1001
+ },
1002
+ [
1003
+ {
1004
+ "color": "#4d6265",
1005
+ "textAlign": "center",
1006
+ },
1007
+ undefined,
1008
+ ],
1009
+ ]
1010
+ }
1011
+ themeIntent="body"
1012
+ themeTypeface="playful"
1013
+ themeVariant="regular"
1014
+ >
1015
+ Please try again later
1016
+ </Text>
1017
+ </View>
1018
+ </View>
1019
+ <View
1020
+ pointerEvents="box-none"
1021
+ position="bottom"
1022
+ style={
1023
+ [
1024
+ {
1025
+ "bottom": 0,
1026
+ "elevation": 9999,
1027
+ "flexDirection": "column-reverse",
1028
+ "left": 0,
1029
+ "paddingHorizontal": 24,
1030
+ "paddingVertical": 16,
1031
+ "position": "absolute",
1032
+ "right": 0,
1033
+ "top": 0,
1034
+ },
1035
+ undefined,
1036
+ ]
1037
+ }
1038
+ />
1039
+ </View>
1040
+ `;