@hero-design/rn 8.64.0 → 8.64.1

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.
@@ -2,4 +2,4 @@
2
2
  src/index.ts → lib/index.js, es/index.js...
3
3
  (!) Plugin replace: @rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`.
4
4
  (!) 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
5
- created lib/index.js, es/index.js in 1m 0.7s
5
+ created lib/index.js, es/index.js in 1m 4.4s
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @hero-design/rn
2
2
 
3
+ ## 8.64.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3246](https://github.com/Thinkei/hero-design/pull/3246) [`1dbb5e198`](https://github.com/Thinkei/hero-design/commit/1dbb5e1985e4b316ca08cd39c10d4d0779aaa43d) Thanks [@vinhphan-eh](https://github.com/vinhphan-eh)! - [Tabs] Fix onTabPress being called on render
8
+
3
9
  ## 8.64.0
4
10
 
5
11
  ### Minor Changes
package/es/index.js CHANGED
@@ -17871,6 +17871,20 @@ var ScrollableTabHeader = function ScrollableTabHeader(_ref2) {
17871
17871
  }));
17872
17872
  };
17873
17873
 
17874
+ var useHandlePageScroll = function useHandlePageScroll() {
17875
+ // Used as a flag to prevent calling onTabPress on initial render
17876
+ var hasScrolled = useRef(false);
17877
+ var onPageScrollStateChanged = useCallback(function (e) {
17878
+ if (!hasScrolled.current && e.nativeEvent.pageScrollState === 'dragging') {
17879
+ hasScrolled.current = true;
17880
+ }
17881
+ }, []);
17882
+ return {
17883
+ onPageScrollStateChanged: onPageScrollStateChanged,
17884
+ hasScrolled: hasScrolled
17885
+ };
17886
+ };
17887
+
17874
17888
  var TabContext = /*#__PURE__*/React__default.createContext(null);
17875
17889
  var ScreenContext = /*#__PURE__*/React__default.createContext(null);
17876
17890
  var useIsFocused = function useIsFocused() {
@@ -17898,14 +17912,15 @@ var ScrollableTab = function ScrollableTab(_ref) {
17898
17912
  componentTestID = _ref.testID,
17899
17913
  _ref$variant = _ref.variant,
17900
17914
  variant = _ref$variant === void 0 ? 'highlighted' : _ref$variant;
17901
- var pagerViewRef = React__default.useRef(null);
17915
+ var pagerViewRef = useRef(null);
17902
17916
  var insets = useSafeAreaInsets();
17903
17917
  var selectedTabIndex = tabs.findIndex(function (item) {
17904
17918
  return item.key === selectedTabKey;
17905
17919
  });
17906
- // Used as a flag to prevent calling onTabPress on initial render
17907
- var hasScrolled = useRef(false);
17908
- React__default.useEffect(function () {
17920
+ var _useHandlePageScroll = useHandlePageScroll(),
17921
+ hasScrolled = _useHandlePageScroll.hasScrolled,
17922
+ onPageScrollStateChanged = _useHandlePageScroll.onPageScrollStateChanged;
17923
+ useEffect(function () {
17909
17924
  var timeoutHandle;
17910
17925
  if (selectedTabIndex !== -1) {
17911
17926
  // If the selected tab is changed too quickly, the setPage is crashed and not work anymore
@@ -17922,7 +17937,7 @@ var ScrollableTab = function ScrollableTab(_ref) {
17922
17937
  }
17923
17938
  };
17924
17939
  }, [selectedTabIndex, pagerViewRef]);
17925
- var tabContextProviderValue = React__default.useMemo(function () {
17940
+ var tabContextProviderValue = useMemo(function () {
17926
17941
  return {
17927
17942
  selectedTabKey: selectedTabKey
17928
17943
  };
@@ -17944,11 +17959,7 @@ var ScrollableTab = function ScrollableTab(_ref) {
17944
17959
  useNext: true,
17945
17960
  initialPage: selectedTabIndex,
17946
17961
  ref: pagerViewRef,
17947
- onPageScrollStateChanged: function onPageScrollStateChanged(e) {
17948
- if (!hasScrolled.current && e.nativeEvent.pageScrollState === 'dragging') {
17949
- hasScrolled.current = true;
17950
- }
17951
- },
17962
+ onPageScrollStateChanged: onPageScrollStateChanged,
17952
17963
  onPageSelected: function onPageSelected(e) {
17953
17964
  var index = e.nativeEvent.position;
17954
17965
  var selectedItem = tabs[index];
@@ -18012,23 +18023,26 @@ var Tabs = function Tabs(_ref2) {
18012
18023
  componentTestID = _ref2.testID;
18013
18024
  var theme = useTheme$1();
18014
18025
  var insets = useSafeAreaInsets();
18015
- var pagerViewRef = React__default.useRef(null);
18026
+ var pagerViewRef = useRef(null);
18016
18027
  var selectedTabIndex = tabs.findIndex(function (item) {
18017
18028
  return item.key === selectedTabKey;
18018
18029
  });
18019
- var scrollOffsetAnimatedValue = React__default.useRef(new Animated.Value(0)).current;
18020
- var positionAnimatedValue = React__default.useRef(new Animated.Value(0)).current;
18021
- var _React$useState = React__default.useState(0),
18022
- _React$useState2 = _slicedToArray(_React$useState, 2),
18023
- tabsWidth = _React$useState2[0],
18024
- setTabsWidth = _React$useState2[1];
18030
+ var scrollOffsetAnimatedValue = useRef(new Animated.Value(0)).current;
18031
+ var positionAnimatedValue = useRef(new Animated.Value(0)).current;
18032
+ var _useState = useState(0),
18033
+ _useState2 = _slicedToArray(_useState, 2),
18034
+ tabsWidth = _useState2[0],
18035
+ setTabsWidth = _useState2[1];
18036
+ var _useHandlePageScroll = useHandlePageScroll(),
18037
+ onPageScrollStateChanged = _useHandlePageScroll.onPageScrollStateChanged,
18038
+ hasScrolled = _useHandlePageScroll.hasScrolled;
18025
18039
  useEffect(function () {
18026
18040
  if (selectedTabIndex !== -1) {
18027
18041
  var _pagerViewRef$current;
18028
18042
  (_pagerViewRef$current = pagerViewRef.current) === null || _pagerViewRef$current === void 0 || _pagerViewRef$current.setPage(selectedTabIndex);
18029
18043
  }
18030
18044
  }, [selectedTabIndex]);
18031
- var tabContextProviderValue = React__default.useMemo(function () {
18045
+ var tabContextProviderValue = useMemo(function () {
18032
18046
  return {
18033
18047
  selectedTabKey: selectedTabKey
18034
18048
  };
@@ -18084,10 +18098,11 @@ var Tabs = function Tabs(_ref2) {
18084
18098
  onPageSelected: function onPageSelected(e) {
18085
18099
  var index = e.nativeEvent.position;
18086
18100
  var selectedItem = tabs[index];
18087
- if (selectedItem) {
18101
+ if (hasScrolled.current && selectedItem) {
18088
18102
  onTabPress(selectedItem.key);
18089
18103
  }
18090
18104
  },
18105
+ onPageScrollStateChanged: onPageScrollStateChanged,
18091
18106
  onPageScroll: Animated.event([{
18092
18107
  nativeEvent: {
18093
18108
  offset: scrollOffsetAnimatedValue,
package/lib/index.js CHANGED
@@ -17901,6 +17901,20 @@ var ScrollableTabHeader = function ScrollableTabHeader(_ref2) {
17901
17901
  }));
17902
17902
  };
17903
17903
 
17904
+ var useHandlePageScroll = function useHandlePageScroll() {
17905
+ // Used as a flag to prevent calling onTabPress on initial render
17906
+ var hasScrolled = React.useRef(false);
17907
+ var onPageScrollStateChanged = React.useCallback(function (e) {
17908
+ if (!hasScrolled.current && e.nativeEvent.pageScrollState === 'dragging') {
17909
+ hasScrolled.current = true;
17910
+ }
17911
+ }, []);
17912
+ return {
17913
+ onPageScrollStateChanged: onPageScrollStateChanged,
17914
+ hasScrolled: hasScrolled
17915
+ };
17916
+ };
17917
+
17904
17918
  var TabContext = /*#__PURE__*/React__default["default"].createContext(null);
17905
17919
  var ScreenContext = /*#__PURE__*/React__default["default"].createContext(null);
17906
17920
  var useIsFocused = function useIsFocused() {
@@ -17928,14 +17942,15 @@ var ScrollableTab = function ScrollableTab(_ref) {
17928
17942
  componentTestID = _ref.testID,
17929
17943
  _ref$variant = _ref.variant,
17930
17944
  variant = _ref$variant === void 0 ? 'highlighted' : _ref$variant;
17931
- var pagerViewRef = React__default["default"].useRef(null);
17945
+ var pagerViewRef = React.useRef(null);
17932
17946
  var insets = reactNativeSafeAreaContext.useSafeAreaInsets();
17933
17947
  var selectedTabIndex = tabs.findIndex(function (item) {
17934
17948
  return item.key === selectedTabKey;
17935
17949
  });
17936
- // Used as a flag to prevent calling onTabPress on initial render
17937
- var hasScrolled = React.useRef(false);
17938
- React__default["default"].useEffect(function () {
17950
+ var _useHandlePageScroll = useHandlePageScroll(),
17951
+ hasScrolled = _useHandlePageScroll.hasScrolled,
17952
+ onPageScrollStateChanged = _useHandlePageScroll.onPageScrollStateChanged;
17953
+ React.useEffect(function () {
17939
17954
  var timeoutHandle;
17940
17955
  if (selectedTabIndex !== -1) {
17941
17956
  // If the selected tab is changed too quickly, the setPage is crashed and not work anymore
@@ -17952,7 +17967,7 @@ var ScrollableTab = function ScrollableTab(_ref) {
17952
17967
  }
17953
17968
  };
17954
17969
  }, [selectedTabIndex, pagerViewRef]);
17955
- var tabContextProviderValue = React__default["default"].useMemo(function () {
17970
+ var tabContextProviderValue = React.useMemo(function () {
17956
17971
  return {
17957
17972
  selectedTabKey: selectedTabKey
17958
17973
  };
@@ -17974,11 +17989,7 @@ var ScrollableTab = function ScrollableTab(_ref) {
17974
17989
  useNext: true,
17975
17990
  initialPage: selectedTabIndex,
17976
17991
  ref: pagerViewRef,
17977
- onPageScrollStateChanged: function onPageScrollStateChanged(e) {
17978
- if (!hasScrolled.current && e.nativeEvent.pageScrollState === 'dragging') {
17979
- hasScrolled.current = true;
17980
- }
17981
- },
17992
+ onPageScrollStateChanged: onPageScrollStateChanged,
17982
17993
  onPageSelected: function onPageSelected(e) {
17983
17994
  var index = e.nativeEvent.position;
17984
17995
  var selectedItem = tabs[index];
@@ -18042,23 +18053,26 @@ var Tabs = function Tabs(_ref2) {
18042
18053
  componentTestID = _ref2.testID;
18043
18054
  var theme = useTheme$1();
18044
18055
  var insets = reactNativeSafeAreaContext.useSafeAreaInsets();
18045
- var pagerViewRef = React__default["default"].useRef(null);
18056
+ var pagerViewRef = React.useRef(null);
18046
18057
  var selectedTabIndex = tabs.findIndex(function (item) {
18047
18058
  return item.key === selectedTabKey;
18048
18059
  });
18049
- var scrollOffsetAnimatedValue = React__default["default"].useRef(new reactNative.Animated.Value(0)).current;
18050
- var positionAnimatedValue = React__default["default"].useRef(new reactNative.Animated.Value(0)).current;
18051
- var _React$useState = React__default["default"].useState(0),
18052
- _React$useState2 = _slicedToArray(_React$useState, 2),
18053
- tabsWidth = _React$useState2[0],
18054
- setTabsWidth = _React$useState2[1];
18060
+ var scrollOffsetAnimatedValue = React.useRef(new reactNative.Animated.Value(0)).current;
18061
+ var positionAnimatedValue = React.useRef(new reactNative.Animated.Value(0)).current;
18062
+ var _useState = React.useState(0),
18063
+ _useState2 = _slicedToArray(_useState, 2),
18064
+ tabsWidth = _useState2[0],
18065
+ setTabsWidth = _useState2[1];
18066
+ var _useHandlePageScroll = useHandlePageScroll(),
18067
+ onPageScrollStateChanged = _useHandlePageScroll.onPageScrollStateChanged,
18068
+ hasScrolled = _useHandlePageScroll.hasScrolled;
18055
18069
  React.useEffect(function () {
18056
18070
  if (selectedTabIndex !== -1) {
18057
18071
  var _pagerViewRef$current;
18058
18072
  (_pagerViewRef$current = pagerViewRef.current) === null || _pagerViewRef$current === void 0 || _pagerViewRef$current.setPage(selectedTabIndex);
18059
18073
  }
18060
18074
  }, [selectedTabIndex]);
18061
- var tabContextProviderValue = React__default["default"].useMemo(function () {
18075
+ var tabContextProviderValue = React.useMemo(function () {
18062
18076
  return {
18063
18077
  selectedTabKey: selectedTabKey
18064
18078
  };
@@ -18114,10 +18128,11 @@ var Tabs = function Tabs(_ref2) {
18114
18128
  onPageSelected: function onPageSelected(e) {
18115
18129
  var index = e.nativeEvent.position;
18116
18130
  var selectedItem = tabs[index];
18117
- if (selectedItem) {
18131
+ if (hasScrolled.current && selectedItem) {
18118
18132
  onTabPress(selectedItem.key);
18119
18133
  }
18120
18134
  },
18135
+ onPageScrollStateChanged: onPageScrollStateChanged,
18121
18136
  onPageScroll: reactNative.Animated.event([{
18122
18137
  nativeEvent: {
18123
18138
  offset: scrollOffsetAnimatedValue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn",
3
- "version": "8.64.0",
3
+ "version": "8.64.1",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -1,10 +1,11 @@
1
- import React, { useRef } from 'react';
2
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
1
+ import React, { useEffect, useMemo, useRef } from 'react';
3
2
  import PagerView from 'react-native-pager-view';
4
- import { TabContainer } from './StyledScrollableTabs';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
4
  import type { TabsProps } from '.';
6
5
  import SceneView from './SceneView';
7
6
  import ScrollableTabHeader from './ScrollableTabsHeader/ScrollableTabsHeader';
7
+ import { TabContainer } from './StyledScrollableTabs';
8
+ import useHandlePageScroll from './useHandlePageScroll';
8
9
  import { ScreenContext, TabContext } from './useIsFocused';
9
10
 
10
11
  export interface ScrollableTabProps extends TabsProps {
@@ -23,15 +24,15 @@ const ScrollableTab = ({
23
24
  testID: componentTestID,
24
25
  variant = 'highlighted',
25
26
  }: ScrollableTabProps) => {
26
- const pagerViewRef = React.useRef<PagerView>(null);
27
+ const pagerViewRef = useRef<PagerView>(null);
27
28
  const insets = useSafeAreaInsets();
28
29
  const selectedTabIndex = tabs.findIndex(
29
30
  (item) => item.key === selectedTabKey
30
31
  );
31
- // Used as a flag to prevent calling onTabPress on initial render
32
- const hasScrolled = useRef(false);
33
32
 
34
- React.useEffect(() => {
33
+ const { hasScrolled, onPageScrollStateChanged } = useHandlePageScroll();
34
+
35
+ useEffect(() => {
35
36
  let timeoutHandle: ReturnType<typeof setTimeout>;
36
37
  if (selectedTabIndex !== -1) {
37
38
  // If the selected tab is changed too quickly, the setPage is crashed and not work anymore
@@ -49,7 +50,7 @@ const ScrollableTab = ({
49
50
  };
50
51
  }, [selectedTabIndex, pagerViewRef]);
51
52
 
52
- const tabContextProviderValue = React.useMemo(
53
+ const tabContextProviderValue = useMemo(
53
54
  () => ({
54
55
  selectedTabKey,
55
56
  }),
@@ -72,14 +73,7 @@ const ScrollableTab = ({
72
73
  useNext
73
74
  initialPage={selectedTabIndex}
74
75
  ref={pagerViewRef}
75
- onPageScrollStateChanged={(e) => {
76
- if (
77
- !hasScrolled.current &&
78
- e.nativeEvent.pageScrollState === 'dragging'
79
- ) {
80
- hasScrolled.current = true;
81
- }
82
- }}
76
+ onPageScrollStateChanged={onPageScrollStateChanged}
83
77
  onPageSelected={(e) => {
84
78
  const index = e.nativeEvent.position;
85
79
  const selectedItem = tabs[index];
@@ -99,6 +99,38 @@ describe('Tabs.Scroll', () => {
99
99
  expect(getByText('Calendar Screen unfocused')).toBeDefined();
100
100
  });
101
101
 
102
+ it('calls onTabPress correctly', () => {
103
+ const onTabPress = jest.fn();
104
+ const { getByText } = renderWithTheme(
105
+ <SafeAreaProvider
106
+ initialMetrics={{
107
+ frame: { x: 0, y: 0, width: 0, height: 0 },
108
+ insets: { top: 0, left: 0, right: 0, bottom: 0 },
109
+ }}
110
+ >
111
+ <ScrollableTabs
112
+ tabs={[
113
+ {
114
+ key: 'work',
115
+ activeItem: 'Work',
116
+ component: <CustomScreen title="Work Screen" />,
117
+ },
118
+ ]}
119
+ onTabPress={onTabPress}
120
+ selectedTabKey="work"
121
+ />
122
+ </SafeAreaProvider>
123
+ );
124
+
125
+ // Not calling the function on first render
126
+ expect(onTabPress).not.toHaveBeenCalled();
127
+
128
+ // Calling the function on tab press
129
+ fireEvent.press(getByText('Work'));
130
+
131
+ expect(onTabPress).toHaveBeenCalledTimes(1);
132
+ });
133
+
102
134
  describe('lazy', () => {
103
135
  it('render all screens when lazy = false', async () => {
104
136
  const { queryByText } = renderWithTheme(
@@ -110,6 +110,38 @@ describe('Tabs', () => {
110
110
  fireEvent.press(getByText('Home'));
111
111
  expect(getByText('Home Screen focused')).toBeDefined();
112
112
  });
113
+
114
+ it('calls onTabPress only when pressed', () => {
115
+ const onTabPress = jest.fn();
116
+ const { getByText } = renderWithTheme(
117
+ <SafeAreaProvider
118
+ initialMetrics={{
119
+ frame: { x: 0, y: 0, width: 0, height: 0 },
120
+ insets: { top: 0, left: 0, right: 0, bottom: 0 },
121
+ }}
122
+ >
123
+ <Tabs
124
+ tabs={[
125
+ {
126
+ key: 'work',
127
+ activeItem: 'Work',
128
+ component: <CustomScreen title="Work Screen" />,
129
+ },
130
+ ]}
131
+ onTabPress={onTabPress}
132
+ selectedTabKey="work"
133
+ />
134
+ </SafeAreaProvider>
135
+ );
136
+
137
+ // Not calling the function on first render
138
+ expect(onTabPress).not.toHaveBeenCalled();
139
+
140
+ // Calling the function on tab press
141
+ fireEvent.press(getByText('Work'));
142
+
143
+ expect(onTabPress).toHaveBeenCalledTimes(1);
144
+ });
113
145
  });
114
146
 
115
147
  describe('useIsFocused', () => {
@@ -1,6 +1,6 @@
1
1
  import { useTheme } from '@emotion/react';
2
2
  import type { ReactNode } from 'react';
3
- import React, { useEffect } from 'react';
3
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
4
4
  import type { StyleProp, ViewProps, ViewStyle } from 'react-native';
5
5
  import { Animated, TouchableWithoutFeedback, View } from 'react-native';
6
6
  import type { PagerViewOnPageScrollEventData } from 'react-native-pager-view';
@@ -19,6 +19,7 @@ import {
19
19
  } from './StyledTabs';
20
20
  import type { BadgeConfigType } from './TabWithBadge';
21
21
  import TabWithBadge from './TabWithBadge';
22
+ import useHandlePageScroll from './useHandlePageScroll';
22
23
  import { ScreenContext, TabContext, useIsFocused } from './useIsFocused';
23
24
 
24
25
  export type ItemType =
@@ -57,7 +58,7 @@ export interface TabsProps extends ViewProps {
57
58
  */
58
59
  barStyle?: StyleProp<ViewStyle>;
59
60
  /**
60
- * Whether inactive screen should be removed and unmounted in React.
61
+ * Whether inactive screen should be removed and unmounted in
61
62
  * Defaults value is `false`.
62
63
  */
63
64
  lazy?: boolean;
@@ -116,13 +117,15 @@ const Tabs = ({
116
117
  }: TabsProps): JSX.Element => {
117
118
  const theme = useTheme();
118
119
  const insets = useSafeAreaInsets();
119
- const pagerViewRef = React.useRef<PagerView>(null);
120
+ const pagerViewRef = useRef<PagerView>(null);
120
121
  const selectedTabIndex = tabs.findIndex(
121
122
  (item) => item.key === selectedTabKey
122
123
  );
123
- const scrollOffsetAnimatedValue = React.useRef(new Animated.Value(0)).current;
124
- const positionAnimatedValue = React.useRef(new Animated.Value(0)).current;
125
- const [tabsWidth, setTabsWidth] = React.useState<number>(0);
124
+ const scrollOffsetAnimatedValue = useRef(new Animated.Value(0)).current;
125
+ const positionAnimatedValue = useRef(new Animated.Value(0)).current;
126
+ const [tabsWidth, setTabsWidth] = useState<number>(0);
127
+
128
+ const { onPageScrollStateChanged, hasScrolled } = useHandlePageScroll();
126
129
 
127
130
  useEffect(() => {
128
131
  if (selectedTabIndex !== -1) {
@@ -130,7 +133,7 @@ const Tabs = ({
130
133
  }
131
134
  }, [selectedTabIndex]);
132
135
 
133
- const tabContextProviderValue = React.useMemo(
136
+ const tabContextProviderValue = useMemo(
134
137
  () => ({
135
138
  selectedTabKey,
136
139
  }),
@@ -201,10 +204,11 @@ const Tabs = ({
201
204
  onPageSelected={(e) => {
202
205
  const index = e.nativeEvent.position;
203
206
  const selectedItem = tabs[index];
204
- if (selectedItem) {
207
+ if (hasScrolled.current && selectedItem) {
205
208
  onTabPress(selectedItem.key);
206
209
  }
207
210
  }}
211
+ onPageScrollStateChanged={onPageScrollStateChanged}
208
212
  onPageScroll={Animated.event<PagerViewOnPageScrollEventData>(
209
213
  [
210
214
  {
@@ -0,0 +1,32 @@
1
+ import { useCallback, useRef } from 'react';
2
+ import { NativeSyntheticEvent } from 'react-native';
3
+
4
+ const useHandlePageScroll = () => {
5
+ // Used as a flag to prevent calling onTabPress on initial render
6
+ const hasScrolled = useRef(false);
7
+
8
+ const onPageScrollStateChanged = useCallback(
9
+ (
10
+ e: NativeSyntheticEvent<
11
+ Readonly<{
12
+ pageScrollState: 'idle' | 'dragging' | 'settling';
13
+ }>
14
+ >
15
+ ) => {
16
+ if (
17
+ !hasScrolled.current &&
18
+ e.nativeEvent.pageScrollState === 'dragging'
19
+ ) {
20
+ hasScrolled.current = true;
21
+ }
22
+ },
23
+ []
24
+ );
25
+
26
+ return {
27
+ onPageScrollStateChanged,
28
+ hasScrolled,
29
+ };
30
+ };
31
+
32
+ export default useHandlePageScroll;
@@ -4840,3 +4840,5 @@ var drawChart = (function (exports) {
4840
4840
  </body>
4841
4841
  </html>
4842
4842
 
4843
+ >
4844
+