@gridui/calendar 0.0.0-stage → 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,109 @@
1
- # Temporary Holding Version
1
+ # @gridui/calendar
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Composable scheduling views. The family has no provider requirement and no dependency on DatePicker or Grid. Applications own events, timezone conversion, editing, resource filtering and persistence.
4
+
5
+ ```tsx
6
+ import "@gridui/theme/styles.css";
7
+ import "@gridui/button/styles.css";
8
+ import "@gridui/calendar/styles.css";
9
+
10
+ import { Calendar, CalendarDayView, CalendarToolbar, useCalendar } from "@gridui/calendar";
11
+
12
+ const state = useCalendar({ defaultDate: "2026-11-02" });
13
+
14
+ <Calendar frame="outline">
15
+ <CalendarToolbar
16
+ date={state.date}
17
+ view={state.view}
18
+ onNavigate={state.navigate}
19
+ onViewChange={state.setView}
20
+ views={["day"]}
21
+ />
22
+ <CalendarDayView
23
+ date={state.date}
24
+ events={events}
25
+ resources={resources}
26
+ onEventSelect={openEditor}
27
+ />
28
+ </Calendar>;
29
+ ```
30
+
31
+ ## Components
32
+
33
+ - `Calendar` is an optional surface. `frame="none"` is the default; `outline` adds one outer border. It adds no seams between children.
34
+ - `CalendarDayView` displays one date. Optional `resources` create one column per declared resource; without resources all events share one column. When resources are supplied, events without a matching `resourceId` are excluded. Resource IDs must be unique and the list must not be empty.
35
+ - `CalendarWeekView` displays 1–7 consecutive dates from `weekStartsOn` (0 = Sunday, default 1). `days={5}` displays a work week when the week starts on Monday. Resource filtering remains with the caller.
36
+ - `CalendarMonthView` displays six weeks. `onDateSelect` handles date and overflow actions. `maxEvents` defaults to 3; without a drill-down handler all events remain reachable instead of being silently hidden.
37
+ - `CalendarAgendaView` displays the next `days` dates (default 7), omitting empty dates. `empty` and `allDayLabel` accept application content.
38
+ - `CalendarEvent` is a native button for custom event compositions. CVA selects its structural `appearance` (`block`, `compact`); `colors` supplies presentation values. `selected` and native button props remain independent of any event store.
39
+ - `CalendarToolbar` accepts explicit state/callbacks, optional view choices, localized labels, a title override and children for application actions. It owns no frame or separator. Arrow labels and view names default to English.
40
+ - `useCalendar` is optional. It supports controlled/uncontrolled dates and views and previous/next navigation. A required `defaultDate` makes initial rendering deterministic. Month navigation clamps the day to the target month's last day. Day navigation moves one day; week/agenda navigation moves seven. Callers with a different agenda length can supply their own navigation callback.
41
+
42
+ All views forward native div props and refs. They can be rendered independently and in any order. `renderEvent`, `getEventLabel` and `onEventSelect` receive the original event plus its visible date, view and cross-day continuation flags. `selectedEventId` is controlled by the caller. A custom renderer supplies button content; do not nest interactive elements inside it. `CalendarEvent` can instead be composed directly for another interaction structure.
43
+
44
+ Time views accept integer `startHour`/`endHour` within 0–24 (defaults 8–18), a positive `hourHeight` in pixels (default 56), and `formatTime`. Timed overlaps use separate columns; adjacent exclusive endpoints reuse a column. Optional `onTimeSelect` enables keyboard-accessible hour slots; `getTimeLabel` can localize their accessible names. All-day events occupy the matching date/resource column. Narrow time columns retain full accessible event labels; Agenda offers a readable alternative for dense schedules.
45
+
46
+ ## Application-owned composition
47
+
48
+ The caller owns the active view and renders the matching component. `CalendarToolbar` only emits callbacks and `useCalendar` only helps manage state; neither is required. Existing Button or Tabs controls can switch views directly:
49
+
50
+ ```tsx
51
+ const [view, setView] = useState<"day" | "week">("day");
52
+ const [selectedEvent, setSelectedEvent] = useState<CalendarEventData | null>(null);
53
+ const schedule = { date, events, onEventSelect: setSelectedEvent };
54
+
55
+ <>
56
+ <Button aria-pressed={view === "day"} onClick={() => setView("day")}>Day</Button>
57
+ <Button aria-pressed={view === "week"} onClick={() => setView("week")}>Week</Button>
58
+ {view === "day" ? <CalendarDayView {...schedule} /> : <CalendarWeekView {...schedule} />}
59
+ {selectedEvent && <EventEditor event={selectedEvent} onClose={() => setSelectedEvent(null)} />}
60
+ </>;
61
+ ```
62
+
63
+ `EventEditor` is an application component. Calendar never opens an overlay, edits an event, or interprets a booking status. The caller can use an ID to look up its full business record when an event is selected.
64
+
65
+ Both `CalendarEventData.colors` and `CalendarEvent.colors` accept `CalendarEventColors`:
66
+
67
+ ```tsx
68
+ colors: {
69
+ accent: "var(--gridui-warning-border)",
70
+ background: "var(--gridui-warning-background)",
71
+ foreground: "var(--gridui-warning-foreground)",
72
+ }
73
+ ```
74
+
75
+ Each property is optional and accepts a CSS color, including theme variables. `accent` controls the event's leading edge and selected outline. It defaults to the theme accent; the default background blends that accent into the theme background, and the default foreground uses the theme text color. Explicit foreground colors also apply to time labels. All views preserve these colors for timed and all-day segments. Applications map business state or categories to colors and supply suitable foreground/background pairs; Calendar has no status-to-color mapping. Native `style` and `className` remain available on standalone `CalendarEvent`.
76
+
77
+ ## Date and event contract
78
+
79
+ `CalendarDate` is a Gregorian `YYYY-MM-DD` civil date. Timed event `start` and `end` use `YYYY-MM-DDTHH:mm`; all-day events set `allDay: true` and use date-only values. End is **exclusive** in both cases. An all-day event on November 2 ends on November 3. A midnight end does not create an event on the following date. Overnight and multi-day events are segmented across views without changing the original event.
80
+
81
+ Values have no UTC offset or implicit timezone conversion. Convert instants into the calendar's display timezone before providing them. This keeps browser timezone and daylight-saving changes from shifting the chosen civil date. Time geometry depicts wall-clock hours, not elapsed duration across timezone transitions. Events require nonempty unique IDs and positive durations; malformed dates/times throw `RangeError`.
82
+
83
+ `locale` defaults to `en-US` and controls date captions. Applications supply `today` to show a current-date indicator; the library does not read the clock during rendering. Status names, tooltips, timezone labels, recurrence, validation against a booking service, drag/drop, resizing and editors are application concerns.
84
+
85
+ ## Grid and border ownership
86
+
87
+ Load `@gridui/grid/styles.css` when using this composition:
88
+
89
+ ```tsx
90
+ <FrameSection>
91
+ <Grid columns={{ base: 1, lg: 4 }} frame="internal">
92
+ <GridItem>{dateNavigation}</GridItem>
93
+ <GridItem span={{ base: 1, lg: 3 }}>
94
+ <Calendar>
95
+ <Split direction="column">
96
+ <section className="p-gridui-16">{toolbar}</section>
97
+ <section><CalendarWeekView date={date} events={events} /></section>
98
+ </Split>
99
+ </Calendar>
100
+ </GridItem>
101
+ </Grid>
102
+ </FrameSection>
103
+ ```
104
+
105
+ FrameSection owns the outside frame, Grid owns column/row seams, and Split owns the seam between toolbar and schedule. Calendar views paint only internal date/time separators. Their roots have no outer borders. Put Split around region wrappers, not directly around controls with functional outlines. Avoid nesting `Calendar frame="outline"` inside an already framed cell unless an inset card is intentional.
106
+
107
+ CSS owns the time-grid geometry, event positioning, cell lines and responsive reflow. CVA owns surface and structural event variants; caller colors are scoped to each event. Tailwind owns ordinary alignment, spacing and typography. No Layout private classes, DOM inspection of a parent grid, or negative border offsets are required.
108
+
109
+ See [component ownership](../../docs/component-ownership.md) and [release history](.changeset/history/).
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace Calendar
5
+ * @description Calendar
6
+ */
7
+ import type { ComponentPropsWithRef, FC } from "react";
8
+ export type CalendarProps = ComponentPropsWithRef<"div"> & {
9
+ readonly frame?: "none" | "outline";
10
+ };
11
+ /** Optional surface. Views and toolbar have no dependency on this wrapper. */
12
+ export declare const Calendar: FC<CalendarProps>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace Calendar
5
+ * @description Style
6
+ */
7
+ export declare const calendarStyles: (props?: ({
8
+ frame?: "none" | "outline" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarAgendaView
5
+ * @description Calendar Agenda View
6
+ */
7
+ import type { CalendarViewOptions } from "../shared/types";
8
+ import type { ComponentPropsWithRef, FC, ReactNode } from "react";
9
+ export type CalendarAgendaViewProps = Omit<ComponentPropsWithRef<"div">, "children"> & CalendarViewOptions & {
10
+ readonly days?: number;
11
+ readonly empty?: ReactNode;
12
+ readonly allDayLabel?: string;
13
+ readonly formatTime?: (minute: number) => string;
14
+ };
15
+ export declare const CalendarAgendaView: FC<CalendarAgendaViewProps>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarDayView
5
+ * @description Calendar Day View
6
+ */
7
+ import { type TimeGridProps } from "../shared/time-grid";
8
+ import type { CalendarResource } from "../shared/types";
9
+ import type { FC } from "react";
10
+ export type CalendarDayViewProps = Omit<TimeGridProps, "columns" | "view"> & {
11
+ readonly resources?: readonly CalendarResource[];
12
+ };
13
+ export declare const CalendarDayView: FC<CalendarDayViewProps>;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarEvent
5
+ * @description Calendar Event
6
+ */
7
+ import type { CalendarEventColors } from "../shared/types";
8
+ import type { ComponentPropsWithRef, FC } from "react";
9
+ export type CalendarEventProps = ComponentPropsWithRef<"button"> & {
10
+ readonly colors?: CalendarEventColors | undefined;
11
+ readonly appearance?: "block" | "compact";
12
+ readonly selected?: boolean;
13
+ };
14
+ export declare const CalendarEvent: FC<CalendarEventProps>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarEvent
5
+ * @description Style
6
+ */
7
+ export declare const eventStyles: (props?: ({
8
+ appearance?: "block" | "compact" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarMonthView
5
+ * @description Calendar Month View
6
+ */
7
+ import type { CalendarDate, CalendarViewOptions } from "../shared/types";
8
+ import type { ComponentPropsWithRef, FC } from "react";
9
+ export type CalendarMonthViewProps = Omit<ComponentPropsWithRef<"div">, "children"> & CalendarViewOptions & {
10
+ readonly weekStartsOn?: number;
11
+ readonly maxEvents?: number;
12
+ readonly onDateSelect?: (date: CalendarDate) => void;
13
+ readonly getMoreLabel?: (count: number, date: CalendarDate) => string;
14
+ };
15
+ export declare const CalendarMonthView: FC<CalendarMonthViewProps>;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarToolbar
5
+ * @description Calendar Toolbar
6
+ */
7
+ import type { CalendarDate, CalendarView } from "../shared/types";
8
+ import type { ComponentPropsWithRef, FC, ReactNode } from "react";
9
+ export type CalendarToolbarLabels = {
10
+ readonly previous: string;
11
+ readonly next: string;
12
+ readonly today: string;
13
+ readonly views: string;
14
+ readonly day: string;
15
+ readonly week: string;
16
+ readonly month: string;
17
+ readonly agenda: string;
18
+ };
19
+ export type CalendarToolbarProps = Omit<ComponentPropsWithRef<"div">, "title"> & {
20
+ readonly date: CalendarDate;
21
+ readonly view: CalendarView;
22
+ readonly onNavigate: (direction: -1 | 1) => void;
23
+ readonly onViewChange: (view: CalendarView) => void;
24
+ readonly onToday?: () => void;
25
+ readonly locale?: string;
26
+ readonly weekStartsOn?: number;
27
+ readonly views?: readonly CalendarView[];
28
+ readonly labels?: Partial<CalendarToolbarLabels>;
29
+ readonly title?: ReactNode;
30
+ };
31
+ export declare const CalendarToolbar: FC<CalendarToolbarProps>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace CalendarWeekView
5
+ * @description Calendar Week View
6
+ */
7
+ import { type TimeGridProps } from "../shared/time-grid";
8
+ import type { FC } from "react";
9
+ export type CalendarWeekViewProps = Omit<TimeGridProps, "columns" | "view"> & {
10
+ readonly weekStartsOn?: number;
11
+ readonly days?: number;
12
+ };
13
+ export declare const CalendarWeekView: FC<CalendarWeekViewProps>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Calendar
4
+ * @namespace Root
5
+ * @description Index
6
+ */
7
+ export type { CalendarProps } from "./calendar/calendar";
8
+ export { Calendar } from "./calendar/calendar";
9
+ export type { CalendarAgendaViewProps } from "./calendar-agenda-view/calendar-agenda-view";
10
+ export { CalendarAgendaView } from "./calendar-agenda-view/calendar-agenda-view";
11
+ export type { CalendarDayViewProps } from "./calendar-day-view/calendar-day-view";
12
+ export { CalendarDayView } from "./calendar-day-view/calendar-day-view";
13
+ export type { CalendarEventProps } from "./calendar-event/calendar-event";
14
+ export { CalendarEvent } from "./calendar-event/calendar-event";
15
+ export type { CalendarMonthViewProps } from "./calendar-month-view/calendar-month-view";
16
+ export { CalendarMonthView } from "./calendar-month-view/calendar-month-view";
17
+ export type { CalendarToolbarLabels, CalendarToolbarProps } from "./calendar-toolbar/calendar-toolbar";
18
+ export { CalendarToolbar } from "./calendar-toolbar/calendar-toolbar";
19
+ export type { CalendarWeekViewProps } from "./calendar-week-view/calendar-week-view";
20
+ export { CalendarWeekView } from "./calendar-week-view/calendar-week-view";
21
+ export type { TimeSelection as CalendarTimeSelection } from "./shared/time-grid";
22
+ export type { CalendarDate, CalendarEventColors, CalendarEventContext, CalendarEventData, CalendarResource, CalendarTimeOptions, CalendarView, CalendarViewOptions } from "./shared/types";
23
+ export type { UseCalendarOptions } from "./use-calendar/use-calendar";
24
+ export { useCalendar } from "./use-calendar/use-calendar";