@jescon-technologies/react-native-ui-kit 0.0.20 → 0.0.22

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/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export { default as ABlink } from './src/Alerts/ABlink';
5
5
  export { default as HIcons } from './src/Hoc/HIcons';
6
6
  export { default as HView } from './src/Hoc/HView';
7
7
  export { default as HProvider } from './src/Hoc/HProvider';
8
+ export { default as HWrappedComponent } from './src/Hoc/HWrappedComponent';
9
+ export { default as HHeading } from './src/Hoc/HHeading';
8
10
  export { default as HShadowButton } from './src/Hoc/HShadowButton';
9
11
  export { default as Navigation } from './src/Navigation/PageNavigation';
10
12
  export { default as SSearchBar } from './src/StaticComponents/SSearchBar';
@@ -23,10 +25,11 @@ export { default as HeaderBlock } from './src/CustomComponents/HeaderBlock';
23
25
  export { default as HDashboard } from './src/Hoc/HDashboard';
24
26
  export { default as NetworkServiceCall } from './src/Common/NetworkServiceCall';
25
27
  export { default as useNotifications } from './src/Handlers/NotificationsContext';
26
- export { default as ResponseComponentContext, ResponseComponentProvider } from './src/Handlers/ResponseComponentContext';
27
- export type { ResponseComponentProviderProps, ResponseContextValue, ResponseJSON } from './src/Handlers/ResponseComponentContext';
28
+ export { default as CBackHandler } from './src/CustomComponents/CBackHandler';
29
+ export * from './src/Handlers/ResponseComponentContext';
28
30
  export * from './src/Navigation/useNavigation';
29
31
  export * from './src/Navigation/useIsFocused';
30
32
  export * from './src/Navigation/useFocusEffect';
31
- export { default as CBackHandler } from './src/CustomComponents/CBackHandler';
32
33
  export * from './src/CommonStyle/ComponentFunctions';
34
+ export * from '../../../src/Common/ApiConstants'
35
+ export * from '../../../src/Common/Global';
package/index.js CHANGED
@@ -5,6 +5,8 @@ export { default as ABlink } from './src/Alerts/ABlink';
5
5
  export { default as HIcons } from './src/Hoc/HIcons';
6
6
  export { default as HView } from './src/Hoc/HView';
7
7
  export { default as HProvider } from './src/Hoc/HProvider';
8
+ export { default as HWrappedComponent } from './src/Hoc/HWrappedComponent';
9
+ export { default as HHeading } from './src/Hoc/HHeading';
8
10
  export { default as HShadowButton } from './src/Hoc/HShadowButton';
9
11
  export { default as Navigation } from './src/Navigation/PageNavigation';
10
12
  export { default as SSearchBar } from './src/StaticComponents/SSearchBar';
@@ -23,9 +25,11 @@ export { default as HeaderBlock } from './src/CustomComponents/HeaderBlock';
23
25
  export { default as HDashboard } from './src/Hoc/HDashboard';
24
26
  export { default as NetworkServiceCall } from './src/Common/NetworkServiceCall';
25
27
  export { default as useNotifications } from './src/Handlers/NotificationsContext';
26
- export { default as ResponseComponentContext, ResponseComponentProvider } from './src/Handlers/ResponseComponentContext';
28
+ export { default as CBackHandler } from './src/CustomComponents/CBackHandler';
29
+ export * from './src/Handlers/ResponseComponentContext';
27
30
  export * from './src/Navigation/useNavigation';
28
31
  export * from './src/Navigation/useIsFocused';
29
32
  export * from './src/Navigation/useFocusEffect';
30
- export { default as CBackHandler } from './src/CustomComponents/CBackHandler';
31
33
  export * from './src/CommonStyle/ComponentFunctions';
34
+ export * from '../../../src/Common/ApiConstants'
35
+ export * from '../../../src/Common/Global';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jescon-technologies/react-native-ui-kit",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "A React Native module for Jescon Technologies that provides react-native-ui-kit",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -0,0 +1,78 @@
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ useEffect,
5
+ useSyncExternalStore,
6
+ } from 'react';
7
+ import type { ReactNode } from 'react';
8
+
9
+ export type GlobalConfig = Record<string, unknown>;
10
+
11
+ interface GlobalStore {
12
+ getSnapshot: () => object;
13
+ subscribe: (listener: () => void) => () => void;
14
+ }
15
+
16
+ let globalConfig: object = {};
17
+ const listeners = new Set<() => void>();
18
+
19
+ const notifyListeners = (): void => {
20
+ listeners.forEach(listener => listener());
21
+ };
22
+
23
+ const globalStore: GlobalStore = {
24
+ getSnapshot: () => globalConfig,
25
+ subscribe: listener => {
26
+ listeners.add(listener);
27
+ return () => listeners.delete(listener);
28
+ },
29
+ };
30
+
31
+ export const GlobalContext = createContext<GlobalStore>(globalStore);
32
+
33
+ export const setGlobal = <T extends object>(config: T): void => {
34
+ globalConfig = config;
35
+ notifyListeners();
36
+ };
37
+
38
+ export const getGlobal = <
39
+ T extends object = GlobalConfig,
40
+ >(): T => globalConfig as T;
41
+
42
+ export const updateGlobal = <T extends object = GlobalConfig>(
43
+ config: Partial<T>,
44
+ ): void => {
45
+ Object.assign(globalConfig, config);
46
+ notifyListeners();
47
+ };
48
+
49
+ export const useGlobal = <T extends object = GlobalConfig>(): T => {
50
+ const store = useContext(GlobalContext);
51
+ return useSyncExternalStore(
52
+ store.subscribe,
53
+ store.getSnapshot,
54
+ store.getSnapshot,
55
+ ) as T;
56
+ };
57
+
58
+ interface GlobalProviderProps {
59
+ global?: object;
60
+ children?: ReactNode;
61
+ }
62
+
63
+ export const GlobalProvider: React.FC<GlobalProviderProps> = ({
64
+ global,
65
+ children,
66
+ }) => {
67
+ useEffect(() => {
68
+ if (global !== undefined) {
69
+ setGlobal(global);
70
+ }
71
+ }, [global]);
72
+
73
+ return (
74
+ <GlobalContext.Provider value={globalStore}>
75
+ {children}
76
+ </GlobalContext.Provider>
77
+ );
78
+ };
@@ -14,7 +14,7 @@ import {
14
14
  ViewStyle,
15
15
  TextStyle,
16
16
  } from 'react-native';
17
- import { APIURL } from '../../../../../src/Common/apiConstants';
17
+ import { APIURL } from '@jescon-technologies/react-native-ui-kit';
18
18
  import Loader from '../Custom/Loader';
19
19
  import { isBNU, isBNUL, isNU, normalize } from '../CommonStyle/ComponentFunctions';
20
20
  import NetworkServiceCall from '../Common/NetworkServiceCall';
@@ -11,7 +11,7 @@ import {
11
11
  import { normalize} from '../CommonStyle/ComponentFunctions';
12
12
  import RNExitApp from 'react-native-exit-app';
13
13
  import { Global, GlobalUserData } from '../../../../../src/Common/Global';
14
- import { imageURL } from '../../../../../src/Common/apiConstants';
14
+ import { imageURL } from '@jescon-technologies/react-native-ui-kit';
15
15
  import { useNavigation } from '../Navigation/useNavigation';
16
16
  import CModalOverlay from '../CustomComponents/CModalOverlay';
17
17
  import HIcons from '../Hoc/HIcons';
@@ -13,7 +13,7 @@ import {
13
13
  TextStyle,
14
14
  } from 'react-native';
15
15
  import { normalize} from '../CommonStyle/ComponentFunctions';
16
- import { APIURL } from '../../../../../src/Common/apiConstants';
16
+ import { imageURL } from '@jescon-technologies/react-native-ui-kit';
17
17
 
18
18
  // ---------------------------------------------------------------------------
19
19
  // Types
@@ -45,7 +45,7 @@ export default function Loader({
45
45
  overlayColor = 'rgba(0,0,0,0.4)',
46
46
  loaderColor = 'lightblue',
47
47
  size = Platform.OS !== 'web' ? 30 : 50,
48
- gifSource = { uri: `${APIURL}file/getCommonFile/image/heartpulse.gif` },
48
+ gifSource = { uri: `${imageURL}heartpulse.gif` },
49
49
  message = '',
50
50
  messageStyle = {},
51
51
  animationType = 'fade',
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import {
3
+ Platform,
4
+ View,
5
+ ScrollView,
6
+ StyleSheet,
7
+ StyleProp,
8
+ ViewStyle,
9
+ } from 'react-native';
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Types
13
+ // ---------------------------------------------------------------------------
14
+
15
+ export interface CHeaderViewProps {
16
+ /** Extra style merged onto the outer container. */
17
+ style?: StyleProp<ViewStyle>;
18
+ /** Header rail content (usually a column/row of buttons). */
19
+ children?: React.ReactNode;
20
+ }
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Styles
24
+ // ---------------------------------------------------------------------------
25
+
26
+ const styles = StyleSheet.create({
27
+ base: {
28
+ backgroundColor: 'white',
29
+ },
30
+ content: {
31
+ alignItems: 'center',
32
+ },
33
+ webContent: {
34
+ flexDirection: 'column',
35
+ paddingVertical: '1%',
36
+ },
37
+ mobileContent: {
38
+ flexDirection: 'row',
39
+ paddingHorizontal: '1%',
40
+ paddingRight: '10%',
41
+ },
42
+ });
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // Component
46
+ // ---------------------------------------------------------------------------
47
+
48
+ const CHeaderView: React.FC<CHeaderViewProps> = ({ style, children }) => {
49
+ const isWeb = Platform.OS === 'web';
50
+
51
+ const containerStyle: ViewStyle = isWeb
52
+ ? {
53
+ position: 'absolute',
54
+ left: 0,
55
+ bottom: 0,
56
+ width: 80,
57
+ borderRightWidth: 1,
58
+ borderRightColor: 'lightgrey',
59
+ zIndex: 10,
60
+ elevation: 10,
61
+ maxHeight: '90%',
62
+ }
63
+ : {
64
+ borderTopWidth: 1,
65
+ borderTopColor: 'lightgrey',
66
+ };
67
+
68
+ return (
69
+ <View style={[styles.base, containerStyle, style]}>
70
+ <ScrollView
71
+ horizontal={!isWeb}
72
+ showsHorizontalScrollIndicator={false}
73
+ showsVerticalScrollIndicator={false}
74
+ bounces={false}
75
+ contentContainerStyle={[
76
+ styles.content,
77
+ isWeb ? styles.webContent : styles.mobileContent,
78
+ ]}
79
+ >
80
+ {children}
81
+ </ScrollView>
82
+ </View>
83
+ );
84
+ };
85
+
86
+ export default CHeaderView;
@@ -33,7 +33,7 @@ import NetworkServiceCall from '../Common/NetworkServiceCall';
33
33
  import HIcons from '../Hoc/HIcons';
34
34
  import ResponseComponentContext from '../Handlers/ResponseComponentContext';
35
35
  import { Global } from '../../../../../src/Common/Global';
36
- import { APIURL } from '../../../../../src/Common/apiConstants';
36
+ import { notifyURL } from '@jescon-technologies/react-native-ui-kit';
37
37
 
38
38
  // import HelpdeskScreenFocus from '../Helpdesk/View/HelpdeskScreenFocus';
39
39
  // import CHelpdeskView from '../Helpdesk/View/CHelpdeskView';
@@ -50,7 +50,6 @@ interface HeaderBlockProps {
50
50
  webview?: unknown;
51
51
  data?: unknown;
52
52
  navigation?: (route: string, params?: object) => void;
53
- APIURL?: string;
54
53
  [key: string]: unknown;
55
54
  }
56
55
 
@@ -358,9 +357,7 @@ const HeaderBlock: React.FC<HeaderBlockProps> = (props) => {
358
357
  const userData = Global.userData as UserDataLite | null | undefined;
359
358
  if (userData && userData.suuser) {
360
359
  setIsLoadingNotifications(true);
361
- const url =
362
- APIURL + 'invget/invcommonget/rnhrsumessageuserretrievaljson ' + userData.suuser;
363
- NetworkServiceCall('get', url)
360
+ NetworkServiceCall('get',`${notifyURL} ${userData.suuser}`)
364
361
  .then((response: NetworkResponse<NotificationItem[] | NotificationsPayload>) => {
365
362
  setIsLoadingNotifications(false);
366
363
  if (response && response.httpstatus == 200) {
@@ -30,9 +30,8 @@ import NetworkServiceCall from '../Common/NetworkServiceCall';
30
30
  import { notifyMessage } from '../CommonStyle/ComponentFunctions';
31
31
  import HShadowButton from './HShadowButton';
32
32
  import HIcons from './HIcons';
33
- import { normalize} from '../CommonStyle/ComponentFunctions';
33
+ import { normalize } from '../CommonStyle/ComponentFunctions';
34
34
  import { Global } from '../../../../../src/Common/Global';
35
- ;
36
35
  import SDateTimePicker from '../StaticComponents/SDateTimePicker';
37
36
 
38
37
  // ---------------------------------------------------------------------------
@@ -118,7 +117,7 @@ interface ContentConfig {
118
117
  interface ChartStyleConfig {
119
118
  bar?: Record<string, unknown>;
120
119
  line?: Record<string, unknown>;
121
- pie?: { centerCaption?: string; [key: string]: unknown };
120
+ pie?: { centerCaption?: string;[key: string]: unknown };
122
121
  axisTextStyle?: TextStyle;
123
122
  [key: string]: unknown;
124
123
  }
@@ -494,7 +493,7 @@ const WIDGET_RENDERERS: Record<string, React.ComponentType<WidgetRendererProps>>
494
493
  // Widget shell
495
494
  // ---------------------------------------------------------------------------
496
495
 
497
- interface WidgetBodyProps extends WidgetRendererProps {}
496
+ interface WidgetBodyProps extends WidgetRendererProps { }
498
497
 
499
498
  const WidgetBody: React.FC<WidgetBodyProps> = ({ widget, theme, content, chartStyle }) => {
500
499
  const Renderer = WIDGET_RENDERERS[widget.type];
@@ -508,7 +507,7 @@ const WidgetBody: React.FC<WidgetBodyProps> = ({ widget, theme, content, chartSt
508
507
  );
509
508
  };
510
509
 
511
- interface DashboardWidgetProps extends WidgetRendererProps {}
510
+ interface DashboardWidgetProps extends WidgetRendererProps { }
512
511
 
513
512
  const DashboardWidget: React.FC<DashboardWidgetProps> = ({
514
513
  widget,
@@ -885,21 +884,21 @@ const styles = StyleSheet.create({
885
884
  justifyContent: 'center',
886
885
  padding: 24,
887
886
  },
888
- centerStateText: { marginTop: 12, fontSize: 14, textAlign: 'center' },
887
+ centerStateText: { marginTop: 8, fontSize: 14, textAlign: 'center' },
889
888
  header: {
890
- paddingTop: 12,
891
- paddingBottom: 10,
889
+ paddingVertical: 8,
892
890
  borderBottomWidth: StyleSheet.hairlineWidth,
893
- marginBottom: 10,
891
+ marginBottom: 8,
894
892
  },
895
893
  headerTop: {
896
894
  flexDirection: 'row',
897
895
  alignItems: 'flex-start',
898
896
  justifyContent: 'space-between',
897
+ width: '100%',
899
898
  },
900
899
  headerIdentity: { flexDirection: 'row', alignItems: 'center', flex: 1 },
901
900
  headerCopy: { flex: 1 },
902
- dashboardTitle: { fontSize: 24, fontWeight: '800', letterSpacing: -0.2 },
901
+ dashboardTitle: { fontSize: 24, fontWeight: '800', letterSpacing: -0.2, width: '50%' },
903
902
  dateRangeBadge: {
904
903
  flexDirection: 'row',
905
904
  alignItems: 'center',
@@ -909,6 +908,7 @@ const styles = StyleSheet.create({
909
908
  padding: 7,
910
909
  borderWidth: 1,
911
910
  borderRadius: 14,
911
+ width: '50%',
912
912
  },
913
913
  dateRangeIconWrap: {
914
914
  width: 32,
@@ -920,15 +920,15 @@ const styles = StyleSheet.create({
920
920
  dateRangeCopy: { flexShrink: 1, marginLeft: 9 },
921
921
  dateRangeLabel: { fontSize: 9, fontWeight: '800', letterSpacing: 0.7 },
922
922
  dateRange: { fontSize: 12, fontWeight: '700', marginTop: 2 },
923
- departmentSelector: { flexDirection: 'row', paddingVertical: 14 },
923
+ departmentSelector: { flexDirection: 'row', paddingVertical: 8 },
924
924
  departmentButton: {
925
925
  flexDirection: 'row',
926
926
  alignItems: 'center',
927
- gap: 7,
927
+ gap: 6,
928
928
  borderWidth: 1,
929
929
  borderRadius: 12,
930
- paddingHorizontal: 14,
931
- paddingVertical: 8,
930
+ paddingHorizontal: 12,
931
+ paddingVertical: 6,
932
932
  marginRight: 8,
933
933
  },
934
934
  departmentButtonText: { fontSize: 12, fontWeight: '700' },
@@ -936,8 +936,8 @@ const styles = StyleSheet.create({
936
936
  width: '50%',
937
937
  borderWidth: 1,
938
938
  borderRadius: 12,
939
- padding: 16,
940
- marginBottom: 12,
939
+ padding: 12,
940
+ marginBottom: 8,
941
941
  minHeight: 88,
942
942
  overflow: 'hidden',
943
943
  },
@@ -951,13 +951,13 @@ const styles = StyleSheet.create({
951
951
  alignItems: 'flex-start',
952
952
  justifyContent: 'space-between',
953
953
  borderBottomWidth: StyleSheet.hairlineWidth,
954
- paddingBottom: 10,
955
- marginBottom: 12,
954
+ paddingBottom: 8,
955
+ marginBottom: 8,
956
956
  },
957
- widgetHeaderCopy: { flex: 1, paddingRight: 12 },
958
- widgetIcon: { marginRight: 8, marginTop: 1 },
957
+ widgetHeaderCopy: { flex: 1, paddingRight: 8 },
958
+ widgetIcon: { marginRight: 6, marginTop: 1 },
959
959
  widgetTitle: { fontSize: 16, fontWeight: '800', letterSpacing: -0.2 },
960
- widgetSubtitle: { fontSize: 12, marginTop: 3, lineHeight: 17, fontWeight: '500' },
960
+ widgetSubtitle: { fontSize: 12, marginTop: 2, lineHeight: 17, fontWeight: '500' },
961
961
  detailsButton: {
962
962
  height: 24,
963
963
  flexDirection: 'row',
@@ -965,7 +965,7 @@ const styles = StyleSheet.create({
965
965
  justifyContent: 'center',
966
966
  borderWidth: 1,
967
967
  borderRadius: 12,
968
- paddingHorizontal: 10,
968
+ paddingHorizontal: 8,
969
969
  marginTop: 1,
970
970
  },
971
971
  detailsButtonText: { fontSize: 10, fontWeight: '700' },
@@ -974,24 +974,24 @@ const styles = StyleSheet.create({
974
974
  flexDirection: 'row',
975
975
  flexWrap: 'wrap',
976
976
  justifyContent: 'flex-start',
977
- marginTop: 14,
977
+ marginTop: 8,
978
978
  borderTopWidth: StyleSheet.hairlineWidth,
979
- paddingTop: 10,
979
+ paddingTop: 8,
980
980
  },
981
981
  chartLegendItem: {
982
982
  width: '50%',
983
983
  flexDirection: 'row',
984
984
  alignItems: 'center',
985
- paddingVertical: 5,
986
- paddingRight: 10,
985
+ paddingVertical: 4,
986
+ paddingRight: 8,
987
987
  },
988
- chartLegendDot: { width: 8, height: 8, borderRadius: 4, marginRight: 7 },
988
+ chartLegendDot: { width: 8, height: 8, borderRadius: 4, marginRight: 6 },
989
989
  chartLegendLabel: { flex: 1, fontSize: 10, fontWeight: '600' },
990
990
  chartLegendValue: { fontSize: 10, fontWeight: '800' },
991
- emptyText: { fontSize: 13, textAlign: 'center', paddingVertical: 26 },
991
+ emptyText: { fontSize: 13, textAlign: 'center', paddingVertical: 16 },
992
992
  itemTitle: { fontSize: 13, fontWeight: '700' },
993
- itemSubtitle: { fontSize: 11, marginTop: 3 },
994
- progressTrack: { height: 10, borderRadius: 8, overflow: 'hidden', marginVertical: 6 },
993
+ itemSubtitle: { fontSize: 11, marginTop: 2 },
994
+ progressTrack: { height: 10, borderRadius: 8, overflow: 'hidden', marginVertical: 4 },
995
995
  progressFill: { height: '100%', borderRadius: 8 },
996
996
  heatmap: { flexDirection: 'row', flexWrap: 'wrap' },
997
997
  heatCell: {
@@ -1001,21 +1001,22 @@ const styles = StyleSheet.create({
1001
1001
  minHeight: 58,
1002
1002
  alignItems: 'center',
1003
1003
  justifyContent: 'center',
1004
- margin: 3,
1004
+ margin: 2,
1005
1005
  borderRadius: 8,
1006
1006
  },
1007
1007
  heatLabel: { fontSize: 11, fontWeight: '600' },
1008
- heatValue: { fontSize: 14, fontWeight: '700', marginTop: 3 },
1009
- rankRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 6 },
1008
+ heatValue: { fontSize: 14, fontWeight: '700', marginTop: 2 },
1009
+ rankRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 4 },
1010
1010
  rankNumber: { width: 24, fontSize: 13, fontWeight: '700' },
1011
1011
  rankBody: { flex: 1 },
1012
- rankLabels: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4 },
1012
+ rankLabels: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 2 },
1013
1013
  datePickerRow: {
1014
1014
  justifyContent: 'space-between',
1015
- flexDirection: 'row',
1015
+ width: '50%',
1016
1016
  },
1017
1017
  datePickerWrapper: {
1018
1018
  marginHorizontal: '2%',
1019
+ marginTop: '2%',
1019
1020
  },
1020
1021
  datePickerLabel: {
1021
1022
  position: 'absolute',
@@ -0,0 +1,121 @@
1
+ import React, { memo } from 'react';
2
+ import { View, TouchableOpacity, Text, StyleProp, TextStyle } from 'react-native';
3
+ import { normalize } from '../CommonStyle/ComponentFunctions';
4
+ import HIcons from './HIcons';
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Types
8
+ // ---------------------------------------------------------------------------
9
+
10
+ export interface HHeadingStyles {
11
+ iconname?: string;
12
+ icongroup?: number;
13
+ bgcolor?: string;
14
+ iconsize?: number;
15
+ iconcolor?: string;
16
+ displaytext?: string;
17
+ textsize?: number;
18
+ textcolor?: string;
19
+ }
20
+
21
+ export interface HHeadingProps {
22
+ /** Style bag — all keys optional; defaults are applied for missing keys. */
23
+ styles?: HHeadingStyles;
24
+ /** Optional expand handler; receives `1` when tapped. */
25
+ Expand?: (value: number) => void;
26
+ /** Right-side content (icons, buttons, etc.). */
27
+ children?: React.ReactNode;
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Defaults
33
+ // ---------------------------------------------------------------------------
34
+
35
+ const DEFAULT_STYLES: Required<
36
+ Pick<
37
+ HHeadingStyles,
38
+ | 'iconname'
39
+ | 'bgcolor'
40
+ | 'iconsize'
41
+ | 'iconcolor'
42
+ | 'displaytext'
43
+ | 'textsize'
44
+ | 'textcolor'
45
+ >
46
+ > = {
47
+ iconname: 'file',
48
+ bgcolor: '#f2efef',
49
+ iconsize: 18,
50
+ iconcolor: 'black',
51
+ displaytext: 'Testing',
52
+ textsize: 15,
53
+ textcolor: 'darkblue',
54
+ };
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Component
58
+ // ---------------------------------------------------------------------------
59
+
60
+ function HHeading(props: HHeadingProps): React.ReactElement {
61
+ const styles: HHeadingStyles =
62
+ props.styles !== undefined ? props.styles : DEFAULT_STYLES;
63
+
64
+ return (
65
+ <TouchableOpacity
66
+ style={{
67
+ backgroundColor: styles.bgcolor ?? '#f2efef',
68
+ paddingVertical: 3,
69
+ paddingHorizontal: 6,
70
+ marginTop: 3,
71
+ marginBottom: 2,
72
+ display: 'flex',
73
+ flexDirection: 'row',
74
+ alignItems: 'center',
75
+ justifyContent: 'center',
76
+ elevation: 5,
77
+ borderWidth: 0.5,
78
+ borderColor: 'lightgrey',
79
+ width: '99%',
80
+ alignSelf: 'center',
81
+ }}
82
+ >
83
+ <TouchableOpacity
84
+ onPress={() => (props.Expand !== undefined ? props.Expand(1) : null)}
85
+ disabled={props.Expand === undefined}
86
+ style={{ width: normalize(30), alignItems: 'center', marginRight: 5 }}
87
+ >
88
+ <HIcons.Icons
89
+ icongroup={styles.icongroup ?? 5}
90
+ name={styles.iconname}
91
+ color={styles.iconcolor}
92
+ size={normalize(styles.iconsize ?? DEFAULT_STYLES.iconsize)}
93
+ />
94
+ </TouchableOpacity>
95
+
96
+ <Text
97
+ style={{
98
+ textShadowRadius: 2,
99
+ fontSize: normalize(styles.textsize ?? DEFAULT_STYLES.textsize),
100
+ fontWeight: 'bold',
101
+ color: styles.textcolor,
102
+ flex: 1,
103
+ }}
104
+ >
105
+ {styles.displaytext}
106
+ </Text>
107
+
108
+ <View
109
+ style={{
110
+ flexDirection: 'row',
111
+ width: normalize(60),
112
+ justifyContent: 'space-around',
113
+ }}
114
+ >
115
+ {props.children}
116
+ </View>
117
+ </TouchableOpacity>
118
+ );
119
+ }
120
+
121
+ export default memo(HHeading);
@@ -10,12 +10,12 @@ interface HProviderProps {
10
10
  }
11
11
  export default function HProvider(props: HProviderProps) {
12
12
  return (
13
- <SafeAreaView style={{ flex: 1 }}>
14
- <ErrorBoundary>
15
- <HView components={props.components}>
16
- <Navigation screens={props.screens} />
17
- </HView>
18
- </ErrorBoundary>
19
- </SafeAreaView>
13
+ <SafeAreaView style={{ flex: 1 }} edges={['left', 'right', 'bottom']}>
14
+ <ErrorBoundary>
15
+ <HView components={props.components}>
16
+ <Navigation screens={props.screens} />
17
+ </HView>
18
+ </ErrorBoundary>
19
+ </SafeAreaView>
20
20
  );
21
21
  }
@@ -0,0 +1,183 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ Dimensions,
6
+ Platform,
7
+ StyleProp,
8
+ ViewStyle,
9
+ TextStyle,
10
+ DimensionValue,
11
+ } from 'react-native';
12
+
13
+ import HeaderBlock from '../CustomComponents/HeaderBlock';
14
+ import HView from './HView';
15
+ import { Global, GlobalOptionDetail } from '../../../../../src/Common/Global';
16
+ import CHeaderView from '../CustomComponents/CHeaderView';
17
+ import HShadowCountButton from './HShadowButton';
18
+ import { normalize, CButtonShadow } from '../CommonStyle/ComponentFunctions';
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Types
22
+ // ---------------------------------------------------------------------------
23
+
24
+ /** Extended shape — `Global.optiondetail` items need these extra fields. */
25
+ interface OptionDetailItem extends GlobalOptionDetail {
26
+ keyid?: string | number;
27
+ icongroup?: number;
28
+ icon?: string;
29
+ display?: string;
30
+ color?: string;
31
+ visibility?: boolean;
32
+ component?: string;
33
+ }
34
+
35
+ interface HWrappedComponentParams {
36
+ component: string;
37
+ data: OptionDetailItem;
38
+ [key: string]: unknown;
39
+ }
40
+
41
+ export interface HWrappedComponentProps {
42
+ route: {
43
+ params: HWrappedComponentParams;
44
+ key?: string;
45
+ name?: string;
46
+ };
47
+ }
48
+
49
+ // ---------------------------------------------------------------------------
50
+ // Constants
51
+ // ---------------------------------------------------------------------------
52
+
53
+ const BUTTON_SIZE =
54
+ Platform.OS === 'web'
55
+ ? Dimensions.get('screen').height * 0.1
56
+ : Dimensions.get('screen').height * 0.05;
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Component
60
+ // ---------------------------------------------------------------------------
61
+
62
+ const HWrappedComponent: React.FC<HWrappedComponentProps> = ({ route }) => {
63
+ const { component, data, ...restParams } = route.params;
64
+
65
+ const [callback, setCallback] = useState<boolean>(false);
66
+ const [selectedComponent, setSelectedComponent] = useState<string>(component);
67
+ const [selectedData, setSelectedData] = useState<OptionDetailItem>(data);
68
+
69
+ const handleHeaderBack = useCallback(() => {
70
+ setCallback((prev) => !prev);
71
+ }, []);
72
+
73
+ const handleCirclePress = (item: OptionDetailItem): void => {
74
+ setSelectedData(item);
75
+ setSelectedComponent(item.component ?? '');
76
+ console.log('ViewHOCComponent', JSON.stringify(item));
77
+ };
78
+
79
+ const optionDetail = Global.optiondetail as OptionDetailItem[] | null | undefined;
80
+
81
+ return (
82
+ <View style={styles.container}>
83
+ <HeaderBlock callback={handleHeaderBack} data={data} />
84
+ <CHeaderView>
85
+ {optionDetail?.map(
86
+ (item) =>
87
+ item.visibility && (
88
+ <HShadowCountButton
89
+ key={item.keyid}
90
+ useicon
91
+ usetext
92
+ disabled={false}
93
+ buttonstyle={[
94
+ styles.button,
95
+ {
96
+ ...CButtonShadow(),
97
+ width: BUTTON_SIZE,
98
+ height: BUTTON_SIZE,
99
+ borderColor: item.color,
100
+ backgroundColor:
101
+ item === selectedData
102
+ ? Global.AppTheme.selected_color
103
+ : Global.AppTheme.bg_button,
104
+ },
105
+ ]}
106
+ iconcolor={item.color}
107
+ icongroup={item.icongroup || 5}
108
+ iconname={item.icon}
109
+ iconsize={
110
+ Platform.OS === 'web' ? normalize(25) : normalize(15)
111
+ }
112
+ displaytext={item.display}
113
+ buttonCallback={() => handleCirclePress(item)}
114
+ textstyle={[
115
+ styles.buttonText,
116
+ {
117
+ color: item.color,
118
+ },
119
+ ]}
120
+ />
121
+ )
122
+ )}
123
+ </CHeaderView>
124
+ {selectedComponent && selectedData ? (
125
+ <HView
126
+ headerCallback={callback}
127
+ component={selectedComponent}
128
+ optiondata={selectedData}
129
+ {...restParams}
130
+ />
131
+ ) : null}
132
+ </View>
133
+ );
134
+ };
135
+
136
+ // ---------------------------------------------------------------------------
137
+ // Styles
138
+ // ---------------------------------------------------------------------------
139
+
140
+ const styles = StyleSheet.create({
141
+ container: {
142
+ flex: 1,
143
+ backgroundColor: '#fff',
144
+ } as ViewStyle,
145
+
146
+ button: {
147
+ borderRadius: 10,
148
+ borderWidth: 0.5,
149
+ justifyContent: 'center',
150
+ alignItems: 'center',
151
+ // ⚠️ Original: `marginVertical: Platform.OS === 'web' && '5%'` and
152
+ // `marginHorizontal: Platform.OS !== 'web' && '.5%'` — when the condition
153
+ // is false, the value is `false`, which is an INVALID `DimensionValue`.
154
+ // RN silently ignores `false`; TS rejects it. Fix via conditional spread
155
+ // so behavior is identical (no margin) and the type is valid.
156
+ ...(Platform.OS === 'web' ? { marginVertical: '5%' as DimensionValue } : {}),
157
+ ...(Platform.OS !== 'web' ? { marginHorizontal: '.5%' as DimensionValue } : {}),
158
+ } as ViewStyle,
159
+
160
+ buttonText: {
161
+ fontSize: normalize(7),
162
+ fontWeight: 'bold',
163
+ textAlign: 'center',
164
+ } as TextStyle,
165
+
166
+ contentContainer: {
167
+ flex: 1,
168
+ padding: 10,
169
+ } as ViewStyle,
170
+
171
+ gridContainer: {
172
+ alignItems: 'center',
173
+ justifyContent: 'center',
174
+ paddingVertical: 10,
175
+ } as ViewStyle,
176
+
177
+ scrollContainer: {
178
+ flexDirection: 'row',
179
+ justifyContent: 'space-around',
180
+ } as ViewStyle,
181
+ });
182
+
183
+ export default HWrappedComponent;