@hero-design/rn 8.99.4 → 8.100.0

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 (121) hide show
  1. package/.turbo/turbo-build.log +8 -3
  2. package/CHANGELOG.md +17 -0
  3. package/es/index.js +5621 -690
  4. package/jest.config.js +1 -1
  5. package/lib/index.js +5545 -613
  6. package/package.json +4 -2
  7. package/src/components/Avatar/AvatarStack/utils.ts +6 -4
  8. package/src/components/Badge/Status.tsx +1 -1
  9. package/src/components/Badge/__tests__/Status.spec.tsx +20 -0
  10. package/src/components/Badge/__tests__/__snapshots__/Status.spec.tsx.snap +2 -0
  11. package/src/components/Chart/ChartSelect/StyledChartSelect.tsx +9 -0
  12. package/src/components/Chart/ChartSelect/__tests__/StyledChartSelect.spec.tsx +15 -0
  13. package/src/components/Chart/ChartSelect/__tests__/__snapshots__/StyledChartSelect.spec.tsx.snap +20 -0
  14. package/src/components/Chart/ChartSelect/__tests__/index.spec.tsx +111 -0
  15. package/src/components/Chart/ChartSelect/index.tsx +137 -0
  16. package/src/components/Chart/ColumnChart/ColumnChartContent.tsx +84 -0
  17. package/src/components/Chart/ColumnChart/Segment.tsx +66 -0
  18. package/src/components/Chart/ColumnChart/StackedSegment.tsx +99 -0
  19. package/src/components/Chart/ColumnChart/StyledColumnChart.tsx +9 -0
  20. package/src/components/Chart/ColumnChart/__tests__/ColumnChartContent.spec.tsx +68 -0
  21. package/src/components/Chart/ColumnChart/__tests__/Segment.spec.tsx +99 -0
  22. package/src/components/Chart/ColumnChart/__tests__/StackedSegment.spec.tsx +115 -0
  23. package/src/components/Chart/ColumnChart/__tests__/__snapshots__/StackedSegment.spec.tsx.snap +120 -0
  24. package/src/components/Chart/ColumnChart/__tests__/__snapshots__/index.spec.tsx.snap +1405 -0
  25. package/src/components/Chart/ColumnChart/__tests__/index.spec.tsx +134 -0
  26. package/src/components/Chart/ColumnChart/index.tsx +216 -0
  27. package/src/components/Chart/Line/Line.tsx +81 -0
  28. package/src/components/Chart/Line/__tests__/Line.spec.tsx +148 -0
  29. package/src/components/Chart/Line/__tests__/__snapshots__/Line.spec.tsx.snap +56 -0
  30. package/src/components/Chart/Line/__tests__/__snapshots__/index.spec.tsx.snap +1461 -0
  31. package/src/components/Chart/Line/__tests__/index.spec.tsx +112 -0
  32. package/src/components/Chart/Line/index.tsx +143 -0
  33. package/src/components/Chart/StyledChart.tsx +16 -0
  34. package/src/components/Chart/index.tsx +13 -0
  35. package/src/components/Chart/shared/AxisLabel.tsx +25 -0
  36. package/src/components/Chart/shared/ChartFrame.tsx +131 -0
  37. package/src/components/Chart/shared/ChartHeader.tsx +19 -0
  38. package/src/components/Chart/shared/EmptyState.tsx +83 -0
  39. package/src/components/Chart/shared/XAxis.tsx +69 -0
  40. package/src/components/Chart/shared/XAxisGrid.tsx +42 -0
  41. package/src/components/Chart/shared/YAxis.tsx +104 -0
  42. package/src/components/Chart/shared/YAxisGrid.tsx +58 -0
  43. package/src/components/Chart/shared/__tests__/ChartFrame.spec.tsx +125 -0
  44. package/src/components/Chart/shared/__tests__/ChartHeader.spec.tsx +22 -0
  45. package/src/components/Chart/shared/__tests__/EmptyState.spec.tsx +29 -0
  46. package/src/components/Chart/shared/__tests__/XAXisGrid.spec.tsx +30 -0
  47. package/src/components/Chart/shared/__tests__/XAxis.spec.tsx +42 -0
  48. package/src/components/Chart/shared/__tests__/YAxis.spec.tsx +72 -0
  49. package/src/components/Chart/shared/__tests__/YAxisGrid.spec.tsx +35 -0
  50. package/src/components/Chart/shared/__tests__/__snapshots__/ChartFrame.spec.tsx.snap +3058 -0
  51. package/src/components/Chart/shared/__tests__/__snapshots__/ChartHeader.spec.tsx.snap +160 -0
  52. package/src/components/Chart/shared/__tests__/__snapshots__/EmptyState.spec.tsx.snap +155 -0
  53. package/src/components/Chart/shared/__tests__/__snapshots__/XAXisGrid.spec.tsx.snap +197 -0
  54. package/src/components/Chart/shared/__tests__/__snapshots__/XAxis.spec.tsx.snap +369 -0
  55. package/src/components/Chart/shared/__tests__/__snapshots__/YAxis.spec.tsx.snap +1013 -0
  56. package/src/components/Chart/shared/__tests__/__snapshots__/YAxisGrid.spec.tsx.snap +228 -0
  57. package/src/components/Chart/shared/__tests__/niceNumbers.spec.tsx +127 -0
  58. package/src/components/Chart/shared/constants.ts +2 -0
  59. package/src/components/Chart/shared/hooks/useColorScale.ts +25 -0
  60. package/src/components/Chart/shared/hooks/useGenerateTicks.ts +27 -0
  61. package/src/components/Chart/shared/hooks/useScaleBandX.ts +17 -0
  62. package/src/components/Chart/shared/hooks/useScaleLinearY.ts +30 -0
  63. package/src/components/Chart/shared/niceNumbers.ts +68 -0
  64. package/src/components/Chart/types.ts +100 -0
  65. package/src/components/Select/MultiSelect/OptionList.tsx +1 -1
  66. package/src/components/Select/MultiSelect/index.tsx +2 -6
  67. package/src/components/Select/MultiSelect/utils.ts +1 -1
  68. package/src/components/Select/SingleSelect/OptionList.tsx +1 -1
  69. package/src/components/Select/SingleSelect/index.tsx +2 -7
  70. package/src/components/Select/__tests__/helpers.spec.tsx +0 -36
  71. package/src/components/Select/helpers.tsx +0 -75
  72. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/Option.spec.tsx.snap +3 -0
  73. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/index.spec.tsx.snap +1 -0
  74. package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabs.spec.tsx.snap +3 -0
  75. package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabsHeader.spec.tsx.snap +2 -0
  76. package/src/components/Tabs/__tests__/__snapshots__/TabWithBadge.spec.tsx.snap +1 -0
  77. package/src/components/Tabs/__tests__/__snapshots__/index.spec.tsx.snap +3 -0
  78. package/src/index.ts +2 -0
  79. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +28 -0
  80. package/src/theme/components/chart.ts +28 -0
  81. package/src/theme/components/columnChart.ts +15 -0
  82. package/src/theme/getTheme.ts +6 -0
  83. package/src/types.ts +4 -0
  84. package/src/utils/__tests__/helpers.spec.ts +36 -1
  85. package/src/utils/helpers.ts +76 -1
  86. package/stats/8.100.0/rn-stats.html +4842 -0
  87. package/stats/8.99.4/rn-stats.html +1 -1
  88. package/types/components/Badge/Status.d.ts +0 -1
  89. package/types/components/Chart/ChartSelect/StyledChartSelect.d.ts +8 -0
  90. package/types/components/Chart/ChartSelect/index.d.ts +63 -0
  91. package/types/components/Chart/ColumnChart/ColumnChartContent.d.ts +25 -0
  92. package/types/components/Chart/ColumnChart/Segment.d.ts +14 -0
  93. package/types/components/Chart/ColumnChart/StackedSegment.d.ts +28 -0
  94. package/types/components/Chart/ColumnChart/StyledColumnChart.d.ts +8 -0
  95. package/types/components/Chart/ColumnChart/index.d.ts +80 -0
  96. package/types/components/Chart/Line/Line.d.ts +21 -0
  97. package/types/components/Chart/Line/index.d.ts +35 -0
  98. package/types/components/Chart/StyledChart.d.ts +9 -0
  99. package/types/components/Chart/index.d.ts +9 -0
  100. package/types/components/Chart/shared/AxisLabel.d.ts +7 -0
  101. package/types/components/Chart/shared/ChartFrame.d.ts +30 -0
  102. package/types/components/Chart/shared/ChartHeader.d.ts +8 -0
  103. package/types/components/Chart/shared/EmptyState.d.ts +8 -0
  104. package/types/components/Chart/shared/XAxis.d.ts +8 -0
  105. package/types/components/Chart/shared/XAxisGrid.d.ts +8 -0
  106. package/types/components/Chart/shared/YAxis.d.ts +10 -0
  107. package/types/components/Chart/shared/YAxisGrid.d.ts +10 -0
  108. package/types/components/Chart/shared/constants.d.ts +2 -0
  109. package/types/components/Chart/shared/hooks/useColorScale.d.ts +7 -0
  110. package/types/components/Chart/shared/hooks/useGenerateTicks.d.ts +6 -0
  111. package/types/components/Chart/shared/hooks/useScaleBandX.d.ts +8 -0
  112. package/types/components/Chart/shared/hooks/useScaleLinearY.d.ts +9 -0
  113. package/types/components/Chart/shared/niceNumbers.d.ts +12 -0
  114. package/types/components/Chart/types.d.ts +84 -0
  115. package/types/components/Select/helpers.d.ts +0 -5
  116. package/types/index.d.ts +2 -1
  117. package/types/theme/components/chart.d.ts +22 -0
  118. package/types/theme/components/columnChart.d.ts +10 -0
  119. package/types/theme/getTheme.d.ts +4 -0
  120. package/types/types.d.ts +3 -1
  121. package/types/utils/helpers.d.ts +5 -0
@@ -1,5 +1,4 @@
1
1
  import {
2
- deepCompareValue,
3
2
  getScrollParams,
4
3
  isSections,
5
4
  toFlatOptions,
@@ -73,38 +72,3 @@ describe('getScrollParams', () => {
73
72
  });
74
73
  });
75
74
  });
76
-
77
- describe('deepCompareValue', () => {
78
- it.each`
79
- a | b | expected
80
- ${1} | ${1} | ${true}
81
- ${'test'} | ${'test'} | ${true}
82
- ${true} | ${true} | ${true}
83
- ${null} | ${null} | ${true}
84
- ${undefined} | ${undefined} | ${true}
85
- ${1} | ${2} | ${false}
86
- ${'test'} | ${'other'} | ${false}
87
- ${true} | ${false} | ${false}
88
- ${null} | ${undefined} | ${false}
89
- ${NaN} | ${NaN} | ${false}
90
- ${1} | ${NaN} | ${false}
91
- ${[1, 2, 3]} | ${[1, 2, 3]} | ${true}
92
- ${['a', 'b']} | ${['a', 'b']} | ${true}
93
- ${[]} | ${[]} | ${true}
94
- ${[1, 2]} | ${[1, 2, 3]} | ${false}
95
- ${[1, 2]} | ${[2, 1]} | ${false}
96
- ${[1, [2, 3]]} | ${[1, [2, 3]]} | ${true}
97
- ${[1, [2, 3]]} | ${[1, [2, 4]]} | ${false}
98
- ${{ a: 1, b: 2 }} | ${{ a: 1, b: 2 }} | ${true}
99
- ${{}} | ${{}} | ${true}
100
- ${{ a: 1 }} | ${{ a: 2 }} | ${false}
101
- ${{ a: 1 }} | ${{ b: 1 }} | ${false}
102
- ${{ a: 1 }} | ${{ a: 1, b: 2 }} | ${false}
103
- ${{ a: { b: 1 } }} | ${{ a: { b: 1 } }} | ${true}
104
- ${{ a: { b: 1 } }} | ${{ a: { b: 2 } }} | ${false}
105
- ${1} | ${'1'} | ${false}
106
- ${[]} | ${{}} | ${false}
107
- `('should compare $a and $b correctly', ({ a, b, expected }) => {
108
- expect(deepCompareValue(a, b)).toBe(expected);
109
- });
110
- });
@@ -1,5 +1,3 @@
1
- import { useEffect, useState } from 'react';
2
- import { Keyboard } from 'react-native';
3
1
  import type { SectionData, CombinedOptionsType, OptionType } from './types';
4
2
 
5
3
  export const getKey = <V, T extends OptionType<V>>(
@@ -71,76 +69,3 @@ export const getScrollParams = <V, T extends OptionType<V>>(
71
69
  itemIndex: itemIndex < 0 ? 0 : itemIndex,
72
70
  };
73
71
  };
74
-
75
- export const useKeyboard = () => {
76
- const [isKeyboardVisible, setKeyboardVisible] = useState(false);
77
- const [keyboardHeight, setKeyboardHeight] = useState(0);
78
-
79
- useEffect(() => {
80
- const keyboardWillShowListener = Keyboard.addListener(
81
- 'keyboardWillShow',
82
- (e) => {
83
- setKeyboardVisible(true);
84
- setKeyboardHeight(e.endCoordinates.height);
85
- }
86
- );
87
- const keyboardWillHideListener = Keyboard.addListener(
88
- 'keyboardWillHide',
89
- () => {
90
- setKeyboardVisible(false);
91
- }
92
- );
93
-
94
- return () => {
95
- keyboardWillShowListener.remove();
96
- keyboardWillHideListener.remove();
97
- };
98
- }, []);
99
-
100
- return { isKeyboardVisible, keyboardHeight };
101
- };
102
-
103
- export const deepCompareValue = <V,>(a: V, b: V): boolean => {
104
- // Handle strict equality first (handles primitives, null, undefined)
105
- if (a === b) return true;
106
-
107
- // Special handling for NaN (NaN !== NaN in JS)
108
- if (
109
- typeof a === 'number' &&
110
- typeof b === 'number' &&
111
- Number.isNaN(a) &&
112
- Number.isNaN(b)
113
- ) {
114
- return false;
115
- }
116
-
117
- // If either is null or undefined (but they are not strictly equal), return false
118
- if (a == null || b == null) return false;
119
-
120
- // If types don't match, they can't be equal
121
- if (typeof a !== typeof b) return false;
122
-
123
- // Handle array comparison
124
- if (Array.isArray(a) && Array.isArray(b)) {
125
- if (a.length !== b.length) return false;
126
- return a.every((val, index) => deepCompareValue(val, b[index]));
127
- }
128
-
129
- // If one is array and the other isn't, return false
130
- if (Array.isArray(a) !== Array.isArray(b)) return false;
131
-
132
- // Handle object comparison
133
- if (typeof a === 'object' && typeof b === 'object') {
134
- const keysA = Object.keys(a) as (keyof V)[];
135
- const keysB = Object.keys(b) as (keyof V)[];
136
-
137
- if (keysA.length !== keysB.length) return false;
138
-
139
- return keysA.every(
140
- (key) => keysB.includes(key) && deepCompareValue(a[key], b[key])
141
- );
142
- }
143
-
144
- // If none of the above conditions matched, they're not equal
145
- return false;
146
- };
@@ -65,6 +65,7 @@ exports[`Option renders correctly when not selected 1`] = `
65
65
  "width": 8,
66
66
  }
67
67
  }
68
+ testID="status-dot"
68
69
  themeIntent="danger"
69
70
  />
70
71
  </View>
@@ -164,6 +165,7 @@ exports[`Option renders correctly when selected 1`] = `
164
165
  "width": 8,
165
166
  }
166
167
  }
168
+ testID="status-dot"
167
169
  themeIntent="danger"
168
170
  />
169
171
  </View>
@@ -285,6 +287,7 @@ exports[`OptionContent renders correctly when there is a badge 1`] = `
285
287
  "width": 8,
286
288
  }
287
289
  }
290
+ testID="status-dot"
288
291
  themeIntent="danger"
289
292
  />
290
293
  </View>
@@ -140,6 +140,7 @@ exports[`SelectorSwitch renders correctly 1`] = `
140
140
  "width": 8,
141
141
  }
142
142
  }
143
+ testID="status-dot"
143
144
  themeIntent="danger"
144
145
  />
145
146
  </View>
@@ -570,6 +570,7 @@ exports[`Tabs.Scroll lazy not render lazy screen: xxx 1`] = `
570
570
  "width": 8,
571
571
  }
572
572
  }
573
+ testID="status-dot"
573
574
  themeIntent="danger"
574
575
  />
575
576
  </View>
@@ -1502,6 +1503,7 @@ exports[`Tabs.Scroll renders correctly 1`] = `
1502
1503
  "width": 8,
1503
1504
  }
1504
1505
  }
1506
+ testID="status-dot"
1505
1507
  themeIntent="danger"
1506
1508
  />
1507
1509
  </View>
@@ -2434,6 +2436,7 @@ exports[`useIsFocused renders correctly 1`] = `
2434
2436
  "width": 8,
2435
2437
  }
2436
2438
  }
2439
+ testID="status-dot"
2437
2440
  themeIntent="danger"
2438
2441
  />
2439
2442
  </View>
@@ -463,6 +463,7 @@ exports[`ScrollableTabsHeader highlighted variant renders correctly 1`] = `
463
463
  "width": 8,
464
464
  }
465
465
  }
466
+ testID="status-dot"
466
467
  themeIntent="danger"
467
468
  />
468
469
  </View>
@@ -1078,6 +1079,7 @@ exports[`ScrollableTabsHeader underlined variant renders correctly 1`] = `
1078
1079
  "width": 8,
1079
1080
  }
1080
1081
  }
1082
+ testID="status-dot"
1081
1083
  themeIntent="danger"
1082
1084
  />
1083
1085
  </View>
@@ -138,6 +138,7 @@ exports[`TabWithBadge renders correctly with status badge config 1`] = `
138
138
  "width": 8,
139
139
  }
140
140
  }
141
+ testID="status-dot"
141
142
  themeIntent="danger"
142
143
  />
143
144
  </View>
@@ -350,6 +350,7 @@ exports[`Tabs renders correctly 1`] = `
350
350
  "width": 8,
351
351
  }
352
352
  }
353
+ testID="status-dot"
353
354
  themeIntent="danger"
354
355
  />
355
356
  </View>
@@ -1026,6 +1027,7 @@ exports[`useIsFocused renders correctly 1`] = `
1026
1027
  "width": 8,
1027
1028
  }
1028
1029
  }
1030
+ testID="status-dot"
1029
1031
  themeIntent="danger"
1030
1032
  />
1031
1033
  </View>
@@ -1702,6 +1704,7 @@ exports[`useIsFocused renders correctly: xxxxxx 1`] = `
1702
1704
  "width": 8,
1703
1705
  }
1704
1706
  }
1707
+ testID="status-dot"
1705
1708
  themeIntent="danger"
1706
1709
  />
1707
1710
  </View>
package/src/index.ts CHANGED
@@ -31,6 +31,7 @@ import Button from './components/Button';
31
31
  import Calendar from './components/Calendar';
32
32
  import Carousel from './components/Carousel';
33
33
  import Card from './components/Card';
34
+ import Chart from './components/Chart';
34
35
  import Chip from './components/Chip';
35
36
  import Collapse from './components/Collapse';
36
37
  import Checkbox from './components/Checkbox';
@@ -110,6 +111,7 @@ export {
110
111
  Button,
111
112
  Calendar,
112
113
  Card,
114
+ Chart,
113
115
  Carousel,
114
116
  Chip,
115
117
  Collapse,
@@ -428,6 +428,26 @@ exports[`theme returns correct theme object 1`] = `
428
428
  "pageControlWrapperHeight": 48,
429
429
  },
430
430
  },
431
+ "chart": {
432
+ "colors": {
433
+ "gridStroke": "#e8e9ea",
434
+ },
435
+ "sizes": {
436
+ "defaultWebEmptyStateHeight": 24,
437
+ "defaultWebEmptyStateWidth": 176,
438
+ "xAxisDefaultTextHeight": 32,
439
+ "yAxisDefaultTextHeight": 8,
440
+ "yAxisDefaultTextWidth": 32,
441
+ },
442
+ "space": {
443
+ "headerMarginBottom": 16,
444
+ "xAxisGridTextMarginTop": 12,
445
+ "xAxisMarginLeft": 16,
446
+ "yAxisGridMarginTop": 8,
447
+ "yAxisGridTextMarginRight": 16,
448
+ "yAxisMarginBottom": 24,
449
+ },
450
+ },
431
451
  "checkbox": {
432
452
  "borderWidths": {
433
453
  "icon": 2,
@@ -501,6 +521,14 @@ exports[`theme returns correct theme object 1`] = `
501
521
  "wrapperVerticalPadding": 8,
502
522
  },
503
523
  },
524
+ "columnChart": {
525
+ "sizes": {
526
+ "columnWidth": 16,
527
+ },
528
+ "space": {
529
+ "segmentGap": 2,
530
+ },
531
+ },
504
532
  "contentNavigator": {
505
533
  "space": {
506
534
  "valueHorizontalPadding": 8,
@@ -0,0 +1,28 @@
1
+ import type { GlobalTheme } from '../global';
2
+
3
+ const getChartTheme = (theme: GlobalTheme) => {
4
+ const space = {
5
+ xAxisMarginLeft: theme.space.medium,
6
+ xAxisGridTextMarginTop: theme.space.smallMedium,
7
+ yAxisMarginBottom: theme.space.large,
8
+ yAxisGridMarginTop: theme.space.small,
9
+ yAxisGridTextMarginRight: theme.space.medium,
10
+ headerMarginBottom: theme.space.medium,
11
+ };
12
+
13
+ const sizes = {
14
+ xAxisDefaultTextHeight: theme.sizes.xlarge,
15
+ yAxisDefaultTextHeight: theme.sizes.small,
16
+ yAxisDefaultTextWidth: theme.sizes.xlarge,
17
+ defaultWebEmptyStateWidth: theme.sizes['19xlarge'], // Only use for web doc
18
+ defaultWebEmptyStateHeight: theme.sizes.large, // Only use for web doc
19
+ };
20
+
21
+ const colors = {
22
+ gridStroke: theme.colors.secondaryOutline,
23
+ };
24
+
25
+ return { space, sizes, colors };
26
+ };
27
+
28
+ export default getChartTheme;
@@ -0,0 +1,15 @@
1
+ import type { GlobalTheme } from '../global';
2
+
3
+ const getColumnChartTheme = (theme: GlobalTheme) => {
4
+ const sizes = {
5
+ columnWidth: theme.sizes.medium,
6
+ };
7
+
8
+ const space = {
9
+ segmentGap: theme.space.xxsmall,
10
+ };
11
+
12
+ return { sizes, space };
13
+ };
14
+
15
+ export default getColumnChartTheme;
@@ -14,6 +14,8 @@ import getCarouselTheme, { CarouselThemeType } from './components/carousel';
14
14
  import getCardCarouselTheme from './components/cardCarousel';
15
15
  import getCheckboxTheme from './components/checkbox';
16
16
  import getChipTheme from './components/chip';
17
+ import getChartTheme from './components/chart';
18
+ import getColumnChartTheme from './components/columnChart';
17
19
  import getContentNavigatorTheme from './components/contentNavigator';
18
20
  import getDatePickerTheme from './components/datePicker';
19
21
  import getDividerTheme from './components/divider';
@@ -73,6 +75,8 @@ type Theme = GlobalTheme & {
73
75
  cardCarousel: ReturnType<typeof getCardCarouselTheme>;
74
76
  checkbox: ReturnType<typeof getCheckboxTheme>;
75
77
  chip: ReturnType<typeof getChipTheme>;
78
+ chart: ReturnType<typeof getChartTheme>;
79
+ columnChart: ReturnType<typeof getColumnChartTheme>;
76
80
  contentNavigator: ReturnType<typeof getContentNavigatorTheme>;
77
81
  datePicker: ReturnType<typeof getDatePickerTheme>;
78
82
  divider: ReturnType<typeof getDividerTheme>;
@@ -133,6 +137,8 @@ const getTheme = (
133
137
  card: getCardTheme(globalTheme),
134
138
  carousel: getCarouselTheme(globalTheme),
135
139
  cardCarousel: getCardCarouselTheme(globalTheme),
140
+ chart: getChartTheme(globalTheme),
141
+ columnChart: getColumnChartTheme(globalTheme),
136
142
  checkbox: getCheckboxTheme(globalTheme),
137
143
  chip: getChipTheme(globalTheme),
138
144
  contentNavigator: getContentNavigatorTheme(globalTheme),
package/src/types.ts CHANGED
@@ -20,6 +20,8 @@ import { ActionGroupHandles } from './components/FAB/ActionGroup';
20
20
  import type { SliderRangeValue } from './components/Slider/RangeSlider';
21
21
  import type { CalendarDateRange } from './components/Calendar/CalendarRange';
22
22
  import { LocaleCode, LocaleValues, DateTimeFormats } from './locales/types';
23
+ import type { ColumnChartProps } from './components/Chart/ColumnChart';
24
+ import { LineChartProps } from './components/Chart/Line';
23
25
 
24
26
  export type {
25
27
  BottomNavigationTabType,
@@ -44,4 +46,6 @@ export type {
44
46
  LocaleCode,
45
47
  LocaleValues,
46
48
  DateTimeFormats,
49
+ ColumnChartProps,
50
+ LineChartProps,
47
51
  };
@@ -1,4 +1,4 @@
1
- import { omit, pick } from '../helpers';
1
+ import { deepCompareValue, omit, pick } from '../helpers';
2
2
 
3
3
  describe('pick', () => {
4
4
  it('works', () => {
@@ -43,3 +43,38 @@ describe('omit', () => {
43
43
  });
44
44
  });
45
45
  });
46
+
47
+ describe('deepCompareValue', () => {
48
+ it.each`
49
+ a | b | expected
50
+ ${1} | ${1} | ${true}
51
+ ${'test'} | ${'test'} | ${true}
52
+ ${true} | ${true} | ${true}
53
+ ${null} | ${null} | ${true}
54
+ ${undefined} | ${undefined} | ${true}
55
+ ${1} | ${2} | ${false}
56
+ ${'test'} | ${'other'} | ${false}
57
+ ${true} | ${false} | ${false}
58
+ ${null} | ${undefined} | ${false}
59
+ ${NaN} | ${NaN} | ${false}
60
+ ${1} | ${NaN} | ${false}
61
+ ${[1, 2, 3]} | ${[1, 2, 3]} | ${true}
62
+ ${['a', 'b']} | ${['a', 'b']} | ${true}
63
+ ${[]} | ${[]} | ${true}
64
+ ${[1, 2]} | ${[1, 2, 3]} | ${false}
65
+ ${[1, 2]} | ${[2, 1]} | ${false}
66
+ ${[1, [2, 3]]} | ${[1, [2, 3]]} | ${true}
67
+ ${[1, [2, 3]]} | ${[1, [2, 4]]} | ${false}
68
+ ${{ a: 1, b: 2 }} | ${{ a: 1, b: 2 }} | ${true}
69
+ ${{}} | ${{}} | ${true}
70
+ ${{ a: 1 }} | ${{ a: 2 }} | ${false}
71
+ ${{ a: 1 }} | ${{ b: 1 }} | ${false}
72
+ ${{ a: 1 }} | ${{ a: 1, b: 2 }} | ${false}
73
+ ${{ a: { b: 1 } }} | ${{ a: { b: 1 } }} | ${true}
74
+ ${{ a: { b: 1 } }} | ${{ a: { b: 2 } }} | ${false}
75
+ ${1} | ${'1'} | ${false}
76
+ ${[]} | ${{}} | ${false}
77
+ `('should compare $a and $b correctly', ({ a, b, expected }) => {
78
+ expect(deepCompareValue(a, b)).toBe(expected);
79
+ });
80
+ });
@@ -1,4 +1,6 @@
1
- import { Platform } from 'react-native';
1
+ import { Platform, Keyboard } from 'react-native';
2
+
3
+ import { useEffect, useState } from 'react';
2
4
 
3
5
  export const isIOS = Platform.OS === 'ios';
4
6
  export const isAndroid = Platform.OS === 'android';
@@ -36,3 +38,76 @@ export function hexToRgba(hex: string, a: number) {
36
38
  const [r, g, b] = arrByte;
37
39
  return `rgba(${r},${g},${b},${a})`;
38
40
  }
41
+
42
+ export const deepCompareValue = <V>(a: V, b: V): boolean => {
43
+ // Handle strict equality first (handles primitives, null, undefined)
44
+ if (a === b) return true;
45
+
46
+ // Special handling for NaN (NaN !== NaN in JS)
47
+ if (
48
+ typeof a === 'number' &&
49
+ typeof b === 'number' &&
50
+ Number.isNaN(a) &&
51
+ Number.isNaN(b)
52
+ ) {
53
+ return false;
54
+ }
55
+
56
+ // If either is null or undefined (but they are not strictly equal), return false
57
+ if (a == null || b == null) return false;
58
+
59
+ // If types don't match, they can't be equal
60
+ if (typeof a !== typeof b) return false;
61
+
62
+ // Handle array comparison
63
+ if (Array.isArray(a) && Array.isArray(b)) {
64
+ if (a.length !== b.length) return false;
65
+ return a.every((val, index) => deepCompareValue(val, b[index]));
66
+ }
67
+
68
+ // If one is array and the other isn't, return false
69
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
70
+
71
+ // Handle object comparison
72
+ if (typeof a === 'object' && typeof b === 'object') {
73
+ const keysA = Object.keys(a) as (keyof V)[];
74
+ const keysB = Object.keys(b) as (keyof V)[];
75
+
76
+ if (keysA.length !== keysB.length) return false;
77
+
78
+ return keysA.every(
79
+ (key) => keysB.includes(key) && deepCompareValue(a[key], b[key])
80
+ );
81
+ }
82
+
83
+ // If none of the above conditions matched, they're not equal
84
+ return false;
85
+ };
86
+
87
+ export const useKeyboard = () => {
88
+ const [isKeyboardVisible, setKeyboardVisible] = useState(false);
89
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
90
+
91
+ useEffect(() => {
92
+ const keyboardWillShowListener = Keyboard.addListener(
93
+ 'keyboardWillShow',
94
+ (e) => {
95
+ setKeyboardVisible(true);
96
+ setKeyboardHeight(e.endCoordinates.height);
97
+ }
98
+ );
99
+ const keyboardWillHideListener = Keyboard.addListener(
100
+ 'keyboardWillHide',
101
+ () => {
102
+ setKeyboardVisible(false);
103
+ }
104
+ );
105
+
106
+ return () => {
107
+ keyboardWillShowListener.remove();
108
+ keyboardWillHideListener.remove();
109
+ };
110
+ }, []);
111
+
112
+ return { isKeyboardVisible, keyboardHeight };
113
+ };