Skip to content

Commit

Permalink
add support for custom date parts
Browse files Browse the repository at this point in the history
  • Loading branch information
WickyNilliams committed Sep 22, 2024
1 parent 599194f commit 4260e57
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 20 deletions.
15 changes: 15 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
width: 100%;
text-align: center;
}

::part(foo) {
background: red;
}
::part(bar) {
background: blue;
}
</style>
</head>
<body>
Expand Down Expand Up @@ -115,6 +122,14 @@ <h2>multi</h2>
if (window.range) {
let start = null;

window.range.getPartsForDate = (date) => {
const d = date.getUTCDate();

if (d % 5 === 0) return "foo";
if (d % 9 === 0) return "bar";
return "";
};

window.range.addEventListener("rangestart", (e) => {
const { detail } = e;
start = detail;
Expand Down
10 changes: 7 additions & 3 deletions src/calendar-base/calendar-base.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { css } from "atomico";
import {
CalendarMonthContext,
CalendarContext,
type CalendarDateContext,
type CalendarMultiContext,
type CalendarRangeContext,
Expand Down Expand Up @@ -67,14 +67,14 @@ export function CalendarBase(
</Button>
</div>

<CalendarMonthContext
<CalendarContext
value={props}
onselectday={props.onSelect}
onfocusday={props.onFocus}
onhoverday={props.onHover}
>
<slot></slot>
</CalendarMonthContext>
</CalendarContext>
</div>
);
}
Expand All @@ -96,6 +96,10 @@ export const props = {
type: Function,
value: (date: Date) => false,
},
getPartsForDate: {
type: Function,
value: (date: Date): string => "",
},
firstDayOfWeek: {
type: Number,
value: (): DaysOfWeek => 1,
Expand Down
40 changes: 39 additions & 1 deletion src/calendar-date/calendar-date.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { CalendarMonth } from "../calendar-month/calendar-month.js";
import type { Pagination } from "../calendar-base/useCalendarBase.js";
import { CalendarDate } from "./calendar-date.js";
import { PlainYearMonth } from "../utils/temporal.js";
import { PlainDate, PlainYearMonth } from "../utils/temporal.js";
import { today, toDate } from "../utils/date.js";

type TestProps = {
Expand Down Expand Up @@ -802,4 +802,42 @@ describe("CalendarDate", () => {
expect(firstJan).to.have.attribute("aria-pressed", "true");
});
});

it("allows customizing day parts", async () => {
const available = new Set(["2020-01-10", "2020-01-11", "2020-01-12"]);
const almostGone = new Set(["2020-01-13", "2020-01-14"]);

const calendar = await mount(<Fixture value="2020-01-01" />);
calendar.getPartsForDate = function getPartsForDate(date: Date) {
const d = PlainDate.from(date).toString();

if (available.has(d)) return "available";
if (almostGone.has(d)) return "almost-gone";
return "";
};

await nextFrame();
const month = getMonth(calendar);

[
getDayButton(month, "10 January"),
getDayButton(month, "11 January"),
getDayButton(month, "12 January"),
].forEach((day) => {
expect(day.part.contains("available")).to.eq(
true,
`"available" not found in part: "${day.part.toString().trim()}"`
);
});

[
getDayButton(month, "13 January"),
getDayButton(month, "14 January"),
].forEach((day) => {
expect(day.part.contains("almost-gone")).to.eq(
true,
`"almost-gone" not found in part: "${day.part.toString().trim()}"`
);
});
});
});
16 changes: 8 additions & 8 deletions src/calendar-month/CalendarMonthContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,45 @@ import { createContext } from "atomico";
import type { PlainDate, PlainYearMonth } from "../utils/temporal.js";
import { today, type DaysOfWeek } from "../utils/date.js";

interface CalendarMonthContextBase {
interface CalendarContextBase {
min?: PlainDate;
max?: PlainDate;
firstDayOfWeek: DaysOfWeek;
isDateDisallowed?: (date: Date) => boolean;
getPartsForDate?: (date: Date) => string;
page: { start: PlainYearMonth; end: PlainYearMonth };
focusedDate: PlainDate;
showOutsideDays?: boolean;
locale?: string;
}

export interface CalendarDateContext extends CalendarMonthContextBase {
export interface CalendarDateContext extends CalendarContextBase {
type: "date";
value?: PlainDate;
}

export interface CalendarRangeContext extends CalendarMonthContextBase {
export interface CalendarRangeContext extends CalendarContextBase {
type: "range";
value: [PlainDate, PlainDate] | [];
}

export interface CalendarMultiContext extends CalendarMonthContextBase {
export interface CalendarMultiContext extends CalendarContextBase {
type: "multi";
value: PlainDate[];
}

export type CalendarMonthContextValue =
export type CalendarContextValue =
| CalendarDateContext
| CalendarRangeContext
| CalendarMultiContext;

const t = today();

export const CalendarMonthContext = createContext<CalendarMonthContextValue>({
export const CalendarContext = createContext<CalendarContextValue>({
type: "date",
firstDayOfWeek: 1,
isDateDisallowed: () => false,
focusedDate: t,
page: { start: t.toPlainYearMonth(), end: t.toPlainYearMonth() },
});

customElements.define("calendar-month-ctx", CalendarMonthContext);
customElements.define("calendar-ctx", CalendarContext);
8 changes: 4 additions & 4 deletions src/calendar-month/calendar-month.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
sendShiftPress,
} from "../utils/test.js";
import {
CalendarMonthContext,
CalendarContext,
type CalendarDateContext,
type CalendarMultiContext,
type CalendarRangeContext,
Expand All @@ -23,7 +23,7 @@ import { fixture } from "atomico/test-dom";
import { PlainDate } from "../utils/temporal.js";
import { toDate, today } from "../utils/date.js";

type MonthContextInstance = InstanceType<typeof CalendarMonthContext>;
type MonthContextInstance = InstanceType<typeof CalendarContext>;

interface TestPropsBase {
onselectday?: (e: CustomEvent<PlainDate>) => void;
Expand All @@ -46,7 +46,7 @@ function Fixture({
...props
}: Partial<DateTestProps | RangeTestProps | MultiTestProps>): VNodeAny {
return (
<CalendarMonthContext
<CalendarContext
onselectday={onselectday}
onfocusday={onfocusday}
dir={dir}
Expand All @@ -64,7 +64,7 @@ function Fixture({
}}
>
<CalendarMonth />
</CalendarMonthContext>
</CalendarContext>
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/calendar-month/calendar-month.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { c, css, useContext, useRef, type Host } from "atomico";
import { reset, vh } from "../utils/styles.js";
import { useCalendarMonth } from "./useCalendarMonth.js";
import { CalendarMonthContext } from "./CalendarMonthContext.js";
import { CalendarContext } from "./CalendarMonthContext.js";
import { toDate } from "../utils/date.js";

export const CalendarMonth = c(
Expand All @@ -12,7 +12,7 @@ export const CalendarMonth = c(
onFocusDay: CustomEvent<string>;
onHoverDay: CustomEvent<string>;
}> => {
const context = useContext(CalendarMonthContext);
const context = useContext(CalendarContext);
const table = useRef<HTMLTableElement>();
const calendar = useCalendarMonth({ props, context });

Expand Down
6 changes: 4 additions & 2 deletions src/calendar-month/useCalendarMonth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
today,
} from "../utils/date.js";
import type { PlainDate } from "../utils/temporal.js";
import type { CalendarMonthContextValue } from "./CalendarMonthContext.js";
import type { CalendarContextValue } from "./CalendarMonthContext.js";

const inRange = (date: PlainDate, min?: PlainDate, max?: PlainDate) =>
clamp(date, min, max) === date;
Expand All @@ -24,7 +24,7 @@ const dispatchOptions = { bubbles: true };

type UseCalendarMonthOptions = {
props: { offset: number };
context: CalendarMonthContextValue;
context: CalendarContextValue;
};

export function useCalendarMonth({ props, context }: UseCalendarMonthOptions) {
Expand Down Expand Up @@ -144,6 +144,8 @@ export function useCalendarMonth({ props, context }: UseCalendarMonthOptions) {
isDisallowed ? "disallowed" : ""
} ${
isToday ? "today" : ""
} ${
context.getPartsForDate?.(asDate) ?? ""
}`;

return {
Expand Down

0 comments on commit 4260e57

Please sign in to comment.