react-native-timer-picker 1.9.0 → 1.10.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 (34) hide show
  1. package/README.md +3 -0
  2. package/dist/commonjs/components/TimerPicker/index.js +6 -3
  3. package/dist/commonjs/components/TimerPicker/index.js.map +1 -1
  4. package/dist/commonjs/components/TimerPicker/types.js.map +1 -1
  5. package/dist/commonjs/tests/TimerPicker.test.js +14 -0
  6. package/dist/commonjs/tests/TimerPicker.test.js.map +1 -1
  7. package/dist/module/components/TimerPicker/index.js +6 -3
  8. package/dist/module/components/TimerPicker/index.js.map +1 -1
  9. package/dist/module/components/TimerPicker/types.js.map +1 -1
  10. package/dist/module/tests/TimerPicker.test.js +14 -0
  11. package/dist/module/tests/TimerPicker.test.js.map +1 -1
  12. package/dist/typescript/components/TimerPicker/types.d.ts +3 -0
  13. package/package.json +1 -2
  14. package/src/components/DurationScroll/index.tsx +0 -459
  15. package/src/components/DurationScroll/types.ts +0 -75
  16. package/src/components/Modal/index.tsx +0 -124
  17. package/src/components/Modal/styles.ts +0 -26
  18. package/src/components/Modal/types.ts +0 -17
  19. package/src/components/TimerPicker/index.tsx +0 -196
  20. package/src/components/TimerPicker/styles.ts +0 -123
  21. package/src/components/TimerPicker/types.ts +0 -74
  22. package/src/components/TimerPickerModal/index.tsx +0 -190
  23. package/src/components/TimerPickerModal/styles.ts +0 -88
  24. package/src/components/TimerPickerModal/types.ts +0 -52
  25. package/src/index.ts +0 -13
  26. package/src/tests/DurationScroll.test.tsx +0 -66
  27. package/src/tests/Modal.test.tsx +0 -36
  28. package/src/tests/TimerPicker.test.tsx +0 -29
  29. package/src/tests/TimerPickerModal.test.tsx +0 -72
  30. package/src/utils/colorToRgba.ts +0 -49
  31. package/src/utils/generateNumbers.ts +0 -64
  32. package/src/utils/getAdjustedLimit.ts +0 -35
  33. package/src/utils/getScrollIndex.ts +0 -15
  34. package/src/utils/padNumber.ts +0 -10
@@ -1,52 +0,0 @@
1
- import type { MutableRefObject } from "react";
2
-
3
- import type { View, TouchableOpacity, Text } from "react-native";
4
-
5
- import type Modal from "../Modal";
6
- import type { TimerPickerProps } from "../TimerPicker/types";
7
-
8
- import type { CustomTimerPickerModalStyles } from "./styles";
9
-
10
- export interface TimerPickerModalRef {
11
- latestDuration: {
12
- hours: MutableRefObject<number> | undefined;
13
- minutes: MutableRefObject<number> | undefined;
14
- seconds: MutableRefObject<number> | undefined;
15
- };
16
- reset: (options?: { animated?: boolean }) => void;
17
- setValue: (
18
- value: {
19
- hours: number;
20
- minutes: number;
21
- seconds: number;
22
- },
23
- options?: { animated?: boolean }
24
- ) => void;
25
- }
26
-
27
- export interface TimerPickerModalProps extends TimerPickerProps {
28
- buttonContainerProps?: React.ComponentProps<typeof View>;
29
- buttonTouchableOpacityProps?: React.ComponentProps<typeof TouchableOpacity>;
30
- cancelButtonText?: string;
31
- closeOnOverlayPress?: boolean;
32
- confirmButtonText?: string;
33
- containerProps?: React.ComponentProps<typeof View>;
34
- contentContainerProps?: React.ComponentProps<typeof View>;
35
- hideCancelButton?: boolean;
36
- modalProps?: React.ComponentProps<typeof Modal>;
37
- modalTitle?: string;
38
- modalTitleProps?: React.ComponentProps<typeof Text>;
39
- onCancel?: () => void;
40
- onConfirm: ({
41
- hours,
42
- minutes,
43
- seconds,
44
- }: {
45
- hours: number;
46
- minutes: number;
47
- seconds: number;
48
- }) => void;
49
- setIsVisible: (isVisible: boolean) => void;
50
- styles?: CustomTimerPickerModalStyles;
51
- visible: boolean;
52
- }
package/src/index.ts DELETED
@@ -1,13 +0,0 @@
1
- export { default as TimerPickerModal } from "./components/TimerPickerModal";
2
- export {
3
- TimerPickerModalProps,
4
- TimerPickerModalRef,
5
- } from "./components/TimerPickerModal/types";
6
- export { CustomTimerPickerModalStyles } from "./components/TimerPickerModal/styles";
7
-
8
- export { default as TimerPicker } from "./components/TimerPicker";
9
- export {
10
- TimerPickerProps,
11
- TimerPickerRef,
12
- } from "./components/TimerPicker/types";
13
- export { CustomTimerPickerStyles } from "./components/TimerPicker/styles";
@@ -1,66 +0,0 @@
1
- import React from "react";
2
-
3
- import { render } from "@testing-library/react-native";
4
-
5
- import DurationScroll from "../components/DurationScroll";
6
- import type { generateStyles } from "../components/TimerPicker/styles";
7
-
8
- describe("DurationScroll", () => {
9
- const onDurationChangeMock = jest.fn();
10
- const emptyStyles = {
11
- pickerContainer: {},
12
- pickerLabelContainer: {},
13
- pickerLabel: {},
14
- pickerItemContainer: {},
15
- pickerItem: {},
16
- pickerAmPmContainer: {},
17
- pickerAmPmLabel: {},
18
- disabledPickerContainer: {},
19
- disabledPickerItem: {},
20
- pickerGradientOverlay: {},
21
- } as ReturnType<typeof generateStyles>;
22
-
23
- it("renders without crashing", () => {
24
- const { getByTestId } = render(
25
- <DurationScroll
26
- aggressivelyGetLatestDuration={false}
27
- numberOfItems={1}
28
- onDurationChange={onDurationChangeMock}
29
- padWithNItems={0}
30
- styles={emptyStyles}
31
- testID="duration-scroll"
32
- />
33
- );
34
- const component = getByTestId("duration-scroll");
35
- expect(component).toBeDefined();
36
- });
37
-
38
- it("renders the correct number of items", () => {
39
- const { getAllByTestId } = render(
40
- <DurationScroll
41
- aggressivelyGetLatestDuration={false}
42
- numberOfItems={2}
43
- onDurationChange={onDurationChangeMock}
44
- padWithNItems={1}
45
- styles={emptyStyles}
46
- />
47
- );
48
- const items = getAllByTestId("picker-item");
49
- expect(items).toHaveLength(7);
50
- });
51
-
52
- it("renders the label if provided", () => {
53
- const { getByText } = render(
54
- <DurationScroll
55
- aggressivelyGetLatestDuration={false}
56
- label="Duration"
57
- numberOfItems={59}
58
- onDurationChange={onDurationChangeMock}
59
- padWithNItems={1}
60
- styles={emptyStyles}
61
- />
62
- );
63
- const label = getByText("Duration");
64
- expect(label).toBeDefined();
65
- });
66
- });
@@ -1,36 +0,0 @@
1
- import React from "react";
2
-
3
- import { render, fireEvent } from "@testing-library/react-native";
4
- import { Text } from "react-native";
5
-
6
- import Modal from "../components/Modal";
7
-
8
- describe("Modal", () => {
9
- it("renders without crashing", () => {
10
- const { getByTestId } = render(<Modal isVisible/>);
11
- const component = getByTestId("modal");
12
- expect(component).toBeDefined();
13
- });
14
-
15
- it("renders children when visible", () => {
16
- const { getByText } = render(
17
- <Modal isVisible>
18
- <Text>{"Modal Content"}</Text>
19
- </Modal>
20
- );
21
- const content = getByText("Modal Content");
22
- expect(content).toBeDefined();
23
- });
24
-
25
- it("calls onOverlayPress when overlay is pressed", () => {
26
- const onOverlayPressMock = jest.fn();
27
- const { getByTestId } = render(
28
- <Modal isVisible onOverlayPress={onOverlayPressMock} />
29
- );
30
- const overlay = getByTestId("modal-backdrop");
31
- fireEvent.press(overlay);
32
- expect(onOverlayPressMock).toHaveBeenCalled();
33
- });
34
-
35
- // Add more test cases to cover different interactions, scenarios, and edge cases
36
- });
@@ -1,29 +0,0 @@
1
- import React from "react";
2
-
3
- import { render } from "@testing-library/react-native";
4
-
5
- import TimerPicker from "../components/TimerPicker";
6
-
7
- describe("TimerPicker", () => {
8
- it("renders without crashing", () => {
9
- const { getByTestId } = render(<TimerPicker />);
10
- const component = getByTestId("timer-picker");
11
- expect(component).toBeDefined();
12
- });
13
-
14
- it("renders without crashing with negative padWithNItems", () => {
15
- const { getByTestId } = render(<TimerPicker padWithNItems={-1} />);
16
- const component = getByTestId("timer-picker");
17
- expect(component).toBeDefined();
18
- });
19
-
20
- it("hides minutes and seconds when respective hide props are provided", () => {
21
- const { queryByTestId } = render(
22
- <TimerPicker hideMinutes hideSeconds />
23
- );
24
- const minutePicker = queryByTestId("duration-scroll-minute");
25
- const secondPicker = queryByTestId("duration-scroll-second");
26
- expect(minutePicker).toBeNull();
27
- expect(secondPicker).toBeNull();
28
- });
29
- });
@@ -1,72 +0,0 @@
1
- import React from "react";
2
-
3
- import { render, fireEvent } from "@testing-library/react-native";
4
-
5
- import TimerPickerModal from "../components/TimerPickerModal";
6
-
7
- describe("TimerPickerModal", () => {
8
- const mockOnConfirm = jest.fn();
9
- const mockOnCancel = jest.fn();
10
-
11
- const defaultProps = {
12
- visible: true,
13
- setIsVisible: jest.fn(),
14
- onConfirm: mockOnConfirm,
15
- onCancel: mockOnCancel,
16
- };
17
-
18
- it("renders without crashing", () => {
19
- const { getByTestId } = render(<TimerPickerModal {...defaultProps} />);
20
- const component = getByTestId("timer-picker-modal");
21
- expect(component).toBeDefined();
22
- });
23
-
24
- it("calls onConfirm when Confirm button is pressed", () => {
25
- const { getByText } = render(<TimerPickerModal {...defaultProps} />);
26
- const confirmButton = getByText("Confirm");
27
- fireEvent.press(confirmButton);
28
- expect(mockOnConfirm).toHaveBeenCalled();
29
- });
30
-
31
- it("calls onCancel when Cancel button is pressed", () => {
32
- const { getByText } = render(<TimerPickerModal {...defaultProps} />);
33
- const cancelButton = getByText("Cancel");
34
- fireEvent.press(cancelButton);
35
- expect(mockOnCancel).toHaveBeenCalled();
36
- });
37
-
38
- it("hides the modal when Cancel button is pressed", () => {
39
- const setIsVisibleMock = jest.fn();
40
- const { getByText } = render(
41
- <TimerPickerModal
42
- {...defaultProps}
43
- setIsVisible={setIsVisibleMock}
44
- />
45
- );
46
- const cancelButton = getByText("Cancel");
47
- fireEvent.press(cancelButton);
48
- expect(setIsVisibleMock).toHaveBeenCalledWith(false);
49
- });
50
-
51
- it("hides the modal when overlay is pressed", () => {
52
- const setIsVisibleMock = jest.fn();
53
- const { getByTestId } = render(
54
- <TimerPickerModal
55
- {...defaultProps}
56
- closeOnOverlayPress
57
- setIsVisible={setIsVisibleMock}
58
- />
59
- );
60
- const overlay = getByTestId("modal-backdrop");
61
- fireEvent.press(overlay);
62
- expect(setIsVisibleMock).toHaveBeenCalledWith(false);
63
- });
64
-
65
- it("calls onConfirm with selected duration when Confirm button is pressed", () => {
66
- const { getByText } = render(<TimerPickerModal {...defaultProps} />);
67
- // Select duration in TimerPicker, assuming its interaction is tested separately
68
- const confirmButton = getByText("Confirm");
69
- fireEvent.press(confirmButton);
70
- expect(mockOnConfirm).toHaveBeenCalledWith(expect.objectContaining({}));
71
- });
72
- });
@@ -1,49 +0,0 @@
1
- export const colorToRgba = (variables: { color: string; opacity?: number }) => {
2
- // this function is required for expo-linear-gradient on iOS. To fade to transparent, we need
3
- // to be able to add opacity to the background color. Supplying 'transparent' does not work
4
- // because that is actually a transparent black (rgba(0, 0, 0, 1)), which results in dodgy rendering
5
-
6
- const { color, opacity = 1 } = variables;
7
- // Handle named colors
8
- const namedColors: { [key: string]: string } = {
9
- transparent: "rgba(0, 0, 0, 0)",
10
- black: "rgba(0, 0, 0, 1)",
11
- white: "rgba(255, 255, 255, 1)",
12
- blue: "rgba(0, 0, 255, 1)",
13
- green: "rgba(0, 128, 0, 1)",
14
- gray: "rgba(128, 128, 128, 1)",
15
- red: "rgba(255, 0, 0, 1)",
16
- };
17
-
18
- if (color in namedColors) {
19
- return namedColors[color];
20
- }
21
-
22
- // Handle RGB format
23
- if (color.startsWith("rgb(")) {
24
- const rgbValues = color
25
- .replace("rgb(", "")
26
- .replace(")", "")
27
- .split(",")
28
- .map((value) => parseInt(value.trim(), 10));
29
- const [r, g, b] = rgbValues;
30
- return `rgba(${r}, ${g}, ${b}, ${opacity})`;
31
- }
32
-
33
- // Handle hex format
34
- if (color.startsWith("#")) {
35
- let hexColor = color.slice(1);
36
- if (hexColor.length === 3) {
37
- hexColor = hexColor
38
- .split("")
39
- .map((value) => value + value)
40
- .join("");
41
- }
42
- const r = parseInt(hexColor.slice(0, 2), 16);
43
- const g = parseInt(hexColor.slice(2, 4), 16);
44
- const b = parseInt(hexColor.slice(4, 6), 16);
45
- return `rgba(${r}, ${g}, ${b}, ${opacity})`;
46
- }
47
-
48
- return color; // Return unchanged if unable to parse
49
- };
@@ -1,64 +0,0 @@
1
- import { padNumber } from "./padNumber";
2
-
3
- export const generateNumbers = (
4
- numberOfItems: number,
5
- options: {
6
- disableInfiniteScroll?: boolean;
7
- padNumbersWithZero?: boolean;
8
- padWithNItems: number;
9
- repeatNTimes?: number;
10
- }
11
- ) => {
12
- if (numberOfItems <= 0) {
13
- return [];
14
- }
15
-
16
- let numbers: string[] = [];
17
- for (let i = 0; i <= numberOfItems; i++) {
18
- numbers.push(padNumber(i, { padWithZero: options.padNumbersWithZero }));
19
- }
20
-
21
- if ((options.repeatNTimes ?? 1) > 1) {
22
- numbers = Array(options.repeatNTimes).fill(numbers).flat();
23
- }
24
- if (options.disableInfiniteScroll) {
25
- numbers.push(...Array(options.padWithNItems).fill(""));
26
- numbers.unshift(...Array(options.padWithNItems).fill(""));
27
- }
28
- return numbers;
29
- };
30
-
31
- export const generate12HourNumbers = (options: {
32
- disableInfiniteScroll?: boolean;
33
- padNumbersWithZero?: boolean;
34
- padWithNItems: number;
35
- repeatNTimes?: number;
36
- }) => {
37
- let numbers: string[] = [];
38
-
39
- // Generate numbers from 0 to 11 for AM
40
- for (let i = 0; i <= 11; i++) {
41
- numbers.push(
42
- `${padNumber(i, { padWithZero: options.padNumbersWithZero })} AM`
43
- );
44
- }
45
-
46
- // Generate numbers from 12 to 11 for PM
47
- for (let i = 12; i <= 23; i++) {
48
- const hour = i > 12 ? i - 12 : i;
49
- numbers.push(
50
- `${padNumber(hour, { padWithZero: options.padNumbersWithZero })} PM`
51
- );
52
- }
53
-
54
- if ((options.repeatNTimes ?? 1) > 1) {
55
- numbers = Array(options.repeatNTimes).fill(numbers).flat();
56
- }
57
-
58
- if (options.disableInfiniteScroll) {
59
- numbers.push(...Array(options.padWithNItems).fill(""));
60
- numbers.unshift(...Array(options.padWithNItems).fill(""));
61
- }
62
-
63
- return numbers;
64
- };
@@ -1,35 +0,0 @@
1
- import type { LimitType } from "../components/DurationScroll/types";
2
-
3
- export const getAdjustedLimit = (
4
- limit: LimitType | undefined,
5
- numberOfItems: number
6
- ): {
7
- max: number;
8
- min: number;
9
- } => {
10
- if (!limit || (!limit.max && !limit.min)) {
11
- return {
12
- max: numberOfItems,
13
- min: 0,
14
- };
15
- }
16
-
17
- // guard against limits that are out of bounds
18
- const adjustedMaxLimit = limit.max
19
- ? Math.min(limit.max, numberOfItems)
20
- : numberOfItems;
21
- const adjustedMinLimit = limit.min ? Math.max(limit.min, 0) : 0;
22
-
23
- // guard against invalid limits
24
- if (adjustedMaxLimit < adjustedMinLimit) {
25
- return {
26
- max: numberOfItems,
27
- min: 0,
28
- };
29
- }
30
-
31
- return {
32
- max: adjustedMaxLimit,
33
- min: adjustedMinLimit,
34
- };
35
- };
@@ -1,15 +0,0 @@
1
- export const getScrollIndex = (variables: {
2
- disableInfiniteScroll?: boolean;
3
- numberOfItems: number;
4
- padWithNItems: number;
5
- value: number;
6
- }) => {
7
- const { disableInfiniteScroll, numberOfItems, padWithNItems, value } =
8
- variables;
9
-
10
- return (
11
- ((value + numberOfItems) % (numberOfItems * 3)) +
12
- (disableInfiniteScroll ? padWithNItems : 0) -
13
- (padWithNItems - 1)
14
- );
15
- };
@@ -1,10 +0,0 @@
1
- export const padNumber = (
2
- value: number,
3
- options?: { padWithZero?: boolean }
4
- ): string => {
5
- if (value < 10) {
6
- return (options?.padWithZero ? "0" : " ") + value;
7
- } else {
8
- return String(value);
9
- }
10
- };