mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
web: replace react-day-picker with custom built day picker
it uses `@rehookify/datepicker`
This commit is contained in:
committed by
Abdullah Atta
parent
9281f9a390
commit
2d226db271
@@ -34,6 +34,7 @@
|
|||||||
"@notesnook/web-clipper": "file:../../extensions/web-clipper",
|
"@notesnook/web-clipper": "file:../../extensions/web-clipper",
|
||||||
"@react-pdf-viewer/core": "^3.12.0",
|
"@react-pdf-viewer/core": "^3.12.0",
|
||||||
"@react-pdf-viewer/toolbar": "^3.12.0",
|
"@react-pdf-viewer/toolbar": "^3.12.0",
|
||||||
|
"@rehookify/datepicker": "^6.6.7",
|
||||||
"@streetwriters/kysely": "^0.27.4",
|
"@streetwriters/kysely": "^0.27.4",
|
||||||
"@tanstack/react-query": "^4.36.1",
|
"@tanstack/react-query": "^4.36.1",
|
||||||
"@tanstack/react-virtual": "^3.0.1",
|
"@tanstack/react-virtual": "^3.0.1",
|
||||||
@@ -48,7 +49,6 @@
|
|||||||
"clipboard-polyfill": "4.0.0",
|
"clipboard-polyfill": "4.0.0",
|
||||||
"comlink": "^4.3.1",
|
"comlink": "^4.3.1",
|
||||||
"cronosjs": "^1.7.1",
|
"cronosjs": "^1.7.1",
|
||||||
"date-fns": "^2.30.0",
|
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
"diffblazer": "^1.0.1",
|
"diffblazer": "^1.0.1",
|
||||||
"electron-trpc": "0.5.2",
|
"electron-trpc": "0.5.2",
|
||||||
|
|||||||
195
apps/web/src/components/day-picker/index.tsx
Normal file
195
apps/web/src/components/day-picker/index.tsx
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import { useDatePicker } from "@rehookify/datepicker";
|
||||||
|
import { Box, Button, Flex, Text } from "@theme-ui/components";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ChevronLeft, ChevronRight } from "../icons";
|
||||||
|
import { SxProp } from "@theme-ui/core";
|
||||||
|
|
||||||
|
type DayPickerProps = {
|
||||||
|
selected: Date;
|
||||||
|
minDate?: Date;
|
||||||
|
maxDate?: Date;
|
||||||
|
onSelect: (date: Date) => void;
|
||||||
|
} & SxProp;
|
||||||
|
export function DayPicker(props: DayPickerProps) {
|
||||||
|
const { selected, sx, maxDate, minDate, onSelect } = props;
|
||||||
|
const [selectedDates, onDatesChange] = useState<Date[]>([selected]);
|
||||||
|
const {
|
||||||
|
data: { weekDays, months, years, calendars },
|
||||||
|
propGetters: { dayButton, addOffset, subtractOffset, setOffset }
|
||||||
|
} = useDatePicker({
|
||||||
|
selectedDates,
|
||||||
|
onDatesChange: (dates) => {
|
||||||
|
onDatesChange(dates);
|
||||||
|
onSelect?.(dates[0]);
|
||||||
|
},
|
||||||
|
dates: {
|
||||||
|
maxDate,
|
||||||
|
minDate
|
||||||
|
},
|
||||||
|
years: { numberOfYears: 99 },
|
||||||
|
calendar: {
|
||||||
|
startDay: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { month, year, days } = calendars[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
flexDirection: "column",
|
||||||
|
...sx
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{ alignItems: "center", justifyContent: "space-between", gap: 1 }}
|
||||||
|
>
|
||||||
|
<Flex sx={{ alignItems: "center", justifyContent: "start", gap: 1 }}>
|
||||||
|
<Button
|
||||||
|
variant="icon"
|
||||||
|
sx={{ p: 0 }}
|
||||||
|
{...subtractOffset({ months: 1 })}
|
||||||
|
>
|
||||||
|
<ChevronLeft />
|
||||||
|
</Button>
|
||||||
|
<select
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--background-secondary)",
|
||||||
|
outline: "none",
|
||||||
|
border: "1px solid var(--border-secondary)",
|
||||||
|
borderRadius: "5px",
|
||||||
|
color: "var(--paragraph)",
|
||||||
|
padding: "5px",
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
value={month}
|
||||||
|
onChange={(e) => {
|
||||||
|
const selectedOption = e.target.selectedOptions[0];
|
||||||
|
setOffset(new Date(selectedOption.dataset.date || ""))?.onClick?.(
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{months.map((month) => (
|
||||||
|
<option
|
||||||
|
key={month.month + year}
|
||||||
|
value={month.month}
|
||||||
|
data-date={month.$date.toDateString()}
|
||||||
|
>
|
||||||
|
{month.month}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--background-secondary)",
|
||||||
|
outline: "none",
|
||||||
|
border: "1px solid var(--border-secondary)",
|
||||||
|
borderRadius: "5px",
|
||||||
|
color: "var(--paragraph)",
|
||||||
|
padding: "5px",
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
value={year}
|
||||||
|
onChange={(e) => {
|
||||||
|
const selectedOption = e.target.selectedOptions[0];
|
||||||
|
setOffset(new Date(selectedOption.dataset.date || ""))?.onClick?.(
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{years.map((year) => (
|
||||||
|
<option
|
||||||
|
key={year.year}
|
||||||
|
value={year.year}
|
||||||
|
data-date={year.$date.toDateString()}
|
||||||
|
>
|
||||||
|
{year.year}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</Flex>
|
||||||
|
<Button variant="icon" sx={{ p: 0 }} {...addOffset({ months: 1 })}>
|
||||||
|
<ChevronRight />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "repeat(7, 1fr)",
|
||||||
|
gap: 1,
|
||||||
|
mt: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{weekDays.map((day) => (
|
||||||
|
<Text
|
||||||
|
variant="body"
|
||||||
|
key={day}
|
||||||
|
sx={{ fontWeight: "bold", textAlign: "center" }}
|
||||||
|
>
|
||||||
|
{day}
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "repeat(7, 1fr)",
|
||||||
|
mt: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{days.map((day) => (
|
||||||
|
<Button
|
||||||
|
key={day.$date.toString()}
|
||||||
|
variant="icon"
|
||||||
|
sx={{
|
||||||
|
p: 0,
|
||||||
|
m: 0,
|
||||||
|
borderRadius: 100,
|
||||||
|
height: 35,
|
||||||
|
width: 35,
|
||||||
|
bg: day.selected ? "background-selected" : "transparent",
|
||||||
|
border: day.selected ? "1px solid var(--border-selected)" : "none"
|
||||||
|
}}
|
||||||
|
{...dayButton(day)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
variant="body"
|
||||||
|
sx={{
|
||||||
|
fontWeight: day.now ? "bold" : "normal",
|
||||||
|
color: day.now
|
||||||
|
? "accent"
|
||||||
|
: day.selected
|
||||||
|
? "accent-selected"
|
||||||
|
: day.inCurrentMonth
|
||||||
|
? "paragraph"
|
||||||
|
: "paragraph-secondary",
|
||||||
|
textAlign: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{day.day}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -29,8 +29,7 @@ import { showToast } from "../utils/toast";
|
|||||||
import { useIsUserPremium } from "../hooks/use-is-user-premium";
|
import { useIsUserPremium } from "../hooks/use-is-user-premium";
|
||||||
import { Calendar, Pro } from "../components/icons";
|
import { Calendar, Pro } from "../components/icons";
|
||||||
import { usePersistentState } from "../hooks/use-persistent-state";
|
import { usePersistentState } from "../hooks/use-persistent-state";
|
||||||
import { DayPicker } from "react-day-picker";
|
import { DayPicker } from "../components/day-picker";
|
||||||
import "react-day-picker/dist/style.css";
|
|
||||||
import { PopupPresenter } from "@notesnook/ui";
|
import { PopupPresenter } from "@notesnook/ui";
|
||||||
import { useStore as useThemeStore } from "../stores/theme-store";
|
import { useStore as useThemeStore } from "../stores/theme-store";
|
||||||
import { getFormattedDate } from "@notesnook/common";
|
import { getFormattedDate } from "@notesnook/common";
|
||||||
@@ -387,45 +386,26 @@ export const AddReminderDialog = DialogManager.register(
|
|||||||
target: dateInputRef.current,
|
target: dateInputRef.current,
|
||||||
location: "top"
|
location: "top"
|
||||||
}}
|
}}
|
||||||
sx={{
|
>
|
||||||
".rdp": {
|
<DayPicker
|
||||||
|
sx={{
|
||||||
bg: "background",
|
bg: "background",
|
||||||
p: 1,
|
p: 2,
|
||||||
boxShadow: `0px 0px 25px 5px ${
|
boxShadow: `0px 0px 25px 5px ${
|
||||||
theme === "dark" ? "#000000aa" : "#0000004e"
|
theme === "dark" ? "#000000aa" : "#0000004e"
|
||||||
}`,
|
}`,
|
||||||
borderRadius: "dialog",
|
borderRadius: "dialog",
|
||||||
fontFamily: "body",
|
width: 300
|
||||||
"--rdp-accent-color": "var(--accent)",
|
|
||||||
"--rdp-background-color": "var(--background)",
|
|
||||||
"--rdp-background-color-dark": "var(--background)",
|
|
||||||
"--rdp-selected-color": "var(--paragraph-selected)",
|
|
||||||
color: "paragraph"
|
|
||||||
},
|
|
||||||
".rdp-caption_label": { fontWeight: "heading" }
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DayPicker
|
|
||||||
mode="single"
|
|
||||||
captionLayout="dropdown-buttons"
|
|
||||||
fromYear={new Date().getFullYear()}
|
|
||||||
toYear={new Date().getFullYear() + 99}
|
|
||||||
modifiers={{
|
|
||||||
disabled: { before: new Date() }
|
|
||||||
}}
|
}}
|
||||||
selected={dayjs(date).toDate()}
|
selected={dayjs(date).toDate()}
|
||||||
|
minDate={new Date()}
|
||||||
|
maxDate={new Date(new Date().getFullYear() + 99, 11, 31)}
|
||||||
onSelect={(day) => {
|
onSelect={(day) => {
|
||||||
if (!day) return;
|
if (!day) return;
|
||||||
const date = getFormattedDate(day, "date");
|
const date = getFormattedDate(day, "date");
|
||||||
setDate((d) => setDateOnly(date, d));
|
setDate((d) => setDateOnly(date, d));
|
||||||
if (dateInputRef.current) dateInputRef.current.value = date;
|
if (dateInputRef.current) dateInputRef.current.value = date;
|
||||||
}}
|
}}
|
||||||
styles={{
|
|
||||||
day: {
|
|
||||||
fontFamily: "inherit",
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</PopupPresenter>
|
</PopupPresenter>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user