cpk-ui 0.5.4 → 0.7.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 (136) hide show
  1. package/README.md +80 -147
  2. package/components/modals/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/components/modals/AlertDialog/AlertDialog.js +14 -7
  4. package/components/modals/Snackbar/Snackbar.d.ts.map +1 -1
  5. package/components/modals/Snackbar/Snackbar.js +20 -17
  6. package/components/uis/Accordion/AccordionItem.d.ts.map +1 -1
  7. package/components/uis/Accordion/AccordionItem.js +41 -17
  8. package/components/uis/Button/Button.d.ts +2 -1
  9. package/components/uis/Button/Button.d.ts.map +1 -1
  10. package/components/uis/Button/Button.js +11 -11
  11. package/components/uis/Card/Card.d.ts +2 -1
  12. package/components/uis/Card/Card.d.ts.map +1 -1
  13. package/components/uis/Card/Card.js +12 -3
  14. package/components/uis/Checkbox/Checkbox.d.ts +2 -1
  15. package/components/uis/Checkbox/Checkbox.d.ts.map +1 -1
  16. package/components/uis/Checkbox/Checkbox.js +2 -2
  17. package/components/uis/CustomPressable/CustomPressable.d.ts.map +1 -1
  18. package/components/uis/CustomPressable/CustomPressable.js +6 -6
  19. package/components/uis/EditText/EditText.d.ts +1 -0
  20. package/components/uis/EditText/EditText.d.ts.map +1 -1
  21. package/components/uis/EditText/EditText.js +18 -13
  22. package/components/uis/Fab/Fab.d.ts +2 -2
  23. package/components/uis/Fab/Fab.d.ts.map +1 -1
  24. package/components/uis/Fab/Fab.js +22 -4
  25. package/components/uis/Icon/Icon.d.ts.map +1 -1
  26. package/components/uis/Icon/Icon.js +6 -3
  27. package/components/uis/IconButton/IconButton.d.ts +2 -1
  28. package/components/uis/IconButton/IconButton.d.ts.map +1 -1
  29. package/components/uis/IconButton/IconButton.js +44 -42
  30. package/components/uis/LoadingIndicator/LoadingIndicator.d.ts +2 -1
  31. package/components/uis/LoadingIndicator/LoadingIndicator.d.ts.map +1 -1
  32. package/components/uis/LoadingIndicator/LoadingIndicator.js +4 -4
  33. package/components/uis/RadioGroup/RadioButton.d.ts +2 -1
  34. package/components/uis/RadioGroup/RadioButton.d.ts.map +1 -1
  35. package/components/uis/RadioGroup/RadioButton.js +2 -2
  36. package/components/uis/RadioGroup/RadioGroup.d.ts.map +1 -1
  37. package/components/uis/RadioGroup/RadioGroup.js +16 -3
  38. package/components/uis/Rating/Rating.d.ts.map +1 -1
  39. package/components/uis/Rating/Rating.js +23 -19
  40. package/components/uis/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  41. package/components/uis/SegmentedControl/SegmentedControl.js +1 -1
  42. package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts +2 -2
  43. package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts.map +1 -1
  44. package/components/uis/StatusbarBrightness/StatusBarBrightness.js +1 -1
  45. package/components/uis/SwitchToggle/SwitchToggle.d.ts +2 -1
  46. package/components/uis/SwitchToggle/SwitchToggle.d.ts.map +1 -1
  47. package/components/uis/SwitchToggle/SwitchToggle.js +2 -2
  48. package/hooks/useHoverState.d.ts +8 -0
  49. package/hooks/useHoverState.d.ts.map +1 -0
  50. package/hooks/useHoverState.js +16 -0
  51. package/package.json +18 -6
  52. package/providers/ThemeProvider.d.ts.map +1 -1
  53. package/providers/ThemeProvider.js +0 -1
  54. package/providers/index.d.ts.map +1 -1
  55. package/providers/index.js +3 -2
  56. package/components/uis/Icon/selection.json +0 -1
  57. package/src/components/common/ErrorBoundary/ErrorBoundary.tsx +0 -75
  58. package/src/components/modals/AlertDialog/AlertDialog.stories.tsx +0 -216
  59. package/src/components/modals/AlertDialog/AlertDialog.test.tsx +0 -251
  60. package/src/components/modals/AlertDialog/AlertDialog.tsx +0 -356
  61. package/src/components/modals/Snackbar/Snackbar.stories.tsx +0 -182
  62. package/src/components/modals/Snackbar/Snackbar.test.tsx +0 -319
  63. package/src/components/modals/Snackbar/Snackbar.tsx +0 -260
  64. package/src/components/modals/Snackbar/const.ts +0 -4
  65. package/src/components/uis/Accordion/Accordion.stories.tsx +0 -167
  66. package/src/components/uis/Accordion/Accordion.test.tsx +0 -272
  67. package/src/components/uis/Accordion/Accordion.tsx +0 -109
  68. package/src/components/uis/Accordion/AccordionItem.tsx +0 -306
  69. package/src/components/uis/Button/Button.stories.tsx +0 -218
  70. package/src/components/uis/Button/Button.test.tsx +0 -620
  71. package/src/components/uis/Button/Button.tsx +0 -436
  72. package/src/components/uis/Card/Card.test.tsx +0 -146
  73. package/src/components/uis/Card/Card.tsx +0 -102
  74. package/src/components/uis/Checkbox/Checkbox.stories.tsx +0 -216
  75. package/src/components/uis/Checkbox/Checkbox.test.tsx +0 -173
  76. package/src/components/uis/Checkbox/Checkbox.tsx +0 -220
  77. package/src/components/uis/CustomPressable/CustomPressable.tsx +0 -48
  78. package/src/components/uis/EditText/EditText.stories.tsx +0 -124
  79. package/src/components/uis/EditText/EditText.test.tsx +0 -477
  80. package/src/components/uis/EditText/EditText.tsx +0 -590
  81. package/src/components/uis/Fab/Fab.stories.tsx +0 -133
  82. package/src/components/uis/Fab/Fab.test.tsx +0 -110
  83. package/src/components/uis/Fab/Fab.tsx +0 -168
  84. package/src/components/uis/Hr/Hr.test.tsx +0 -26
  85. package/src/components/uis/Hr/Hr.tsx +0 -19
  86. package/src/components/uis/Icon/Icon.stories.tsx +0 -98
  87. package/src/components/uis/Icon/Icon.test.tsx +0 -49
  88. package/src/components/uis/Icon/Icon.tsx +0 -3819
  89. package/src/components/uis/IconButton/IconButton.test.tsx +0 -165
  90. package/src/components/uis/IconButton/IconButton.tsx +0 -275
  91. package/src/components/uis/LoadingIndicator/LoadingIndicator.tsx +0 -126
  92. package/src/components/uis/LoadingIndicator/LodingIndicator.stories.tsx +0 -81
  93. package/src/components/uis/PinchZoom/PinchZoom.stories.tsx +0 -266
  94. package/src/components/uis/PinchZoom/PinchZoom.test.tsx +0 -113
  95. package/src/components/uis/PinchZoom/PinchZoom.tsx +0 -424
  96. package/src/components/uis/RadioGroup/RadioButton.tsx +0 -188
  97. package/src/components/uis/RadioGroup/RadioGroup.stories.tsx +0 -188
  98. package/src/components/uis/RadioGroup/RadioGroup.test.tsx +0 -287
  99. package/src/components/uis/RadioGroup/RadioGroup.tsx +0 -109
  100. package/src/components/uis/Rating/Rating.test.tsx +0 -98
  101. package/src/components/uis/Rating/Rating.tsx +0 -200
  102. package/src/components/uis/SegmentedControl/SegmentedControl.stories.tsx +0 -546
  103. package/src/components/uis/SegmentedControl/SegmentedControl.test.tsx +0 -274
  104. package/src/components/uis/SegmentedControl/SegmentedControl.tsx +0 -229
  105. package/src/components/uis/StatusbarBrightness/StatusBarBrightness.test.tsx +0 -41
  106. package/src/components/uis/StatusbarBrightness/StatusBarBrightness.tsx +0 -26
  107. package/src/components/uis/Styled/StyledComponents.tsx +0 -217
  108. package/src/components/uis/SwitchToggle/SwitchToggle.stories.tsx +0 -75
  109. package/src/components/uis/SwitchToggle/SwitchToggle.test.tsx +0 -105
  110. package/src/components/uis/SwitchToggle/SwitchToggle.tsx +0 -305
  111. package/src/components/uis/Typography/Typography.stories.tsx +0 -149
  112. package/src/components/uis/Typography/Typography.test.tsx +0 -58
  113. package/src/components/uis/Typography/Typography.tsx +0 -386
  114. package/src/hooks/index.ts +0 -2
  115. package/src/hooks/useAnimations.ts +0 -71
  116. package/src/hooks/useDebouncedColorScheme.tsx +0 -30
  117. package/src/hooks/useOptimizedStyles.ts +0 -22
  118. package/src/hooks/usePerformance.ts +0 -93
  119. package/src/index.tsx +0 -38
  120. package/src/providers/ThemeProvider.tsx +0 -177
  121. package/src/providers/index.tsx +0 -130
  122. package/src/test/testUtils.tsx +0 -101
  123. package/src/types/common.ts +0 -77
  124. package/src/types/index.ts +0 -1
  125. package/src/types/kstyled.d.ts +0 -6
  126. package/src/utils/accessibility.ts +0 -110
  127. package/src/utils/colors.ts +0 -151
  128. package/src/utils/createCtx.tsx +0 -26
  129. package/src/utils/guards.ts +0 -93
  130. package/src/utils/index.ts +0 -2
  131. package/src/utils/performanceTest.ts +0 -174
  132. package/src/utils/platform.ts +0 -69
  133. package/src/utils/theme.ts +0 -38
  134. package/test/testUtils.d.ts +0 -113
  135. package/test/testUtils.d.ts.map +0 -1
  136. package/test/testUtils.js +0 -65
@@ -1,110 +0,0 @@
1
- import type {AccessibilityProps} from '../types/common';
2
-
3
- /**
4
- * Generate accessibility props for button-like components
5
- */
6
- export function getButtonAccessibilityProps(
7
- label: string,
8
- disabled?: boolean,
9
- pressed?: boolean,
10
- ): AccessibilityProps {
11
- return {
12
- accessibilityRole: 'button',
13
- accessibilityLabel: label,
14
- accessibilityState: {
15
- disabled: disabled ?? false,
16
- ...(pressed !== undefined && {selected: pressed}),
17
- },
18
- };
19
- }
20
-
21
- /**
22
- * Generate accessibility props for checkbox components
23
- */
24
- export function getCheckboxAccessibilityProps(
25
- label: string,
26
- checked: boolean,
27
- disabled?: boolean,
28
- ): AccessibilityProps {
29
- return {
30
- accessibilityRole: 'checkbox',
31
- accessibilityLabel: label,
32
- accessibilityState: {
33
- checked,
34
- disabled: disabled ?? false,
35
- },
36
- };
37
- }
38
-
39
- /**
40
- * Generate accessibility props for radio button components
41
- */
42
- export function getRadioAccessibilityProps(
43
- label: string,
44
- selected: boolean,
45
- disabled?: boolean,
46
- ): AccessibilityProps {
47
- return {
48
- accessibilityRole: 'radio',
49
- accessibilityLabel: label,
50
- accessibilityState: {
51
- selected,
52
- disabled: disabled ?? false,
53
- },
54
- };
55
- }
56
-
57
- /**
58
- * Generate accessibility props for text input components
59
- */
60
- export function getTextInputAccessibilityProps(
61
- label: string,
62
- placeholder?: string,
63
- required?: boolean,
64
- invalid?: boolean,
65
- ): AccessibilityProps {
66
- return {
67
- accessibilityRole: 'text',
68
- accessibilityLabel: label,
69
- accessibilityHint: placeholder,
70
- accessibilityState: {
71
- ...(required && {busy: true}),
72
- ...(invalid && {selected: false}),
73
- },
74
- };
75
- }
76
-
77
- /**
78
- * Generate accessibility props for switch/toggle components
79
- */
80
- export function getSwitchAccessibilityProps(
81
- label: string,
82
- value: boolean,
83
- disabled?: boolean,
84
- ): AccessibilityProps {
85
- return {
86
- accessibilityRole: 'switch',
87
- accessibilityLabel: label,
88
- accessibilityState: {
89
- checked: value,
90
- disabled: disabled ?? false,
91
- },
92
- };
93
- }
94
-
95
- /**
96
- * Generate accessibility props for expandable components (like Accordion)
97
- */
98
- export function getExpandableAccessibilityProps(
99
- label: string,
100
- expanded: boolean,
101
- ): AccessibilityProps {
102
- return {
103
- accessibilityRole: 'button',
104
- accessibilityLabel: label,
105
- accessibilityState: {
106
- expanded,
107
- },
108
- accessibilityHint: expanded ? 'Double tap to collapse' : 'Double tap to expand',
109
- };
110
- }
@@ -1,151 +0,0 @@
1
- const baseColors = {
2
- success: '#1CD66C',
3
- warning: '#E2B101',
4
- danger: '#F84444',
5
- info: '#307EF1',
6
- accent: '#6BF3C5',
7
- link: '#A351F4',
8
- };
9
-
10
- const buttonColors = {
11
- light: {
12
- primary: {bg: '#1B1B1B', text: '#FFFFFF'},
13
- secondary: {bg: '#3D8BFF', text: '#FFFFFF'},
14
- success: {bg: '#1CD66C', text: '#FFFFFF'},
15
- danger: {bg: '#F84444', text: '#FFFFFF'},
16
- warning: {bg: '#E2B101', text: '#FFFFFF'},
17
- info: {bg: '#307EF1', text: '#FFFFFF'},
18
- light: {bg: '#E8E8E8', text: '#232323'},
19
- disabled: {bg: '#EDEDED', text: '#BEBEBE'},
20
- },
21
- dark: {
22
- primary: {bg: '#FFFFFF', text: '#000000'},
23
- secondary: {bg: '#3D8BFF', text: '#000000'},
24
- success: {bg: '#2FFA86', text: '#000000'},
25
- danger: {bg: '#FF3C3C', text: '#000000'},
26
- warning: {bg: '#F4CC3E', text: '#000000'},
27
- info: {bg: '#2998FF', text: '#000000'},
28
- light: {bg: '#313131', text: '#FFFFFF'},
29
- disabled: {bg: '#292929', text: '#474747'},
30
- },
31
- };
32
-
33
- const colors: {
34
- light: Partial<ThemeColors>;
35
- dark: Partial<ThemeColors>;
36
- } = {
37
- light: {
38
- bg: {
39
- basic: '#FFFFFF',
40
- paper: '#EDEDED',
41
- disabled: '#BEBEBE',
42
- },
43
- role: {
44
- primary: '#1B1B1B',
45
- secondary: '#3D8BFF',
46
- success: baseColors.success,
47
- warning: baseColors.warning,
48
- danger: baseColors.danger,
49
- info: baseColors.info,
50
- accent: baseColors.accent,
51
- link: baseColors.link,
52
- border: '#CCCCCC',
53
- underlay: 'rgba(0, 0, 0, 0.16)',
54
- underlayContrast: 'rgba(0, 0, 0, 0.8)',
55
- },
56
- text: {
57
- basic: '#000000',
58
- label: '#4D4D4D',
59
- placeholder: '#787878',
60
- disabled: '#BEBEBE',
61
- validation: '#DA0000',
62
- contrast: '#FFFFFF',
63
- },
64
- button: buttonColors.light,
65
- },
66
-
67
- dark: {
68
- bg: {
69
- basic: '#242424',
70
- paper: '#1E1D1D',
71
- disabled: '#474747',
72
- },
73
- role: {
74
- primary: '#FFFFFF',
75
- secondary: '#3D8BFF',
76
- success: '#2FFA86',
77
- warning: '#F4CC3E',
78
- danger: '#FF3C3C',
79
- info: '#2998FF',
80
- accent: '#4AE3AD',
81
- link: baseColors.link,
82
- border: '#363636',
83
- underlay: 'rgba(255, 255, 255, 0.16)',
84
- underlayContrast: 'rgba(255, 255, 255, 0.8)',
85
- },
86
- text: {
87
- basic: '#FFFFFF',
88
- label: '#BEBEBE',
89
- placeholder: '#909090',
90
- disabled: '#6D6D6D',
91
- validation: '#FF2C2C',
92
- contrast: '#000000',
93
- },
94
- button: buttonColors.dark,
95
- },
96
- };
97
-
98
- type ThemeColors = {
99
- bg: {
100
- basic: string;
101
- paper: string;
102
- disabled: string;
103
- };
104
- role: {
105
- primary: string;
106
- secondary: string;
107
- success: string;
108
- warning: string;
109
- danger: string;
110
- info: string;
111
- accent: string;
112
- link: string;
113
- border: string;
114
- underlay: string;
115
- underlayContrast: string;
116
- };
117
- text: {
118
- basic: string;
119
- label: string;
120
- placeholder: string;
121
- disabled: string;
122
- validation: string;
123
- contrast: string;
124
- };
125
- button: {
126
- primary: {bg: string; text: string};
127
- secondary: {bg: string; text: string};
128
- success: {bg: string; text: string};
129
- danger: {bg: string; text: string};
130
- warning: {bg: string; text: string};
131
- info: {bg: string; text: string};
132
- light: {bg: string; text: string};
133
- disabled: {bg: string; text: string};
134
- };
135
- };
136
-
137
- const createTheme = (mode: 'light' | 'dark'): ThemeColors => {
138
- const themeColors = colors[mode];
139
-
140
- return {
141
- bg: themeColors.bg as ThemeColors['bg'],
142
- role: themeColors.role as ThemeColors['role'],
143
- text: themeColors.text as ThemeColors['text'],
144
- button: themeColors.button as ThemeColors['button'],
145
- };
146
- };
147
-
148
- export const light = createTheme('light');
149
- export const dark = createTheme('dark');
150
-
151
- export type Colors = typeof light;
@@ -1,26 +0,0 @@
1
- import React from "react";
2
-
3
- type CreateCtx<A> = readonly [
4
- () => A,
5
- React.ProviderExoticComponent<React.ProviderProps<A | undefined>>
6
- ];
7
-
8
- // create context with no upfront defaultValue
9
- // without having to do undefined check all the time
10
- function createCtx<A>(): CreateCtx<A> {
11
- const ctx = React.createContext<A | undefined>(undefined);
12
-
13
- function useCtx(): A {
14
- const c = React.useContext(ctx);
15
-
16
- if (!c) {
17
- throw new Error("useTheme must be inside a ThemeProvider");
18
- }
19
-
20
- return c;
21
- }
22
-
23
- return [useCtx, ctx.Provider] as const;
24
- }
25
-
26
- export default createCtx;
@@ -1,93 +0,0 @@
1
- import React, {cloneElement, type ReactElement} from 'react';
2
- import type {ColorValue, ViewStyle} from 'react-native';
3
- import {
4
- Button,
5
- Image,
6
- Pressable,
7
- Text,
8
- TextInput,
9
- TouchableHighlight,
10
- TouchableOpacity,
11
- TouchableWithoutFeedback,
12
- View,
13
- } from 'react-native';
14
- import {Icon} from '../components/uis/Icon/Icon';
15
-
16
- const getRootElementStyleType = (
17
- element: ReactElement,
18
- ): 'TextStyle' | 'ViewStyle' | 'unknown' => {
19
- if (React.isValidElement(element)) {
20
- if (
21
- element.type === Text ||
22
- element.type === TextInput ||
23
- element.type === Icon
24
- ) {
25
- return 'TextStyle';
26
- }
27
-
28
- if (
29
- element.type === Image ||
30
- element.type === View ||
31
- element.type === Button ||
32
- element.type === TouchableHighlight ||
33
- element.type === TouchableOpacity ||
34
- element.type === Pressable ||
35
- element.type === TouchableWithoutFeedback
36
- ) {
37
- return 'ViewStyle';
38
- }
39
- }
40
-
41
- return 'unknown';
42
- };
43
-
44
- type CloneElemColorsParams = {
45
- /**
46
- * ReactElement to be cloned to shape default colors.
47
- */
48
- element?: ReactElement;
49
- /**
50
- * Text color to be applied.
51
- * If not passed, default color will be applied.
52
- * Invalid if element is ViewStyle.
53
- */
54
- color?: ColorValue;
55
- /**
56
- * Background color to be applied.
57
- * If not passed, default color will be applied.
58
- * Invalid if element is TextStyle.
59
- */
60
- backgroundColor?: ColorValue;
61
- /**
62
- * Extra style to be applied.
63
- */
64
- style?: ViewStyle;
65
- };
66
-
67
- /**
68
- * This function applies default colors to cloned element.
69
- *
70
- * @param {CloneElemColorsParams} params
71
- * @returns {ReactElement} - Cloned element with default colors if exists. Otherwise, null.
72
- */
73
- export const cloneElemWithDefaultColors = ({
74
- element,
75
- color,
76
- backgroundColor,
77
- style,
78
- }: CloneElemColorsParams): ReactElement | null => {
79
- return element
80
- ? cloneElement(element, {
81
- style: [
82
- getRootElementStyleType(element) === 'TextStyle' && {
83
- color,
84
- },
85
- getRootElementStyleType(element) === 'ViewStyle' && {
86
- borderColor: color,
87
- backgroundColor: backgroundColor,
88
- },
89
- {...style, ...(element.props as any).style},
90
- ],
91
- } as any)
92
- : null;
93
- };
@@ -1,2 +0,0 @@
1
- export * from './platform';
2
- export * from './accessibility';
@@ -1,174 +0,0 @@
1
- import React, {useCallback, useEffect, useRef, useState} from 'react';
2
-
3
- /**
4
- * Performance testing utilities for cpk-ui components
5
- */
6
-
7
- export interface PerformanceMetrics {
8
- renderCount: number;
9
- lastRenderTime: number;
10
- averageRenderTime: number;
11
- maxRenderTime: number;
12
- minRenderTime: number;
13
- }
14
-
15
- /**
16
- * Hook to track component render performance
17
- * Useful for development and testing component optimizations
18
- */
19
- export function usePerformanceTest(componentName: string = 'Unknown'): PerformanceMetrics {
20
- const renderCount = useRef(0);
21
- const renderTimes = useRef<number[]>([]);
22
- const lastRenderStart = useRef(performance.now());
23
- const [metrics, setMetrics] = useState<PerformanceMetrics>({
24
- renderCount: 0,
25
- lastRenderTime: 0,
26
- averageRenderTime: 0,
27
- maxRenderTime: 0,
28
- minRenderTime: 0,
29
- });
30
-
31
- useEffect(() => {
32
- const renderEnd = performance.now();
33
- const renderTime = renderEnd - lastRenderStart.current;
34
-
35
- renderCount.current += 1;
36
- renderTimes.current.push(renderTime);
37
-
38
- // Keep only last 100 render times to avoid memory issues
39
- if (renderTimes.current.length > 100) {
40
- renderTimes.current = renderTimes.current.slice(-100);
41
- }
42
-
43
- const averageRenderTime = renderTimes.current.reduce((sum, time) => sum + time, 0) / renderTimes.current.length;
44
- const maxRenderTime = Math.max(...renderTimes.current);
45
- const minRenderTime = Math.min(...renderTimes.current);
46
-
47
- setMetrics({
48
- renderCount: renderCount.current,
49
- lastRenderTime: renderTime,
50
- averageRenderTime,
51
- maxRenderTime,
52
- minRenderTime,
53
- });
54
-
55
- // Log performance if it's slow (over 16ms for 60fps)
56
- if (renderTime > 16) {
57
- console.warn(`[Performance] ${componentName} slow render: ${renderTime.toFixed(2)}ms`);
58
- }
59
-
60
- lastRenderStart.current = performance.now();
61
- });
62
-
63
- return metrics;
64
- }
65
-
66
- /**
67
- * Hook to measure style calculation performance
68
- */
69
- export function useStylePerformanceTest() {
70
- const measureStyleCalculation = useCallback((
71
- styleFn: () => any,
72
- styleName: string = 'Style'
73
- ) => {
74
- const start = performance.now();
75
- const result = styleFn();
76
- const end = performance.now();
77
- const duration = end - start;
78
-
79
- if (duration > 1) {
80
- console.warn(`[Style Performance] ${styleName} calculation took ${duration.toFixed(2)}ms`);
81
- }
82
-
83
- return result;
84
- }, []);
85
-
86
- return measureStyleCalculation;
87
- }
88
-
89
- /**
90
- * Hook to detect unnecessary re-renders
91
- */
92
- export function useRenderTracker(props: Record<string, any>, componentName: string = 'Component') {
93
- const prevProps = useRef<Record<string, any> | undefined>(undefined);
94
- const renderCount = useRef(0);
95
-
96
- useEffect(() => {
97
- renderCount.current += 1;
98
-
99
- if (prevProps.current) {
100
- const changedProps: string[] = [];
101
-
102
- Object.keys(props).forEach(key => {
103
- if (prevProps.current![key] !== props[key]) {
104
- changedProps.push(key);
105
- }
106
- });
107
-
108
- if (changedProps.length === 0) {
109
- console.warn(`[Render Tracker] ${componentName} re-rendered without prop changes (render #${renderCount.current})`);
110
- } else if (changedProps.length > 0) {
111
- console.log(`[Render Tracker] ${componentName} re-rendered due to: ${changedProps.join(', ')}`);
112
- }
113
- }
114
-
115
- prevProps.current = props;
116
- });
117
-
118
- return renderCount.current;
119
- }
120
-
121
- /**
122
- * Hook to measure memory usage (approximation)
123
- */
124
- export function useMemoryTracker(componentName: string = 'Component') {
125
- const [memoryUsage, setMemoryUsage] = useState<number>(0);
126
-
127
- useEffect(() => {
128
- // Only available in some browsers and development
129
- if ('memory' in performance && (performance as any).memory) {
130
- const memory = (performance as any).memory;
131
- const usedJSHeapSize = memory.usedJSHeapSize / 1024 / 1024; // Convert to MB
132
- setMemoryUsage(usedJSHeapSize);
133
-
134
- if (usedJSHeapSize > 50) { // Warn if over 50MB
135
- console.warn(`[Memory] ${componentName} - High memory usage: ${usedJSHeapSize.toFixed(2)}MB`);
136
- }
137
- }
138
- });
139
-
140
- return memoryUsage;
141
- }
142
-
143
- /**
144
- * Component wrapper for performance testing
145
- */
146
- export function withPerformanceTest<P extends object>(
147
- Component: React.ComponentType<P>,
148
- componentName?: string
149
- ): React.ComponentType<P> {
150
- const PerformanceTestWrapper = (props: P) => {
151
- const name = componentName || Component.displayName || Component.name || 'Unknown';
152
- const metrics = usePerformanceTest(name);
153
- const renderCount = useRenderTracker(props as Record<string, any>, name);
154
- const memoryUsage = useMemoryTracker(name);
155
-
156
- // Log metrics every 10 renders
157
- useEffect(() => {
158
- if (renderCount % 10 === 0 && renderCount > 0) {
159
- console.log(`[Performance Summary] ${name}:`, {
160
- renders: renderCount,
161
- avgRenderTime: `${metrics.averageRenderTime.toFixed(2)}ms`,
162
- maxRenderTime: `${metrics.maxRenderTime.toFixed(2)}ms`,
163
- memoryUsage: `${memoryUsage.toFixed(2)}MB`,
164
- });
165
- }
166
- }, [renderCount, metrics, memoryUsage, name]);
167
-
168
- return React.createElement(Component, props);
169
- };
170
-
171
- PerformanceTestWrapper.displayName = `withPerformanceTest(${componentName || Component.displayName || Component.name})`;
172
-
173
- return PerformanceTestWrapper;
174
- }
@@ -1,69 +0,0 @@
1
- import {Platform} from 'react-native';
2
-
3
- /**
4
- * Safely check if current platform is web
5
- * Prevents undefined Platform.OS errors during testing
6
- */
7
- export function isWeb(): boolean {
8
- try {
9
- return Platform.OS === 'web';
10
- } catch {
11
- return false;
12
- }
13
- }
14
-
15
- /**
16
- * Safely check if current platform is iOS
17
- */
18
- export function isIOS(): boolean {
19
- try {
20
- return Platform.OS === 'ios';
21
- } catch {
22
- return false;
23
- }
24
- }
25
-
26
- /**
27
- * Safely check if current platform is Android
28
- */
29
- export function isAndroid(): boolean {
30
- try {
31
- return Platform.OS === 'android';
32
- } catch {
33
- return false;
34
- }
35
- }
36
-
37
- /**
38
- * Safe wrapper for Platform.select
39
- * Provides fallback when Platform.OS is undefined
40
- */
41
- export function safePlatformSelect<T>(options: {
42
- web?: T;
43
- ios?: T;
44
- android?: T;
45
- native?: T;
46
- default?: T;
47
- }): T | undefined {
48
- try {
49
- const platformSelect = Platform.select(options);
50
- return platformSelect ?? options.default;
51
- } catch {
52
- return options.default;
53
- }
54
- }
55
-
56
- /**
57
- * Get safe platform-specific values
58
- */
59
- export function getPlatformValue<T>(
60
- webValue: T,
61
- nativeValue: T,
62
- fallback: T,
63
- ): T {
64
- try {
65
- return Platform.OS === 'web' ? webValue : nativeValue;
66
- } catch {
67
- return fallback;
68
- }
69
- }
@@ -1,38 +0,0 @@
1
- import {Colors, light} from './colors';
2
-
3
- // Internal base theme type for cpk-ui components
4
- export type CpkThemeBase = Colors & {
5
- isPortrait?: boolean;
6
- isDesktop?: boolean;
7
- isTablet?: boolean;
8
- isMobile?: boolean;
9
- };
10
-
11
- // Empty interface for module augmentation (like @emotion/react's Theme)
12
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
13
- export interface CpkTheme extends CpkThemeBase {}
14
-
15
- type RecursivePartial<T> = {
16
- [P in keyof T]?: RecursivePartial<T[P]>;
17
- };
18
-
19
- export type CpkThemeParams = RecursivePartial<CpkThemeBase>;
20
-
21
- export type ThemeObjParams = {
22
- bg: Partial<Colors['bg']>;
23
- role: Partial<Colors['role']>;
24
- text: Partial<Colors['text']>;
25
- button: Partial<Colors['button']>;
26
- };
27
-
28
- export interface ThemeParam {
29
- light?: Partial<ThemeObjParams & any>;
30
- dark?: Partial<ThemeObjParams & any>;
31
- }
32
-
33
- export const isEmptyObject = (param: any): boolean =>
34
- Object.keys(param).length === 0 && param.constructor === Object;
35
-
36
- export const getTheme = (theme?: CpkTheme): CpkThemeBase => {
37
- return (isEmptyObject(theme) || theme === undefined ? light : theme) as CpkThemeBase;
38
- };