Skip to content

Commit

Permalink
Optionally clamp selected value when min and/or max change (#66)
Browse files Browse the repository at this point in the history
* Optionally clamp selected value when min and/or max change

* Create eleven-hats-fry.md
  • Loading branch information
Zertz authored Jul 4, 2022
1 parent b4cc016 commit ef4f822
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changeset/eleven-hats-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@tempocal/react": minor
"@tempocal/www": minor
---

Optionally clamp selected value when min and/or max change
44 changes: 41 additions & 3 deletions packages/react/src/useTempocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
} from "@tempocal/core";
import * as React from "react";

export type ClampMode = "always" | "value-change" | "never";

export type DateRange =
| [undefined, undefined]
| [Temporal.PlainDate, undefined]
Expand Down Expand Up @@ -65,9 +67,9 @@ export function useTempocal<
}: {
clampCalendarValue?: boolean;
clampSelectedValue?: Mode extends "date"
? boolean
? ClampMode
: Mode extends "datetime"
? boolean
? ClampMode
: never;
locale: Locale;
maxValue?: Temporal.PlainDate | Temporal.PlainDateTime;
Expand Down Expand Up @@ -188,7 +190,11 @@ export function useTempocal<
| DateRange
| DateTimeRange
) => {
if (!clampSelectedValue || Array.isArray(nextSelectedValue)) {
if (
!clampSelectedValue ||
clampSelectedValue === "never" ||
Array.isArray(nextSelectedValue)
) {
// @ts-expect-error Help.
setValue(nextSelectedValue);

Expand Down Expand Up @@ -280,6 +286,38 @@ export function useTempocal<
[mode, setValue, updateSelectedValue, value]
);

const previousClampSelectedValue = React.useRef(clampSelectedValue);
const previousMaxValue = React.useRef(maxValue);
const previousMinValue = React.useRef(minValue);

React.useEffect(() => {
if (!clampSelectedValue || !value) {
return;
}

if (!maxValue && !minValue) {
return;
}

if (clampSelectedValue !== "always") {
return;
}

if (
clampSelectedValue !== previousClampSelectedValue.current ||
maxValue !== previousMaxValue.current ||
minValue !== previousMinValue.current
) {
updateSelectedValue(value);
}
});

React.useEffect(() => {
previousClampSelectedValue.current = clampSelectedValue;
previousMaxValue.current = maxValue;
previousMinValue.current = minValue;
});

return {
calendarProps: {
locale,
Expand Down
4 changes: 2 additions & 2 deletions packages/www/examples/DateTimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Temporal } from "@js-temporal/polyfill";
import { temporalToDate } from "@tempocal/core";
import { Calendar, useTempocal } from "@tempocal/react";
import { Calendar, ClampMode, useTempocal } from "@tempocal/react";
import classnames from "classnames";
import * as React from "react";
import { CalendarHeader } from "../recipes/CalendarHeader";
Expand All @@ -15,7 +15,7 @@ const dateTimeFormatter = new Intl.DateTimeFormat(locale, {
export function DateTimePicker({
clampSelectedValue,
}: {
clampSelectedValue: boolean;
clampSelectedValue: ClampMode;
}) {
const [value, setValue] = React.useState(
Temporal.PlainDateTime.from({
Expand Down
10 changes: 7 additions & 3 deletions packages/www/pages/examples/DateTimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ClampMode } from "@tempocal/react/dist/tempocal-react";
import { InferGetStaticPropsType } from "next";
import * as React from "react";
import { Checkbox } from "../../components/Checkbox";
Expand All @@ -8,7 +9,8 @@ import { fetchFromGitHub } from "../../utils/fetchFromGitHub";
export default function DateTimePickerPage(
props: InferGetStaticPropsType<typeof getStaticProps>
) {
const [clampSelectedValue, setClampSelectedValue] = React.useState(true);
const [clampSelectedValue, setClampSelectedValue] =
React.useState<ClampMode>("always");

return (
<Example
Expand All @@ -19,13 +21,15 @@ export default function DateTimePickerPage(
<fieldset className="flex flex-col gap-2">
<legend className="sr-only">Props</legend>
<Checkbox
checked={clampSelectedValue}
checked={clampSelectedValue === "always"}
hint="When minValue and/or maxValue are set, automatically keep the selected value within those values."
id="clampSelectedValue"
label="clampSelectedValue"
name="clampSelectedValue"
onChange={() => {
setClampSelectedValue((clampSelectedValue) => !clampSelectedValue);
setClampSelectedValue((clampSelectedValue) =>
clampSelectedValue === "always" ? "never" : "always"
);
}}
/>
</fieldset>
Expand Down
4 changes: 2 additions & 2 deletions packages/www/pages/react/useTempocal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const {
onChangeSelectedValue,
} = useTempocal({
clampCalendarValue?: boolean;
clampSelectedValue?: boolean;
clampSelectedValue?: "always" | "value-change" | "never";
locale: Locale;
maxValue?: Temporal.PlainDate | Temporal.PlainDateTime;
minValue?: Temporal.PlainDate | Temporal.PlainDateTime;
Expand Down Expand Up @@ -68,7 +68,7 @@ const {
automatically select 8 AM instead to keep the time within the
minimum.
</p>
<CodeBlock>{`clampSelectedValue?: boolean`}</CodeBlock>
<CodeBlock>{`clampSelectedValue?: "always" | "value-change" | "never"`}</CodeBlock>
</div>
<div className="space-y-2">
<AnchorHeader id="options-locale">locale</AnchorHeader>
Expand Down
2 changes: 1 addition & 1 deletion packages/www/test/DateTimePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DateTimePicker } from "../examples/DateTimePicker";

test("DateTimePicker renders without crashing", () => {
const { getByText, getByTitle } = render(
<DateTimePicker clampSelectedValue />
<DateTimePicker clampSelectedValue="always" />
);

expect(
Expand Down

1 comment on commit ef4f822

@vercel
Copy link

@vercel vercel bot commented on ef4f822 Jul 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

tempocal – ./

tempocal-zertz.vercel.app
tempocal.vercel.app
tempocal-git-main-zertz.vercel.app
tempocal.pierluc.io

Please sign in to comment.