dhre-component-lib 0.1.6 → 0.1.8

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 (145) hide show
  1. package/{src/components/Badge → dist}/Badge.module.scss +0 -1
  2. package/{src/components/BreadCrumb → dist}/Breadcrumb.module.scss +0 -3
  3. package/{src/components/Button → dist}/Button.module.scss +3 -16
  4. package/{src/components/CircularProgress → dist}/CircularProgress.module.scss +0 -1
  5. package/dist/assets/output-4Fi7j5sB.css +247 -0
  6. package/dist/components/Avatar/Avatar.d.ts +9 -0
  7. package/dist/components/Avatar/Avatar.test.d.ts +1 -0
  8. package/dist/components/Avatar/index.d.ts +1 -0
  9. package/dist/components/Badge/Badge.d.ts +8 -0
  10. package/dist/components/Badge/Badge.test.d.ts +1 -0
  11. package/dist/components/Badge/index.d.ts +1 -0
  12. package/dist/components/BreadCrumb/BreadCrumb.d.ts +14 -0
  13. package/dist/components/BreadCrumb/BreadCrumb.test.d.ts +1 -0
  14. package/dist/components/BreadCrumb/index.d.ts +1 -0
  15. package/dist/components/Button/Button.d.ts +10 -0
  16. package/dist/components/Button/Button.test.d.ts +1 -0
  17. package/dist/components/Button/index.d.ts +1 -0
  18. package/dist/components/Checkbox/Checkbox.d.ts +11 -0
  19. package/dist/components/Checkbox/Checkbox.test.d.ts +1 -0
  20. package/dist/components/Checkbox/index.d.ts +1 -0
  21. package/dist/components/CircularProgress/CircularProgress.d.ts +10 -0
  22. package/dist/components/CircularProgress/CircularProgress.test.d.ts +1 -0
  23. package/dist/components/CircularProgress/index.d.ts +1 -0
  24. package/dist/components/Divider/Divider.d.ts +8 -0
  25. package/dist/components/Divider/Divider.test.d.ts +1 -0
  26. package/dist/components/Divider/index.d.ts +1 -0
  27. package/dist/components/Enum.d.ts +17 -0
  28. package/dist/components/InputTextField/InputTextField.d.ts +16 -0
  29. package/dist/components/InputTextField/InputTextField.test.d.ts +1 -0
  30. package/dist/components/InputTextField/index.d.ts +1 -0
  31. package/dist/components/Link/Link.d.ts +10 -0
  32. package/dist/components/Link/Link.test.d.ts +1 -0
  33. package/dist/components/Link/index.d.ts +1 -0
  34. package/dist/components/Map/Directions.d.ts +13 -0
  35. package/dist/components/Map/GoogleMap.d.ts +12 -0
  36. package/dist/components/Map/GoogleMapsLoader.d.ts +4 -0
  37. package/dist/components/Modal/Modal.d.ts +10 -0
  38. package/dist/components/Modal/Modal.test.d.ts +1 -0
  39. package/dist/components/Modal/index.d.ts +1 -0
  40. package/dist/components/Notification/Notification.d.ts +10 -0
  41. package/dist/components/Notification/Notification.test.d.ts +1 -0
  42. package/dist/components/Notification/index.d.ts +1 -0
  43. package/dist/components/OtpInput/OtpInput.d.ts +14 -0
  44. package/dist/components/OtpInput/OtpInput.test.d.ts +1 -0
  45. package/dist/components/OtpInput/index.d.ts +1 -0
  46. package/dist/components/PdfView/PdfView.d.ts +18 -0
  47. package/dist/components/PdfView/PdfView.test.d.ts +1 -0
  48. package/dist/components/PdfView/index.d.ts +1 -0
  49. package/dist/components/Progress/Progress.d.ts +12 -0
  50. package/dist/components/Progress/Progress.test.d.ts +1 -0
  51. package/dist/components/Progress/index.d.ts +1 -0
  52. package/dist/components/RadioButton/RadioButton.d.ts +14 -0
  53. package/dist/components/RadioButton/RadioButton.test.d.ts +1 -0
  54. package/dist/components/RadioButton/index.d.ts +1 -0
  55. package/dist/components/Switch/Switch.d.ts +13 -0
  56. package/dist/components/Switch/Switch.test.d.ts +1 -0
  57. package/dist/components/Switch/index.d.ts +1 -0
  58. package/dist/components/Tag/Tag.d.ts +9 -0
  59. package/dist/components/Tag/Tag.test.d.ts +1 -0
  60. package/dist/components/Tag/index.d.ts +1 -0
  61. package/dist/components/Tooltip/Tooltip.d.ts +9 -0
  62. package/dist/components/Tooltip/Tooltip.test.d.ts +1 -0
  63. package/dist/components/Tooltip/index.d.ts +1 -0
  64. package/dist/dist/styles.css +2 -0
  65. package/dist/dist/styles.css.map +1 -0
  66. package/dist/index.d.ts +15 -0
  67. package/dist/index.esm.js +9323 -0
  68. package/dist/index.esm.js.map +1 -0
  69. package/dist/index.js +9359 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/theme/colors.d.ts +1 -0
  72. package/package.json +17 -7
  73. package/src/__mocks__/styleMock.js +0 -1
  74. package/src/components/Avatar/Avatar.test.tsx +0 -53
  75. package/src/components/Avatar/Avatar.tsx +0 -28
  76. package/src/components/Avatar/index.ts +0 -1
  77. package/src/components/Badge/Badge.test.tsx +0 -59
  78. package/src/components/Badge/Badge.tsx +0 -25
  79. package/src/components/Badge/index.ts +0 -1
  80. package/src/components/BreadCrumb/BreadCrumb.test.tsx +0 -90
  81. package/src/components/BreadCrumb/BreadCrumb.tsx +0 -45
  82. package/src/components/BreadCrumb/index.ts +0 -1
  83. package/src/components/Button/Button.test.tsx +0 -49
  84. package/src/components/Button/Button.tsx +0 -29
  85. package/src/components/Button/index.ts +0 -1
  86. package/src/components/Checkbox/Checkbox.test.tsx +0 -93
  87. package/src/components/Checkbox/Checkbox.tsx +0 -35
  88. package/src/components/Checkbox/index.ts +0 -1
  89. package/src/components/CircularProgress/CircularProgress.test.tsx +0 -39
  90. package/src/components/CircularProgress/CircularProgress.tsx +0 -37
  91. package/src/components/CircularProgress/index.ts +0 -1
  92. package/src/components/Divider/Divider.test.tsx +0 -44
  93. package/src/components/Divider/Divider.tsx +0 -24
  94. package/src/components/Divider/index.ts +0 -1
  95. package/src/components/Enum.ts +0 -19
  96. package/src/components/InputTextField/InputTextField.test.tsx +0 -118
  97. package/src/components/InputTextField/InputTextField.tsx +0 -48
  98. package/src/components/InputTextField/index.ts +0 -1
  99. package/src/components/Link/Link.test.tsx +0 -55
  100. package/src/components/Link/Link.tsx +0 -33
  101. package/src/components/Link/index.ts +0 -1
  102. package/src/components/Map/Directions.tsx +0 -36
  103. package/src/components/Map/GoogleMap.tsx +0 -186
  104. package/src/components/Map/GoogleMapsLoader.tsx +0 -12
  105. package/src/components/Modal/Modal.test.tsx +0 -74
  106. package/src/components/Modal/Modal.tsx +0 -39
  107. package/src/components/Modal/index.ts +0 -1
  108. package/src/components/Notification/Notification.test.tsx +0 -53
  109. package/src/components/Notification/Notification.tsx +0 -42
  110. package/src/components/Notification/index.ts +0 -1
  111. package/src/components/OtpInput/OtpInput.test.tsx +0 -53
  112. package/src/components/OtpInput/OtpInput.tsx +0 -137
  113. package/src/components/OtpInput/index.ts +0 -1
  114. package/src/components/PdfView/PdfView.test.tsx +0 -52
  115. package/src/components/PdfView/PdfView.tsx +0 -116
  116. package/src/components/PdfView/index.ts +0 -1
  117. package/src/components/Progress/Progress.test.tsx +0 -43
  118. package/src/components/Progress/Progress.tsx +0 -35
  119. package/src/components/Progress/index.ts +0 -1
  120. package/src/components/RadioButton/RadioButton.test.tsx +0 -56
  121. package/src/components/RadioButton/RadioButton.tsx +0 -43
  122. package/src/components/RadioButton/index.ts +0 -1
  123. package/src/components/Switch/Switch.test.tsx +0 -83
  124. package/src/components/Switch/Switch.tsx +0 -38
  125. package/src/components/Switch/index.ts +0 -1
  126. package/src/components/Tag/Tag.css +0 -14
  127. package/src/components/Tag/Tag.test.tsx +0 -61
  128. package/src/components/Tag/Tag.tsx +0 -19
  129. package/src/components/Tag/index.ts +0 -1
  130. package/src/components/Tooltip/Tooltip.test.tsx +0 -68
  131. package/src/components/Tooltip/Tooltip.tsx +0 -38
  132. package/src/components/Tooltip/index.ts +0 -1
  133. package/src/components/index.ts +0 -15
  134. package/src/index.ts +0 -1
  135. package/src/theme/colors.ts +0 -3
  136. package/src/typings.d.ts +0 -1
  137. /package/{src/components/Map → dist}/GoogleMap.module.scss +0 -0
  138. /package/{src/components/Modal → dist}/Modal.module.scss +0 -0
  139. /package/{src/components/Notification → dist}/Notification.module.scss +0 -0
  140. /package/{src/components/OtpInput → dist}/OtpInput.module.scss +0 -0
  141. /package/{src/components/PdfView → dist}/PdfView.module.scss +0 -0
  142. /package/{src/components/Tooltip → dist}/Tooltip.module.scss +0 -0
  143. /package/{src/theme/colors → dist}/colors.scss +0 -0
  144. /package/{src/components/Map/index.ts → dist/components/Map/index.d.ts} +0 -0
  145. /package/{src/theme/Typography → dist}/typography.scss +0 -0
@@ -1,39 +0,0 @@
1
- import React from "react";
2
- import styles from './Modal.module.scss';
3
-
4
- interface ModalProps {
5
- isOpen: boolean;
6
- onClose: () => void;
7
- children: React.ReactNode;
8
- modalOverlayClassname?: string;
9
- modalContentClassname?: string;
10
- }
11
-
12
- const Modal: React.FC<ModalProps> = ({
13
- isOpen,
14
- onClose,
15
- children,
16
- modalOverlayClassname = '',
17
- modalContentClassname = ''
18
- }) => {
19
- if (!isOpen) return null;
20
-
21
- const handleOverlayClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
22
- if (event.target === event.currentTarget) {
23
- onClose();
24
- }
25
- };
26
-
27
- return (
28
- <button
29
- className={`${styles.modalOverlay} ${modalOverlayClassname}`}
30
- onClick={handleOverlayClick}
31
- >
32
- <div className={`${styles.modalContent} ${modalContentClassname}`}>
33
- {children}
34
- </div>
35
- </button>
36
- );
37
- };
38
-
39
- export default Modal;
@@ -1 +0,0 @@
1
- export { default } from "./Modal";
@@ -1,53 +0,0 @@
1
- import React from 'react';
2
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3
- import Notification, { NotificationProps } from './Notification';
4
-
5
- describe('Notification Component', () => {
6
- const defaultProps: NotificationProps = {
7
- message: 'Test Message',
8
- severity: 'info',
9
- autoHideDuration: 6000,
10
- onClose: jest.fn(),
11
- };
12
-
13
- const renderNotification = (props: Partial<NotificationProps> = {}) => {
14
- return render(<Notification {...defaultProps} {...props} />);
15
- };
16
-
17
- test('renders notification with the correct message', () => {
18
- render(<Notification message="Test Message" severity="info" />);
19
-
20
- // Check if the element exists by querying it
21
- const notificationElement = screen.getByText('Test Message');
22
- expect(notificationElement).not.toBeNull(); // Equivalent to `toBeInTheDocument`
23
-
24
- // Alternatively, check for the presence of the role or className
25
- const alertElement = screen.getByRole('alert');
26
- expect(alertElement.className).toContain('info'); // Check if className includes "info"
27
- });
28
-
29
- test('calls onClose when the notification is clicked', () => {
30
- const onClose = jest.fn();
31
- renderNotification({ onClose });
32
-
33
- fireEvent.click(screen.getByRole('alert'));
34
-
35
- expect(onClose).toHaveBeenCalled();
36
- });
37
-
38
- test('calls onClose when the close button is clicked', () => {
39
- const onClose = jest.fn();
40
- renderNotification({ onClose });
41
-
42
- fireEvent.click(screen.getByLabelText('Close notification'));
43
-
44
- expect(onClose).toHaveBeenCalledWith(expect.anything(), 'close');
45
- });
46
-
47
- test('calls onClose after autoHideDuration expires', async () => {
48
- const onClose = jest.fn();
49
- renderNotification({ onClose, autoHideDuration: 1000 });
50
-
51
- await waitFor(() => expect(onClose).toHaveBeenCalledWith(expect.anything(), 'timeout'), { timeout: 1500 });
52
- });
53
- });
@@ -1,42 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import './Notification.module.scss';
3
- export interface NotificationProps {
4
- message: string;
5
- severity?: 'error' | 'warning' | 'info' | 'success';
6
- autoHideDuration?: number;
7
- onClose?: (event: React.SyntheticEvent<any> | Event, reason?: string) => void;
8
- }
9
-
10
- const Notification: React.FC<NotificationProps> = ({
11
- message,
12
- severity = 'info',
13
- autoHideDuration = 6000,
14
- onClose,
15
- }) => {
16
- useEffect(() => {
17
- if (autoHideDuration && onClose) {
18
- const timer = setTimeout(() => {
19
- onClose(new Event('timeout'), 'timeout');
20
- }, autoHideDuration);
21
-
22
- return () => clearTimeout(timer);
23
- }
24
- }, [autoHideDuration, onClose]);
25
-
26
- const handleClose = (event: React.SyntheticEvent<any> | Event, reason?: string) => {
27
- if (onClose) {
28
- onClose(event, reason);
29
- }
30
- };
31
-
32
- return (
33
- <div className={`notification ${severity}`} onClick={(e) => handleClose(e)} role="alert">
34
- <div className="notification-message">{message}</div>
35
- <button className="close-button" onClick={(e) => handleClose(e, 'close')} aria-label="Close notification">
36
- &times;
37
- </button>
38
- </div>
39
- );
40
- };
41
-
42
- export default Notification;
@@ -1 +0,0 @@
1
- export { default } from "./Notification";
@@ -1,53 +0,0 @@
1
- import React from 'react';
2
- import { render, fireEvent, screen } from '@testing-library/react';
3
- import OTPInput from './OtpInput';
4
- import '@testing-library/jest-dom';
5
-
6
- describe('OTPInput Component', () => {
7
- it('renders the correct number of input fields based on the length prop', () => {
8
- render(
9
- <OTPInput
10
- length={4}
11
- onChange={() => {}}
12
- onResend={() => {}}
13
- resendText="Resend OTP"
14
- />
15
- );
16
- const inputs = screen.getAllByRole('textbox');
17
- expect(inputs).toHaveLength(4);
18
- });
19
- it('calls onChange prop when input changes', () => {
20
- const handleChange = jest.fn();
21
- render(<OTPInput length={4} onChange={handleChange} onResend={() => {}} resendText="Resend OTP" />);
22
- const inputs = screen.getAllByRole('textbox');
23
- fireEvent.change(inputs[0], { target: { value: '1' } });
24
- expect(handleChange).toHaveBeenCalledWith('1');
25
- });
26
-
27
- it('calls onResend prop when the resend button is clicked', async () => {
28
- const handleResend = jest.fn();
29
- render(<OTPInput length={4} onChange={() => {}} onResend={handleResend} resendText="Resend OTP" resendDelay={0} />);
30
- const resendButton = screen.getByRole('button', { name: /resend otp/i });
31
- fireEvent.click(resendButton);
32
- expect(handleResend).toHaveBeenCalled();
33
- });
34
- it('displays error text when the error prop is true', () => {
35
- const errorMessage = 'Invalid OTP';
36
- render(<OTPInput length={4} onChange={() => {}} onResend={() => {}} resendText="Resend OTP" error={true} errorText={errorMessage} />);
37
- const errorElement = screen.getByText(errorMessage);
38
- expect(errorElement).toBeInTheDocument();
39
- });
40
- it('changes border color to red when the error prop is true', () => {
41
- render(
42
- <OTPInput
43
- length={4}
44
- onChange={() => {}}
45
- onResend={() => {}}
46
- resendText="Resend OTP"
47
- error={true}
48
- />
49
- );
50
- const firstInput = screen.getByTestId('otp-input-0');
51
- expect(firstInput).toHaveStyle('border: 1px solid #EB0542');
52
- });
53
- });
@@ -1,137 +0,0 @@
1
- import React, { useEffect, useState } from "react";
2
- import "./OtpInput.module.scss";
3
- interface OTPInputProps {
4
- length?: number;
5
- // eslint-disable-next-line no-unused-vars
6
- onChange: (otp: string) => void;
7
- autoFocus?: boolean;
8
- onResend: () => void;
9
- resendDelay?: number;
10
- error?: boolean;
11
- errorText?: string;
12
- resendText: string;
13
- }
14
-
15
- const OTPInput: React.FC<OTPInputProps> = ({
16
- length = 4,
17
- onChange,
18
- autoFocus = false,
19
- onResend,
20
- resendDelay = 60,
21
- error = false,
22
- errorText,
23
- resendText,
24
- }) => {
25
- const [otp, setOtp] = useState<string[]>(Array(length).fill(""));
26
- const [timer, setTimer] = useState<number>(resendDelay);
27
- const [isComplete, setIsComplete] = useState<boolean>(false);
28
-
29
- useEffect(() => {
30
- const countdown = setInterval(() => {
31
- setTimer((prevTimer) => (prevTimer > 0 ? prevTimer - 1 : 0));
32
- }, 1000);
33
-
34
- return () => clearInterval(countdown);
35
- }, []);
36
- const handleChange = (value: string, index: number) => {
37
- if (isNaN(Number(value))) return;
38
-
39
- const newOtp = [...otp];
40
- newOtp[index] = value;
41
- setOtp(newOtp);
42
- onChange(newOtp.join(""));
43
-
44
- if (value && index < length - 1) {
45
- const nextInput = document.getElementById(
46
- `otp-input-${index + 1}`
47
- ) as HTMLInputElement;
48
- if (nextInput) {
49
- nextInput.focus();
50
- }
51
- }
52
- };
53
-
54
- const handleKeyDown = (
55
- e: React.KeyboardEvent<HTMLInputElement>,
56
- index: number
57
- ) => {
58
- if (e.key === "Backspace" && !otp[index] && index > 0) {
59
- const prevInput = document.getElementById(
60
- `otp-input-${index - 1}`
61
- ) as HTMLInputElement;
62
- if (prevInput) {
63
- prevInput.focus();
64
- }
65
- }
66
- };
67
-
68
- const handleResendClick = () => {
69
- onResend();
70
- setOtp(Array(length).fill(""));
71
- setTimer(resendDelay);
72
- setIsComplete(false);
73
- };
74
-
75
- useEffect(() => {
76
- setIsComplete(otp.every((digit) => digit !== ""));
77
- }, [otp]);
78
-
79
- useEffect(() => {
80
- if (error) {
81
- setTimer(0);
82
- }
83
- }, [error]);
84
-
85
- function getReadableStatus() {
86
- if (error) {
87
- return "#EB0542";
88
- }
89
- return isComplete ? "#00B578" : "#A7A7A7";
90
- }
91
- return (
92
- <div className="otpMainContainer">
93
- <div className="otpInputDiv">
94
- {Array(length)
95
- .fill("")
96
- .map((_, index) => (
97
- <input
98
- key={index}
99
- type="text"
100
- id={`otp-input-${index}`}
101
- value={otp[index]}
102
- data-testid={`otp-input-${index}`}
103
- role="textbox"
104
- onChange={(e) => handleChange(e.target.value, index)}
105
- onKeyDown={(e) => handleKeyDown(e, index)}
106
- maxLength={1}
107
- style={{ border: `1px solid ${getReadableStatus()}` }}
108
- className="otpInput"
109
- autoFocus={autoFocus && index === 0}
110
- />
111
- ))}
112
- </div>
113
- <div className="resendContainer">
114
- {error ? (
115
- <div className="errorText">{errorText}</div>
116
- ) : (
117
- <div className="timerText">
118
- {timer > 0 ? `00:${timer} secs` : ""}
119
- </div>
120
- )}
121
- <button
122
- onClick={handleResendClick}
123
- disabled={timer > 0}
124
- style={{
125
- border: "none",
126
- background: "none",
127
- cursor: timer > 0 ? "not-allowed" : "pointer",
128
- }}
129
- >
130
- <div className="resendText">{resendText}</div>
131
- </button>
132
- </div>
133
- </div>
134
- );
135
- };
136
-
137
- export default OTPInput;
@@ -1 +0,0 @@
1
- export { default } from "./OtpInput";
@@ -1,52 +0,0 @@
1
- import React from 'react';
2
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import PdfView from './PdfView';
5
-
6
- // Dummy base64 content for testing
7
- const validBase64Content = 'JVBERi0xLjQKJeLjz9MNCjEgMCBvYmoKPDwvTGluay9QYWdlcyAyIDAgUj4+CnN0YXJ0eHJlZgoyNCAwIFIKZW5kb2JqCjEgMCBvYmoKPDwvTGluay9QYWdlcyAyIDAgUj4+CnN0YXJ0eHJlZgo2IDAgUgo+';
8
- const invalidBase64Content = 'invalid base64 content';
9
- const errorText = 'Failed to load PDF';
10
- const buttonText = 'View PDF';
11
- const loadingText = 'Loading...';
12
-
13
- // Save the original implementation of createObjectURL
14
- const originalCreateObjectURL = global.URL.createObjectURL;
15
-
16
- describe('PdfView Component', () => {
17
- beforeAll(() => {
18
- // Mock URL.createObjectURL directly
19
- global.URL.createObjectURL = jest.fn(() => 'mock-url');
20
- });
21
-
22
- afterAll(() => {
23
- // Restore the original implementation
24
- global.URL.createObjectURL = originalCreateObjectURL;
25
- });
26
-
27
- it('renders correctly with default props', () => {
28
- render(<PdfView content={validBase64Content} />);
29
- expect(screen.getByText(buttonText)).toBeInTheDocument();
30
- });
31
-
32
- it('shows error message if content is invalid', () => {
33
- render(<PdfView content={invalidBase64Content} />);
34
- expect(screen.getByText(errorText)).toBeInTheDocument();
35
- });
36
-
37
- it('applies the provided class names', () => {
38
- const className = 'custom-class';
39
- render(<PdfView content={validBase64Content} className={className} />);
40
- expect(screen.getByText(buttonText).parentElement).toHaveClass(className);
41
- });
42
-
43
-
44
-
45
- it('does not show spinner or loading text if isLoading is false', () => {
46
- render(<PdfView content={validBase64Content} />);
47
-
48
- // The component should not be in a loading state initially
49
- expect(screen.queryByTestId('spinnertest')).not.toBeInTheDocument();
50
- expect(screen.queryByText(loadingText)).not.toBeInTheDocument();
51
- });
52
- });
@@ -1,116 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import styles from './PdfView.module.scss';
3
-
4
- export interface PdfViewerProps {
5
- content: string;
6
- contentType?: string;
7
- buttonText?: string;
8
- loadingText?: string;
9
- errorText?: string;
10
- cleanUpDelay?: number;
11
- buttonVariant?: "text" | "outlined" | "contained";
12
- buttonColor?: "inherit" | "primary" | "secondary" | "error" | "info" | "success" | "warning";
13
- buttonSize?: "small" | "medium" | "large";
14
- showLoadingSpinner?: boolean;
15
- spinnerSize?: number;
16
- spinnerColor?: "inherit" | "primary" | "secondary";
17
- className?: string;
18
- }
19
-
20
- const PdfView: React.FC<PdfViewerProps> = ({
21
- content,
22
- contentType = "application/pdf",
23
- buttonText = "View PDF",
24
- loadingText = "Loading...",
25
- errorText = "Failed to load PDF",
26
- cleanUpDelay = 1000,
27
- buttonVariant = "contained",
28
- buttonColor = "primary",
29
- buttonSize = "medium",
30
- showLoadingSpinner = false,
31
- spinnerSize = 24,
32
- spinnerColor = "primary",
33
- className = "",
34
- }) => {
35
- const [isLoading, setIsLoading] = React.useState(false);
36
- const [isError, setIsError] = React.useState(false);
37
- const [errorMsg, setErrorMsg] = React.useState(errorText);
38
-
39
- useEffect(() => {
40
- if (btoa(atob(content)) !== content) {
41
- setIsError(true);
42
- }
43
- }, [content]);
44
-
45
- const base64ToBlob = (content: string, contentType: string = "application/pdf"): Blob | null => {
46
- try {
47
- const byteCharacters = atob(content);
48
- const byteArray = new Uint8Array(byteCharacters.length);
49
-
50
- for (let i = 0; i < byteCharacters.length; i++) {
51
- byteArray[i] = byteCharacters.charCodeAt(i);
52
- }
53
-
54
- return new Blob([byteArray], { type: contentType });
55
- } catch (error) {
56
- setIsError(true);
57
- setErrorMsg("Invalid base64 string:");
58
- return null;
59
- }
60
- };
61
-
62
- const handleViewPdf = async () => {
63
- setIsLoading(true);
64
- setIsError(false);
65
- const blob = base64ToBlob(content, contentType);
66
- if (blob) {
67
- const url = URL.createObjectURL(blob);
68
-
69
- window.open(url, "_blank");
70
-
71
- setTimeout(() => {
72
- URL.revokeObjectURL(url);
73
- }, cleanUpDelay);
74
- setIsLoading(false);
75
- } else {
76
- setIsLoading(false);
77
- setIsError(true);
78
- setErrorMsg("Failed to create Blob from base64 string.");
79
- }
80
- };
81
-
82
- const buttonClass = `
83
- ${styles.button}
84
- ${styles[`button${buttonVariant.charAt(0).toUpperCase() + buttonVariant.slice(1)}`]}
85
- ${styles[`button${buttonColor.charAt(0).toUpperCase() + buttonColor.slice(1)}`]}
86
- ${styles[`button${buttonSize.charAt(0).toUpperCase() + buttonSize.slice(1)}`]}
87
- `;
88
-
89
- const spinnerClass = `${styles.spinner} ${styles.spinnerInner}`;
90
-
91
- return (
92
- <div className={`${styles.container} ${className}`}>
93
- {isLoading && showLoadingSpinner && (
94
- <div
95
- data-testid="spinnertest"
96
- className={spinnerClass}
97
- style={{ width: spinnerSize, height: spinnerSize, borderColor: spinnerColor }}
98
- >
99
- <div className={styles.spinnerInner}></div>
100
- </div>
101
- )}
102
- {isError && <p className={styles.errorText}>{errorMsg}</p>}
103
- {!isLoading && !isError && (
104
- <button
105
- onClick={handleViewPdf}
106
- className={buttonClass}
107
- >
108
- {buttonText}
109
- </button>
110
- )}
111
- {isLoading && !showLoadingSpinner && <p>{loadingText}</p>}
112
- </div>
113
- );
114
- };
115
-
116
- export default PdfView;
@@ -1 +0,0 @@
1
- export { default } from "./PdfView";
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import Progress from './Progress';
5
-
6
- describe('Progress Component', () => {
7
- it('renders the progress bar with correct percentage width', () => {
8
- render(<Progress value={50} max={100} barClassName="progress-bar" />);
9
- const progressBar = screen.getByTestId('progress-bar');
10
- expect(progressBar).toHaveStyle('width: 50%');
11
- });
12
-
13
- it('renders the label when provided', () => {
14
- render(<Progress value={30} max={100} label="Loading" labelClassName="label-class" />);
15
- expect(screen.getByText('Loading')).toHaveClass('label-class');
16
- });
17
-
18
- it('does not render the label when not provided', () => {
19
- render(<Progress value={30} max={100} />);
20
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
21
- });
22
-
23
-
24
-
25
- it('handles zero values correctly', () => {
26
- render(<Progress value={0} max={100} barClassName="progress-bar" />);
27
- const progressBar = screen.getByTestId('progress-bar');
28
- expect(progressBar).toHaveStyle('width: 0%');
29
- });
30
-
31
- it('handles max values correctly', () => {
32
- render(<Progress value={100} max={100} barClassName="progress-bar" />);
33
- const progressBar = screen.getByTestId('progress-bar');
34
- expect(progressBar).toHaveStyle('width: 100%');
35
- });
36
-
37
- it('handles values greater than max', () => {
38
- render(<Progress value={150} max={100} barClassName="progress-bar" />);
39
- const progressBar = screen.getByTestId('progress-bar');
40
- expect(progressBar).toHaveStyle('width: 150%'); // Matches the component's behavior
41
- });
42
-
43
- })
@@ -1,35 +0,0 @@
1
- import React from 'react';
2
-
3
- export interface ProgressProps {
4
- value: number;
5
- max: number;
6
- className?: string;
7
- barContainerClassName?: string;
8
- barClassName?: string;
9
- labelClassName?: string;
10
- label?: string;
11
- }
12
-
13
- const Progress: React.FC<ProgressProps> = ({
14
- value,
15
- max,
16
- className = '',
17
- barContainerClassName = '',
18
- barClassName = '',
19
- labelClassName = '',
20
- label,
21
- ...rest
22
- }) => {
23
- const percentage = (value / max) * 100;
24
-
25
- return (
26
- <div className={className} {...rest}>
27
- {label && <div className={labelClassName}>{label}</div>}
28
- <div className={barContainerClassName}>
29
- <div data-testid="progress-bar" className={barClassName} style={{ width: `${percentage}%` }} />
30
- </div>
31
- </div>
32
- );
33
- };
34
-
35
- export default Progress;
@@ -1 +0,0 @@
1
- export { default } from "./Progress";
@@ -1,56 +0,0 @@
1
- import React from 'react';
2
- import { render, screen, fireEvent } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import CustomRadioButton from './RadioButton';
5
-
6
- describe('CustomRadioButton', () => {
7
- it('should render with given props', () => {
8
- render(
9
- <CustomRadioButton
10
- name="testName"
11
- value="testValue"
12
- checked={true}
13
- onChange={() => {}}
14
- className="custom-class"
15
- inputClassName="input-class"
16
- labelClassName="label-class"
17
- id="radio1"
18
- />
19
- );
20
-
21
- const radioInput = screen.getByRole('radio');
22
- const label = screen.getByText('testValue'); // Use text to find the label
23
-
24
- // Assert that the radio input is rendered correctly
25
- expect(radioInput).toBeInTheDocument();
26
- expect(radioInput).toHaveAttribute('name', 'testName');
27
- expect(radioInput).toHaveAttribute('value', 'testValue');
28
- expect(radioInput).toBeChecked();
29
- expect(radioInput).toHaveClass('input-class');
30
-
31
- // Assert that the label is rendered correctly
32
- expect(label).toBeInTheDocument();
33
-
34
- // Ensure the label has the correct class by finding the label element directly
35
- const labelElement = document.querySelector(`label[for="radio1"]`);
36
- expect(labelElement).toHaveClass('label-class');
37
- });
38
-
39
- it('should call onChange handler when clicked', () => {
40
- const handleChange = jest.fn();
41
-
42
- render(
43
- <CustomRadioButton
44
- name="testName"
45
- value="testValue"
46
- onChange={handleChange}
47
- id="radio1"
48
- />
49
- );
50
-
51
- const radioInput = screen.getByRole('radio');
52
- fireEvent.click(radioInput);
53
-
54
- expect(handleChange).toHaveBeenCalled();
55
- });
56
- });
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
-
3
- interface RadioButtonProps {
4
- name: string;
5
- value: string;
6
- checked?: boolean;
7
- onChange?: React.ChangeEventHandler<HTMLInputElement>;
8
- className?: string;
9
- inputClassName?: string;
10
- labelClassName?: string;
11
- id?: string;
12
- [key: string]: any;
13
- }
14
-
15
- const CustomRadioButton: React.FC<RadioButtonProps> = ({
16
- name,
17
- value,
18
- checked = false,
19
- onChange,
20
- className = '',
21
- inputClassName = '',
22
- labelClassName = '',
23
- id,
24
- ...rest
25
- }) => {
26
- return (
27
- <div className={className}>
28
- <input
29
- type="radio"
30
- name={name}
31
- value={value}
32
- checked={checked}
33
- onChange={onChange}
34
- id={id}
35
- className={inputClassName}
36
- {...rest}
37
- />
38
- <label htmlFor={id} className={labelClassName}>{value}</label>
39
- </div>
40
- );
41
- };
42
-
43
- export default CustomRadioButton;