diff --git a/source/app.tsx b/source/app.tsx
index a46508c..2807755 100644
--- a/source/app.tsx
+++ b/source/app.tsx
@@ -1,11 +1,16 @@
-// Third-party imports.
import {Component} from "preact";
+import {BigDate, Calendar} from "./components/exports.js";
+import {DateWrapper} from "./date/date.js";
export class App extends Component {
render() {
+ const today = new DateWrapper(new Date());
+
return (
<>
Today is:
+
+
>
);
}
diff --git a/source/components/calendar.tsx b/source/components/calendar.tsx
new file mode 100644
index 0000000..6bae9b2
--- /dev/null
+++ b/source/components/calendar.tsx
@@ -0,0 +1,82 @@
+import {Component} from "preact";
+import {type SharedProps} from "./shared.js";
+
+export class Calendar extends Component {
+ render() {
+ const {today} = this.props;
+
+ const dayNames = ["", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];
+ const currentWeekDayName = dayNames[today.dayOfTheWeek()];
+
+ // Create the row with the names of the day.
+ const dayNameRow = dayNames.map((name) => {
+ const classes = [
+ currentWeekDayName === name ? "current-week-day-name" : "",
+ name === "" ? "week-number" : "week-day-name",
+ ];
+ return {name}
;
+ });
+
+ // Create the start of the calendar and set it to the first day of the
+ // month.
+ const start = today.clone();
+ start.date.setDate(1);
+
+ // Subtract the amount of days in the week we are in from the start.
+ // Add 1 to account for Monday starting at 1.
+ const subtractDays = -start.dayOfTheWeek() + 1;
+
+ // If the subtraction ends up being 0 it means the first day of the month is
+ // a Monday, in which case we want to subtract a whole week instead.
+ start.addDays(subtractDays === 0 ? -7 : subtractDays);
+
+ const weekRows = [];
+
+ // Loop over 6 weeks to include in the calendar.
+ for (let weekCounter = 0; weekCounter < 6; weekCounter++) {
+ // Get the current week and add the week we're in to it.
+ const currentWeek = start.week() + weekCounter;
+
+ // Clone the start date and add the amount of weeks we've looped over.
+ const weekDay = start.clone();
+ weekDay.addDays(weekCounter * 7);
+
+ const currentWeekClasses = [
+ today.week() === weekDay.week() ? "current-week" : "",
+ "week-number",
+ ];
+
+ // Add the week number as the first column of the grid.
+ weekRows.push(
+ {currentWeek}
,
+ );
+
+ // Loop over each day in the week.
+ for (let dayCounter = 0; dayCounter < 7; dayCounter++) {
+ // Create CSS classes for the current day, weekday and month.
+ const classes = [
+ today.iso().startsWith(weekDay.iso().slice(0, 10))
+ ? "current-day"
+ : "",
+ today.week() === weekDay.week() ? "current-week-day" : "",
+ today.date.getMonth() === weekDay.date.getMonth()
+ ? "current-month"
+ : "other-month",
+ ];
+
+ // Add the new week day to the list and advance it by a day.
+ weekRows.push(
+ {weekDay.paddedDay()}
,
+ );
+ weekDay.addDays(1);
+ }
+ }
+
+ return (
+
+ {dayNameRow}
+ {weekRows}
+
+ );
+ }
+}
diff --git a/source/components/exports.ts b/source/components/exports.ts
new file mode 100644
index 0000000..8fe1e81
--- /dev/null
+++ b/source/components/exports.ts
@@ -0,0 +1,2 @@
+export * from "./big-date.js";
+export * from "./calendar.js";
diff --git a/source/global.scss b/source/global.scss
new file mode 100644
index 0000000..03ef560
--- /dev/null
+++ b/source/global.scss
@@ -0,0 +1,97 @@
+blockquote,
+code,
+h1,
+h2,
+h3,
+h4,
+h5,
+li,
+ol,
+p,
+pre,
+ul {
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ font-size: 62.5%;
+}
+
+body {
+ --base: #24273a;
+ --surface-0: #363a4f;
+ --subtext-0: #a5adcb;
+ --overlay-0: #6e738d;
+ --text: #cad3f5;
+ --spacing-1: 32px;
+
+ background-color: var(--base);
+ color: var(--text);
+ font-size: 2rem;
+}
+
+.preact-root {
+ border: 2px solid var(--overlay-0);
+ min-height: 100vh;
+ min-width: 100vw;
+}
+
+.calendar,
+.big-date,
+.subtitle {
+ margin-left: var(--spacing-1);
+}
+
+.subtitle {
+ margin-top: var(--spacing-1);
+}
+
+.big-date {
+ font-size: 4rem;
+
+ .dash {
+ color: var(--overlay-0);
+ }
+}
+
+.calendar {
+ border: 2px solid var(--text);
+ display: inline-grid;
+ font-family: monospace;
+ grid-template-columns: repeat(8, 1fr);
+ width: fit-content;
+
+ p {
+ padding: 4px;
+ }
+
+ .current-week,
+ .current-week-day {
+ background-color: var(--surface-0);
+ }
+
+ .current-day,
+ .current-week-day-name {
+ background-color: var(--text);
+ color: var(--base);
+ }
+
+ .current-month,
+ .current-week,
+ .current-week-day-name {
+ font-weight: bold;
+ }
+
+ .other-month {
+ color: var(--overlay-0);
+ }
+
+ .week-day-name {
+ border-bottom: 2px solid var(--text);
+ }
+
+ .week-number {
+ border-right: 2px solid var(--text);
+ }
+}