Skip to content

Commit

Permalink
Merge branch 'release/v1.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
troberts-28 committed May 6, 2024
2 parents badd4ff + 901a24a commit b0ae01f
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 69 deletions.
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Works with Expo and bare React Native apps.
- [Contributing 🧑‍🤝‍🧑](#contributing-)
- [Dev Setup](#dev-setup)
- [GitHub Guidelines](#github-guidelines)
- [Limitations ⚠](#limitations-)
- [License 📝](#license-)

<br>
Expand Down Expand Up @@ -332,18 +333,16 @@ return (
| Prop | Description | Type | Default | Required |
| :------------------------------: | :------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: | :------: |
| onDurationChange | Callback when the duration changes | `(duration: { hours: number, minutes: number, seconds: number }) => void` | - | false |
| initialHours | Initial value for hours | Number | - | false |
| initialMinutes | Initial value for minutes | Number | - | false |
| initialSeconds | Initial value for seconds | Number | - | false |
| initialValue | Initial value for the picker | `{ hours?: number, minutes?: number, seconds?: number }` | - | false |
| hideHours | Hide the hours picker | Boolean | false | false |
| hideMinutes | Hide the minutes picker | Boolean | false | false |
| hideSeconds | Hide the seconds picker | Boolean | false | false |
| hoursPickerIsDisabled | Disable the hours picker picker | Boolean | false | false |
| minutesPickerIsDisabled | Disable the minutes picker picker | Boolean | false | false |
| secondsPickerIsDisabled | Disable the seconds picker picker | Boolean | false | false |
| hourLimit | Limit on the hours it is possible to select | { max?: Number, min?: Number } | - | false |
| minuteLimit | Limit on the minutes it is possible to select | { max?: Number, min?: Number } | - | false |
| secondLimit | Limit on the seconds it is possible to select | { max?: Number, min?: Number } | - | false |
| hourLimit | Limit on the hours it is possible to select | `{ max?: Number, min?: Number }` | - | false |
| minuteLimit | Limit on the minutes it is possible to select | `{ max?: Number, min?: Number }` | - | false |
| secondLimit | Limit on the seconds it is possible to select | `{ max?: Number, min?: Number }` | - | false |
| hourLabel | Label for the hours picker | String \| React.ReactElement | h | false |
| minuteLabel | Label for the minutes picker | String \| React.ReactElement | m | false |
| secondLabel | Label for the seconds picker | String \| React.ReactElement | s | false |
Expand All @@ -370,17 +369,19 @@ The following custom styles can be supplied to re-style the component in any way
| theme | Theme of the component | "light" \| "dark" |
| backgroundColor | Main background color | string |
| text | Base text style | TextStyle |
| pickerContainer | Main container for the picker | ViewStyle |
| pickerContainer | Main container for the picker | ViewStyle & { backgroundColor?: string } |
| pickerLabelContainer | Container for the picker's labels | ViewStyle |
| pickerLabel | Style for the picker's labels | TextStyle |
| pickerAmPmContainer | Style for the picker's labels | ViewStyle |
| pickerAmPmLabel | Style for the picker's labels | TextStyle |
| pickerItemContainer | Container for each number in the picker | ViewStyle |
| pickerItemContainer | Container for each number in the picker | ViewStyle & { height?: number } |
| pickerItem | Style for each individual picker number | TextStyle |
| disabledPickerItem | Style for any numbers outside any set limits | TextStyle |
| disabledPickerContainer | Style for disabled pickers | ViewStyle |
| pickerGradientOverlay | Style for the gradient overlay (fade out) | ViewStyle |

Note the minor limitations to the allowed styles for `pickerContainer` and `pickerItemContainer`. These are made because these styles are used for internal calculations and all possible `backgroundColor`/`height` types are not supported.

### TimerPickerModal ⏰

The TimerPickerModal component accepts all [TimerPicker props](#timerpicker-️), and the below additional props.
Expand Down Expand Up @@ -486,6 +487,12 @@ There are two permenant branches: `main` and `develop`. You should never work di
<br>
## Limitations ⚠
Nesting the `TimerPicker` component inside a vertical ScrollView is not supported. React Native will throw an error and the picker will not be scrollable. The modal component works fine in this scenario however.
<br>
## License 📝
This project is licensed under the [MIT License](LICENSE).
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"url": "https://github.com/troberts-28"
},
"license": "MIT",
"version": "1.6.0",
"version": "1.7.0",
"main": "dist/commonjs/index.js",
"types": "dist/typescript/src/index.d.ts",
"scripts": {
Expand Down
24 changes: 12 additions & 12 deletions src/components/TimerPicker/TimerPicker.styles.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { StyleSheet } from "react-native";
import { StyleSheet, TextStyle, ViewStyle } from "react-native";

export interface CustomTimerPickerStyles {
theme?: "light" | "dark";
backgroundColor?: string;
text?: any;
pickerContainer?: any;
pickerLabelContainer?: any;
pickerLabel?: any;
pickerAmPmContainer?: any;
pickerAmPmLabel?: any;
pickerItemContainer?: any;
pickerItem?: any;
disabledPickerContainer?: any;
disabledPickerItem?: any;
pickerGradientOverlay?: any;
text?: TextStyle;
pickerContainer?: ViewStyle & { backgroundColor?: string };
pickerLabelContainer?: ViewStyle;
pickerLabel?: TextStyle;
pickerAmPmContainer?: ViewStyle;
pickerAmPmLabel?: TextStyle;
pickerItemContainer?: ViewStyle & { height?: number };
pickerItem?: TextStyle;
disabledPickerContainer?: ViewStyle;
disabledPickerItem?: TextStyle;
pickerGradientOverlay?: ViewStyle;
}

const DARK_MODE_BACKGROUND_COLOR = "#232323";
Expand Down
42 changes: 27 additions & 15 deletions src/components/TimerPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ export interface TimerPickerProps {
minutes: number;
seconds: number;
}) => void;
initialHours?: number;
initialMinutes?: number;
initialSeconds?: number;
initialValue?: {
hours?: number;
minutes?: number;
seconds?: number;
};
aggressivelyGetLatestDuration?: boolean;
use12HourPicker?: boolean;
amLabel?: string;
Expand Down Expand Up @@ -73,9 +75,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
{
allowFontScaling = false,
onDurationChange,
initialHours = 0,
initialMinutes = 0,
initialSeconds = 0,
initialValue,
hideHours = false,
hideMinutes = false,
hideSeconds = false,
Expand Down Expand Up @@ -115,9 +115,21 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
[checkedPadWithNItems, customStyles]
);

const [selectedHours, setSelectedHours] = useState(initialHours);
const [selectedMinutes, setSelectedMinutes] = useState(initialMinutes);
const [selectedSeconds, setSelectedSeconds] = useState(initialSeconds);
const safeInitialValue = {
hours: initialValue?.hours ?? 0,
minutes: initialValue?.minutes ?? 0,
seconds: initialValue?.seconds ?? 0,
};

const [selectedHours, setSelectedHours] = useState(
safeInitialValue.hours
);
const [selectedMinutes, setSelectedMinutes] = useState(
safeInitialValue.minutes
);
const [selectedSeconds, setSelectedSeconds] = useState(
safeInitialValue.seconds
);

useEffect(() => {
onDurationChange?.({
Expand All @@ -134,9 +146,9 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(

useImperativeHandle(ref, () => ({
reset: (options) => {
setSelectedHours(initialHours);
setSelectedMinutes(initialMinutes);
setSelectedSeconds(initialSeconds);
setSelectedHours(safeInitialValue.hours);
setSelectedMinutes(safeInitialValue.minutes);
setSelectedSeconds(safeInitialValue.seconds);
hoursDurationScrollRef.current?.reset(options);
minutesDurationScrollRef.current?.reset(options);
secondsDurationScrollRef.current?.reset(options);
Expand Down Expand Up @@ -175,7 +187,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
hourLabel ?? (!use12HourPicker ? "h" : undefined)
}
isDisabled={hoursPickerIsDisabled}
initialValue={initialHours}
initialValue={safeInitialValue.hours}
allowFontScaling={allowFontScaling}
aggressivelyGetLatestDuration={
aggressivelyGetLatestDuration
Expand Down Expand Up @@ -205,7 +217,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
numberOfItems={59}
label={minuteLabel ?? "m"}
isDisabled={minutesPickerIsDisabled}
initialValue={initialMinutes}
initialValue={safeInitialValue.minutes}
allowFontScaling={allowFontScaling}
aggressivelyGetLatestDuration={
aggressivelyGetLatestDuration
Expand Down Expand Up @@ -233,7 +245,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
numberOfItems={59}
label={secondLabel ?? "s"}
isDisabled={secondsPickerIsDisabled}
initialValue={initialSeconds}
initialValue={safeInitialValue.seconds}
allowFontScaling={allowFontScaling}
aggressivelyGetLatestDuration={
aggressivelyGetLatestDuration
Expand Down
16 changes: 8 additions & 8 deletions src/components/TimerPickerModal.styles.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { StyleSheet } from "react-native";
import { StyleSheet, TextStyle, ViewStyle } from "react-native";

import type { CustomTimerPickerStyles } from "./TimerPicker/TimerPicker.styles";

export interface CustomTimerPickerModalStyles extends CustomTimerPickerStyles {
container?: any;
contentContainer?: any;
buttonContainer?: any;
button?: any;
cancelButton?: any;
confirmButton?: any;
modalTitle?: any;
container?: ViewStyle;
contentContainer?: ViewStyle;
buttonContainer?: ViewStyle;
button?: TextStyle;
cancelButton?: TextStyle;
confirmButton?: TextStyle;
modalTitle?: TextStyle;
}

const DARK_MODE_BACKGROUND_COLOR = "#232323";
Expand Down
45 changes: 20 additions & 25 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
onCancel,
onDurationChange,
closeOnOverlayPress,
initialHours = 0,
initialMinutes = 0,
initialSeconds = 0,
initialValue,
hideHours = false,
hideMinutes = false,
hideSeconds = false,
Expand Down Expand Up @@ -114,33 +112,32 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(

const timerPickerRef = useRef<TimerPickerRef>(null);

const [selectedDuration, setSelectedDuration] = useState({
hours: initialHours,
minutes: initialMinutes,
seconds: initialSeconds,
});
const [confirmedDuration, setConfirmedDuration] = useState({
hours: initialHours,
minutes: initialMinutes,
seconds: initialSeconds,
});
const safeInitialValue = {
hours: initialValue?.hours ?? 0,
minutes: initialValue?.minutes ?? 0,
seconds: initialValue?.seconds ?? 0,
};

const [selectedDuration, setSelectedDuration] =
useState(safeInitialValue);
const [confirmedDuration, setConfirmedDuration] =
useState(safeInitialValue);

const reset = (options?: { animated?: boolean }) => {
const initialDuration = {
hours: initialHours,
minutes: initialMinutes,
seconds: initialSeconds,
};
setSelectedDuration(initialDuration);
setConfirmedDuration(initialDuration);
setSelectedDuration(safeInitialValue);
setConfirmedDuration(safeInitialValue);
timerPickerRef.current?.reset(options);
};

// reset state if the initial times change
// reset state if the initial value changes
useEffect(() => {
reset();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialHours, initialMinutes, initialSeconds]);
}, [
safeInitialValue.hours,
safeInitialValue.minutes,
safeInitialValue.seconds,
]);

const hideModalHandler = () => {
setSelectedDuration({
Expand Down Expand Up @@ -217,9 +214,7 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
<TimerPicker
ref={timerPickerRef}
onDurationChange={durationChangeHandler}
initialHours={confirmedDuration.hours}
initialMinutes={confirmedDuration.minutes}
initialSeconds={confirmedDuration.seconds}
initialValue={confirmedDuration}
aggressivelyGetLatestDuration={true}
hideHours={hideHours}
hideMinutes={hideMinutes}
Expand Down

0 comments on commit b0ae01f

Please sign in to comment.