Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow custom day styles #64

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/src/pages/components/calendar-date.astro
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ import Link from "../../components/Link.astro";
<td><code>(date: Date) =&gt; boolean</code></td>
<td><code>() =&gt; false</code></td>
</tr>
<tr>
<td><code>getPartsForDate</code></td>
<td>-</td>
<td>
A function that takes a date and returns a string of CSS parts, allowing
custom styling for individual dates
</td>
<td><code>(date: Date) =&gt; string</code></td>
<td><code>() =&gt; ""</code></td>
</tr>
</Table>

<Heading level={2}>Events</Heading>
Expand Down
10 changes: 10 additions & 0 deletions docs/src/pages/components/calendar-multi.astro
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ import Link from "../../components/Link.astro";
<td><code>(date: Date) =&gt; boolean</code></td>
<td><code>() =&gt; false</code></td>
</tr>
<tr>
<td><code>getPartsForDate</code></td>
<td>-</td>
<td>
A function that takes a date and returns a string of CSS parts, allowing
custom styling for individual dates
</td>
<td><code>(date: Date) =&gt; string</code></td>
<td><code>() =&gt; ""</code></td>
</tr>
</Table>

<Heading level={2}>Events</Heading>
Expand Down
10 changes: 10 additions & 0 deletions docs/src/pages/components/calendar-range.astro
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ import Link from "../../components/Link.astro";
<td><code>(date: Date) =&gt; boolean</code></td>
<td><code>() =&gt; false</code></td>
</tr>
<tr>
<td><code>getPartsForDate</code></td>
<td>-</td>
<td>
A function that takes a date and returns a string of CSS parts, allowing
custom styling for individual dates
</td>
<td><code>(date: Date) =&gt; string</code></td>
<td><code>() =&gt; ""</code></td>
</tr>
</Table>

<Heading level={2}>Events</Heading>
Expand Down
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
Loading