react-attendance-calendar 2.4.4 → 2.4.6

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,44 +1,33 @@
1
1
  # React Attendance Calendar
2
2
 
3
- A modern, responsive, and highly customizable attendance calendar component for React with full TypeScript support. Perfect for tracking employee attendance, student presence, or any date-based status system.
3
+ A modern, responsive React attendance calendar with a **compound component** architecture. Style it with classes, swap out navigation buttons, render custom cells or just drop in the pre-composed version and go.
4
4
 
5
- ## Features
5
+ ## Features
6
6
 
7
- - 📅 **Responsive design** - Automatically switches between 7-14 columns based on container width
8
- - 🎨 **Fully customizable** - Complete control with Tailwind CSS classes
9
- - 🖱️ **Interactive** - Date click callbacks with hover effects
10
- - 📱 **Mobile-friendly** - Fluid cells scale with container no overflow on any screen size
11
- - 🔧 **TypeScript support** - Full type safety and IntelliSense
12
- - 🎭 **Beautiful defaults** - Modern design with emerald/amber color scheme
13
- - 📊 **Multi-month support** - Provide attendance data for multiple months at once
14
- - 🔄 **Flexible data format** - Support both single month and array of months
15
- - ⚡ **Auto-initialization** - Defaults to current month if no view provided
16
- - 🎯 **Smart navigation** - Seamless month/year transitions
17
- - 🗓️ **Today highlight** - Current date is highlighted; style it with `todayCellClassName` (merged last so it wins over present/absent/cell classes)
18
- - 📐 **Flexible header** - Position month title left, center, or right
7
+ - **Compound components** compose `Calendar.Root`, `Header`, `Title`, `PrevTrigger`, `NextTrigger`, `WeekDays`, and `Grid` any way you like
8
+ - **Pre-composed default** `AttendanceCalendar` works out of the box with zero config
9
+ - **`renderCell`** full control over every cell's markup and style
10
+ - **`useCalendar()` hook** headless access to all calendar state for completely custom UIs
11
+ - **`classNames` object** one clean prop for `cell`, `present`, `absent`, `today`, `outside` styles
12
+ - **Responsive** — auto-switches between 7 and 14 columns based on container width
13
+ - **TypeScript** full type safety and IntelliSense
14
+ - **Multi-month data** provide attendance for multiple months at once
19
15
 
20
- ## 📦 Installation
16
+ ## Installation
21
17
 
22
18
  ```bash
23
19
  npm install react-attendance-calendar
24
20
  ```
25
21
 
26
- ### 🎨 CSS Setup
27
-
28
- **Simply import the CSS in your app:**
22
+ Import the CSS once in your app entry:
29
23
 
30
24
  ```tsx
31
- // In your main app file (e.g., App.tsx, main.tsx, or _app.tsx)
32
25
  import "react-attendance-calendar/styles.css";
33
26
  ```
34
27
 
35
- **That's it!** The component will render with beautiful default styling.
36
-
37
- > **Note:** No additional setup required. The package includes pre-compiled CSS. If you're using Tailwind CSS v4 in your project, you can customize the component further using the `className` props.
38
-
39
- ## 🚀 Usage
28
+ > The package ships pre-compiled CSS. If you use Tailwind CSS v4, you can further customize via `className` and `classNames` props.
40
29
 
41
- ### Basic Example
30
+ ## Quick Start
42
31
 
43
32
  ```tsx
44
33
  import { useState } from "react";
@@ -48,351 +37,325 @@ import "react-attendance-calendar/styles.css";
48
37
  function App() {
49
38
  const [view, setView] = useState({ year: 2024, monthIndex: 0 });
50
39
 
51
- return <AttendanceCalendar view={view} onChangeView={setView} />;
52
- }
53
- ```
54
-
55
- ### Minimal Example (Auto-initialize to current month)
56
-
57
- ```tsx
58
- import { AttendanceCalendar } from "react-attendance-calendar";
59
- import "react-attendance-calendar/styles.css";
60
-
61
- function App() {
62
- const [view, setView] = useState();
40
+ const data = {
41
+ year: 2024,
42
+ monthIndex: 0,
43
+ presentDays: new Set([1, 2, 3, 5, 8, 9, 10]),
44
+ absentDays: new Set([4, 11]),
45
+ };
63
46
 
64
- return <AttendanceCalendar onChangeView={setView} />;
47
+ return (
48
+ <AttendanceCalendar
49
+ view={view}
50
+ onChangeView={setView}
51
+ attendanceData={data}
52
+ onDateClick={(day, month, year) => console.log(day, month, year)}
53
+ />
54
+ );
65
55
  }
66
56
  ```
67
57
 
68
- ### With Single Month Attendance Data
58
+ ## Usage
69
59
 
70
- ```tsx
71
- import { AttendanceCalendar } from "react-attendance-calendar";
72
- import "react-attendance-calendar/styles.css";
60
+ ### Pre-composed (simple)
73
61
 
74
- const attendanceData = {
75
- year: 2024,
76
- monthIndex: 0,
77
- presentDays: new Set([1, 2, 3, 5, 8, 9, 10]),
78
- absentDays: new Set([4, 11]),
79
- };
62
+ The `AttendanceCalendar` component is a ready-to-use calendar with sensible defaults. Pass a `classNames` object to customize cell styles without touching the layout.
80
63
 
64
+ ```tsx
81
65
  <AttendanceCalendar
82
66
  view={view}
83
67
  onChangeView={setView}
84
- attendanceData={attendanceData}
85
- onDateClick={(day, month, year) => console.log(day, month, year)}
86
- />;
68
+ attendanceData={data}
69
+ classNames={{
70
+ cell: "rounded-full",
71
+ present: "bg-teal-500 shadow-md",
72
+ absent: "bg-rose-500",
73
+ today: "ring-2 ring-blue-400",
74
+ outside: "opacity-20",
75
+ }}
76
+ />
87
77
  ```
88
78
 
89
- ### With Multiple Months Attendance Data
79
+ ### Compound components (full control)
80
+
81
+ Build your own layout with `Calendar.*` components. Place the title, navigation buttons, weekday headers, and grid wherever you want.
90
82
 
91
83
  ```tsx
92
- import { AttendanceCalendar } from "react-attendance-calendar";
84
+ import { Calendar } from "react-attendance-calendar";
93
85
  import "react-attendance-calendar/styles.css";
94
86
 
95
- // Provide data for multiple months at once
96
- const attendanceData = [
97
- // January 2024
98
- {
99
- year: 2024,
100
- monthIndex: 0,
101
- presentDays: new Set([
102
- 1, 2, 3, 5, 8, 9, 10, 12, 15, 16, 17, 19, 22, 23, 24, 26, 29, 30, 31,
103
- ]),
104
- absentDays: new Set([4, 11, 18, 25]),
105
- },
106
- // February 2025
107
- {
108
- year: 2025,
109
- monthIndex: 1,
110
- presentDays: new Set([
111
- 1, 2, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 26, 27, 28,
112
- ]),
113
- absentDays: new Set([3, 10, 17, 24]),
114
- },
115
- ];
87
+ function MyCalendar() {
88
+ const [view, setView] = useState({ year: 2024, monthIndex: 0 });
116
89
 
117
- <AttendanceCalendar
118
- view={view}
119
- onChangeView={setView}
120
- attendanceData={attendanceData}
121
- onDateClick={(day, month, year) => console.log(day, month, year)}
122
- />;
90
+ return (
91
+ <Calendar.Root
92
+ view={view}
93
+ onChangeView={setView}
94
+ attendanceData={data}
95
+ onDateClick={(day, month, year) => console.log(day, month, year)}
96
+ >
97
+ <Calendar.Header>
98
+ <Calendar.Title className="text-indigo-700" />
99
+ <div className="flex gap-2">
100
+ <Calendar.PrevTrigger className="rounded-full bg-indigo-500 text-white">
101
+
102
+ </Calendar.PrevTrigger>
103
+ <Calendar.NextTrigger className="rounded-full bg-indigo-500 text-white">
104
+
105
+ </Calendar.NextTrigger>
106
+ </div>
107
+ </Calendar.Header>
108
+ <Calendar.WeekDays dayClassName="text-indigo-400" />
109
+ <Calendar.Grid
110
+ classNames={{
111
+ present: "bg-indigo-500",
112
+ absent: "bg-pink-500",
113
+ }}
114
+ />
115
+ </Calendar.Root>
116
+ );
117
+ }
123
118
  ```
124
119
 
125
- ### Custom Month Title Position
120
+ ### Custom title format
126
121
 
127
- ```tsx
128
- // Center (default) — [←] January 2024 [→]
129
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="center" />
122
+ Use `format` for full control over the title markup, or keep the default layout and style the month (`className` on the `<h2>`) and year (`yearClassName` on the year span) separately.
130
123
 
131
- // Left January 2024 [← →]
132
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="left" />
124
+ **Default title with separate year styling**
133
125
 
134
- // Right [← →] January 2024
135
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="right" />
136
- ```
137
-
138
- ### Custom Styling
126
+ `className` applies to the whole heading (`<h2>`). `yearClassName` applies only to the year number and overrides the default `text-slate-500` (merged with `tailwind-merge`, so a new `text-*` class wins).
139
127
 
140
128
  ```tsx
141
- <AttendanceCalendar
142
- view={view}
143
- onChangeView={setView}
144
- presentCellClassName="bg-blue-500 text-white"
145
- absentCellClassName="bg-red-500 text-white"
146
- cellClassName="rounded-full"
129
+ <Calendar.Title
130
+ className="text-indigo-900"
131
+ yearClassName="text-indigo-600"
147
132
  />
148
133
  ```
149
134
 
150
- ### Today cell (`todayCellClassName`)
151
-
152
- The current calendar date (“today”) gets default emphasis (dark slate when the day is neither present nor absent; a ring when it is present or absent). Pass **`todayCellClassName`** with Tailwind utilities to fully control that cell. These classes are **merged last** on the cell, so they override `cellClassName`, `presentCellClassName`, and `absentCellClassName` for today only.
135
+ **Fully custom title**
153
136
 
154
137
  ```tsx
155
- <AttendanceCalendar
156
- view={view}
157
- onChangeView={setView}
158
- attendanceData={attendanceData}
159
- presentCellClassName="bg-emerald-500 text-white"
160
- todayCellClassName="ring-4 ring-violet-500 ring-offset-2 scale-105 bg-violet-600 text-white"
138
+ <Calendar.Title
139
+ format={(monthName, year) => (
140
+ <span className="text-lg font-medium">
141
+ {monthName} / {year}
142
+ </span>
143
+ )}
161
144
  />
162
145
  ```
163
146
 
164
- ### Custom Cell Sizes
147
+ ### Custom cell rendering
165
148
 
166
- ```tsx
167
- // Square cells with custom size
168
- <AttendanceCalendar
169
- view={view}
170
- onChangeView={setView}
171
- cellSize={60} // 60px x 60px cells
172
- />
149
+ Use `renderCell` on `Calendar.Grid` (or the pre-composed `AttendanceCalendar`) for complete control over each cell's markup. The callback receives a `CellData` object with all the state you need.
173
150
 
174
- // Custom width and height
175
- <AttendanceCalendar
176
- view={view}
177
- onChangeView={setView}
178
- cellWidth={80} // 80px wide
179
- cellHeight={50} // 50px tall
180
- />
181
-
182
- // Small compact calendar
183
- <AttendanceCalendar
184
- view={view}
185
- onChangeView={setView}
186
- cellSize={32} // 32px x 32px cells
187
- cellClassName="text-xs"
151
+ ```tsx
152
+ <Calendar.Grid
153
+ renderCell={(cell) => (
154
+ <div
155
+ className={`w-full aspect-square grid place-items-center rounded-xl text-sm ${
156
+ cell.isPresent
157
+ ? "bg-green-100 text-green-700"
158
+ : cell.isAbsent
159
+ ? "bg-red-100 text-red-700"
160
+ : cell.isToday
161
+ ? "bg-blue-600 text-white"
162
+ : "text-slate-600"
163
+ }`}
164
+ >
165
+ {cell.day}
166
+ {cell.isPresent && <span className="text-[10px]">✓</span>}
167
+ {cell.isAbsent && <span className="text-[10px]">✗</span>}
168
+ </div>
169
+ )}
188
170
  />
189
171
  ```
190
172
 
191
- ### Complete Example with Custom Styling
173
+ ### Headless with `useCalendar()`
174
+
175
+ For a completely custom UI, use the hook inside a `Calendar.Root`:
192
176
 
193
177
  ```tsx
194
- import { useState } from "react";
195
- import {
196
- AttendanceCalendar,
197
- type MonthView,
198
- type AttendanceData,
199
- } from "react-attendance-calendar";
200
- import "react-attendance-calendar/styles.css";
178
+ import { Calendar, useCalendar } from "react-attendance-calendar";
179
+
180
+ function HeadlessCalendar() {
181
+ const { view, monthName, goPrev, goNext, cells, currentMonthData, today, columns } =
182
+ useCalendar();
183
+
184
+ // Build any UI you want with full access to calendar state
185
+ return <div>{/* your custom markup */}</div>;
186
+ }
201
187
 
202
188
  function App() {
203
- const [view, setView] = useState<MonthView>({
204
- year: 2024,
205
- monthIndex: 0, // January
206
- });
207
-
208
- // Sample attendance data for multiple months
209
- const attendanceData: AttendanceData = [
210
- // January 2024
211
- {
212
- year: 2024,
213
- monthIndex: 0,
214
- presentDays: new Set([
215
- 1, 2, 3, 5, 8, 9, 10, 12, 15, 16, 17, 19, 22, 23, 24, 26, 29, 30, 31,
216
- ]),
217
- absentDays: new Set([4, 11, 18, 25]),
218
- },
219
- // February 2025
220
- {
221
- year: 2025,
222
- monthIndex: 1,
223
- presentDays: new Set([
224
- 1, 2, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 26, 27, 28,
225
- ]),
226
- absentDays: new Set([3, 10, 17, 24]),
227
- },
228
- ];
229
-
230
- const handleDateClick = (day: number, month: number, year: number) => {
231
- console.log(`Clicked on ${day}/${month + 1}/${year}`);
232
- // Your custom logic here
233
- };
189
+ const [view, setView] = useState({ year: 2024, monthIndex: 0 });
234
190
 
235
191
  return (
236
- <div className="max-w-4xl mx-auto p-4">
237
- <AttendanceCalendar
238
- view={view}
239
- onChangeView={setView}
240
- attendanceData={attendanceData}
241
- onDateClick={handleDateClick}
242
- showNavigation={true}
243
- showWeekdayHeaders={true}
244
- // Custom styling with className props
245
- cellClassName="rounded-full"
246
- presentCellClassName="bg-green-500 text-white shadow-lg"
247
- absentCellClassName="bg-red-500 text-white border-2 border-red-300"
248
- navigationButtonClassName="bg-blue-500 text-white hover:bg-blue-600"
249
- monthTitleClassName="text-3xl text-purple-600"
250
- containerClassName="border border-gray-200 rounded-lg p-4"
251
- />
252
- </div>
192
+ <Calendar.Root view={view} onChangeView={setView} attendanceData={data}>
193
+ <HeadlessCalendar />
194
+ </Calendar.Root>
253
195
  );
254
196
  }
255
-
256
- export default App;
257
197
  ```
258
198
 
259
- ## 📚 Props
260
-
261
- | Prop | Type | Required | Description |
262
- | --------------------------- | ---------------------------- | -------- | -------------------------------------------------- |
263
- | `view` | `MonthView` | ❌ | Current month and year (defaults to current month) |
264
- | `onChangeView` | `(view: MonthView) => void` | ✅ | Month navigation callback |
265
- | `attendanceData` | `AttendanceData` | ❌ | Present/absent days data (single month or array) |
266
- | `onDateClick` | `(day, month, year) => void` | ❌ | Date click callback |
267
- | `monthTitlePosition` | `'left' \| 'center' \| 'right'` | ❌ | Position of the month title (default: `'center'`) |
268
- | `showNavigation` | `boolean` | ❌ | Show nav arrows (default: `true`) |
269
- | `showWeekdayHeaders` | `boolean` | ❌ | Show weekday headers (default: `true`) |
270
- | `cellSize` | `number` | ❌ | Size in pixels for all calendar cells (square) |
271
- | `cellHeight` | `number` | ❌ | Height in pixels for calendar cells |
272
- | `cellWidth` | `number` | ❌ | Width in pixels for calendar cells |
273
- | `className` | `string` | ❌ | Additional classes for root element |
274
- | `cellClassName` | `string` | ❌ | Custom classes for all cells |
275
- | `presentCellClassName` | `string` | ❌ | Custom classes for present days |
276
- | `absentCellClassName` | `string` | ❌ | Custom classes for absent days |
277
- | `navigationButtonClassName` | `string` | ❌ | Custom classes for nav buttons |
278
- | `monthTitleClassName` | `string` | ❌ | Custom classes for month title |
279
- | `weekdayHeaderClassName` | `string` | ❌ | Custom classes for weekday headers |
280
- | `containerClassName` | `string` | ❌ | Custom classes for main container |
281
- | `todayCellClassName` | `string` | ❌ | Classes for **today’s** cell only; merged **last** so they override other cell props |
282
-
283
- ### TypeScript
284
-
285
- ```typescript
286
- type MonthView = {
287
- year: number; // e.g., 2024
288
- monthIndex: number; // 0-11 (0 = January)
289
- };
199
+ ### Custom cell sizes
290
200
 
291
- type MonthAttendanceData = {
292
- year: number;
293
- monthIndex: number;
294
- presentDays: Set<number>; // Day numbers 1-31
295
- absentDays: Set<number>; // Day numbers 1-31
296
- };
201
+ ```tsx
202
+ // Square cells
203
+ <AttendanceCalendar view={view} onChangeView={setView} cellSize={50} />
297
204
 
298
- // Support both single month and multiple months
299
- type AttendanceData = MonthAttendanceData | MonthAttendanceData[];
205
+ // Custom width and height
206
+ <AttendanceCalendar view={view} onChangeView={setView} cellWidth={80} cellHeight={50} />
300
207
 
301
- type MonthTitlePosition = "left" | "center" | "right";
208
+ // Compact
209
+ <AttendanceCalendar
210
+ view={view}
211
+ onChangeView={setView}
212
+ cellSize={32}
213
+ classNames={{ cell: "rounded-full text-xs" }}
214
+ />
302
215
  ```
303
216
 
304
- ## 🎨 Styling
217
+ ### Multi-month data
305
218
 
306
- The component uses Tailwind CSS classes with a modern design system:
219
+ Pass an array to `attendanceData` to pre-load multiple months. Navigation between loaded months is instant.
307
220
 
308
- ### Default Theme
221
+ ```tsx
222
+ const data: AttendanceData = [
223
+ {
224
+ year: 2024,
225
+ monthIndex: 0,
226
+ presentDays: new Set([1, 2, 3, 5, 8, 9, 10]),
227
+ absentDays: new Set([4, 11]),
228
+ },
229
+ {
230
+ year: 2024,
231
+ monthIndex: 1,
232
+ presentDays: new Set([1, 2, 5, 6, 7]),
233
+ absentDays: new Set([3, 4, 8]),
234
+ },
235
+ ];
309
236
 
310
- - **Present days**: Emerald green (`emerald-500`) with white text
311
- - **Absent days**: Amber orange (`amber-500`) with white text
312
- - **Regular days**: Slate gray (`slate-700`) with light border
313
- - **Today** (not present/absent): Dark slate background (`slate-900`) with white text; use `todayCellClassName` to replace or extend
314
- - **Today** (present/absent): Same as that status, plus a subtle ring; override with `todayCellClassName`
315
- - **Navigation**: Rounded buttons with hover effects
316
- - **Typography**: Clean, readable fonts with proper hierarchy
237
+ <AttendanceCalendar view={view} onChangeView={setView} attendanceData={data} />;
238
+ ```
317
239
 
318
- ### Responsive Behavior
240
+ ## API Reference
319
241
 
320
- - **All screens**: Cells use `w-full aspect-square` by default — they fluidly fill the grid column with no overflow
321
- - **Desktop (≥700px container)**: Switches to 14-column layout
322
- - **Narrow containers / mobile**: 7-column layout with touch-friendly sizing
323
- - **Fixed size mode**: Use `cellSize`, `cellWidth`, or `cellHeight` for explicit pixel dimensions
242
+ ### `AttendanceCalendar` (pre-composed)
324
243
 
325
- ### Customization
244
+ | Prop | Type | Default | Description |
245
+ | --- | --- | --- | --- |
246
+ | `view` | `MonthView` | current month | Current month and year |
247
+ | `onChangeView` | `(view: MonthView) => void` | **required** | Month navigation callback |
248
+ | `attendanceData` | `AttendanceData` | — | Present/absent days (single or array) |
249
+ | `onDateClick` | `(day, month, year) => void` | — | Date click callback |
250
+ | `showNavigation` | `boolean` | `true` | Show header with nav buttons |
251
+ | `showWeekDays` | `boolean` | `true` | Show weekday labels |
252
+ | `className` | `string` | — | Root container class |
253
+ | `classNames` | `GridClassNames` | — | Cell style overrides (see below) |
254
+ | `cellSize` | `number` | — | Square cell size in px |
255
+ | `cellWidth` | `number` | — | Cell width in px |
256
+ | `cellHeight` | `number` | — | Cell height in px |
257
+ | `renderCell` | `(state: CellData) => ReactNode` | — | Custom cell renderer |
326
258
 
327
- Override any styling using the `className` props and size controls:
259
+ ### `GridClassNames`
328
260
 
329
- #### Size Control
261
+ ```typescript
262
+ type GridClassNames = {
263
+ cell?: string; // Base class for all cells
264
+ present?: string; // Present-day cells
265
+ absent?: string; // Absent-day cells
266
+ today?: string; // Today's cell (merged last, wins over present/absent)
267
+ outside?: string; // Days outside current month
268
+ };
269
+ ```
330
270
 
331
- - **`cellSize`** - Set both width and height for square cells
332
- - **`cellWidth`** - Set only the width of cells
333
- - **`cellHeight`** - Set only the height of cells
334
- - **Automatic font sizing** - Text size adjusts based on cell dimensions
271
+ ### `CellData`
335
272
 
336
- #### Styling Options
273
+ Passed to `renderCell`:
337
274
 
338
- All Tailwind classes are supported:
275
+ ```typescript
276
+ type CellData = {
277
+ day: number;
278
+ date: Date;
279
+ inCurrentMonth: boolean;
280
+ isPresent: boolean;
281
+ isAbsent: boolean;
282
+ isToday: boolean;
283
+ isClickable: boolean;
284
+ };
285
+ ```
339
286
 
340
- - Colors, spacing, borders, shadows
341
- - Hover effects, transitions, animations
342
- - Responsive breakpoints and utilities
343
- - **`todayCellClassName`** — prefer this for today’s look so your utilities reliably override shared props like `presentCellClassName`
287
+ ### Compound Components
344
288
 
345
- ## 🔄 Multi-Month Data Format
289
+ | Component | Props | Description |
290
+ | --- | --- | --- |
291
+ | `Calendar.Root` | `view`, `onChangeView`, `attendanceData`, `onDateClick`, `className`, `children` | Context provider and container |
292
+ | `Calendar.Header` | `className`, `children` | Flex wrapper for title + nav |
293
+ | `Calendar.Title` | `className`, `yearClassName?`, `format?` | Month/year heading — `yearClassName` styles the year span only (default year color: `text-slate-500`) |
294
+ | `Calendar.PrevTrigger` | all `<button>` props | Previous month button |
295
+ | `Calendar.NextTrigger` | all `<button>` props | Next month button |
296
+ | `Calendar.WeekDays` | `className`, `dayClassName`, `labels?` | Weekday labels row |
297
+ | `Calendar.Grid` | `className`, `classNames`, `cellSize`, `cellHeight`, `cellWidth`, `renderCell` | Date grid |
346
298
 
347
- The `attendanceData` prop supports two formats:
299
+ ### `useCalendar()` Hook
348
300
 
349
- ### Single Month (Legacy Format)
301
+ Returns all calendar state when used inside `Calendar.Root`:
350
302
 
351
303
  ```typescript
352
- const attendanceData: AttendanceData = {
353
- year: 2024,
354
- monthIndex: 0,
355
- presentDays: new Set([1, 2, 3, 5, 8]),
356
- absentDays: new Set([4, 6, 7]),
357
- };
304
+ const {
305
+ view, // MonthView — current month/year
306
+ monthName, // string — e.g. "January"
307
+ today, // { day, month, year }
308
+ currentMonthData,// MonthAttendanceData | undefined
309
+ columns, // number — 7 or 14 (responsive)
310
+ cells, // { day, inCurrentMonth }[]
311
+ weekdayLabels, // string[]
312
+ goPrev, // () => void
313
+ goNext, // () => void
314
+ onDateClick, // ((day, month, year) => void) | undefined
315
+ } = useCalendar();
358
316
  ```
359
317
 
360
- ### Multiple Months (New Format)
318
+ ### Types
361
319
 
362
320
  ```typescript
363
- const attendanceData: AttendanceData = [
364
- {
365
- year: 2024,
366
- monthIndex: 0, // January
367
- presentDays: new Set([1, 2, 3, 5, 8]),
368
- absentDays: new Set([4, 6, 7]),
369
- },
370
- {
371
- year: 2024,
372
- monthIndex: 1, // February
373
- presentDays: new Set([1, 2, 5, 6, 7]),
374
- absentDays: new Set([3, 4, 8]),
375
- },
376
- // ... add more months as needed
377
- ];
321
+ type MonthView = {
322
+ year: number;
323
+ monthIndex: number; // 0-11
324
+ };
325
+
326
+ type MonthAttendanceData = {
327
+ year: number;
328
+ monthIndex: number;
329
+ presentDays: Set<number>;
330
+ absentDays: Set<number>;
331
+ };
332
+
333
+ type AttendanceData = MonthAttendanceData | MonthAttendanceData[];
378
334
  ```
379
335
 
380
- **Benefits of Multi-Month Format:**
336
+ ## Default Theme
337
+
338
+ - **Present** — emerald green (`emerald-500`) with white text
339
+ - **Absent** — amber orange (`amber-500`) with white text
340
+ - **Today** (no data) — dark slate (`slate-900`) with white text
341
+ - **Today** (present/absent) — status color + ring highlight
342
+ - **Outside month** — faded with light border
343
+ - **Navigation** — rounded buttons with hover/active effects
344
+
345
+ ## Responsive Behavior
381
346
 
382
- - **Batch loading** - Load attendance data for multiple months at once
383
- - **Better performance** - No need to fetch data when navigating between months
384
- - **Seamless navigation** - Smooth transitions between months with data
385
- - **Backward compatible** - Works with existing single month format
386
- - ✅ **Memory efficient** - Store data in memory for instant access
387
- - ✅ **Offline ready** - Pre-load data for offline calendar browsing
347
+ - Cells use `w-full aspect-square` by default fluid with no overflow
348
+ - Container >= 700px: switches to 14-column layout
349
+ - Narrow / mobile: 7-column layout with touch-friendly sizing
350
+ - Use `cellSize`, `cellWidth`, or `cellHeight` for fixed pixel dimensions
388
351
 
389
- ## 📝 License
352
+ ## License
390
353
 
391
354
  MIT © [Alamin](https://github.com/alamincodes)
392
355
 
393
356
  ---
394
357
 
395
358
  <div align="center">
396
- <a href="https://github.com/alamincodes/attendance-calendar">GitHub</a> •
359
+ <a href="https://github.com/alamincodes/attendance-calendar">GitHub</a> •
397
360
  <a href="https://www.npmjs.com/package/react-attendance-calendar">npm</a>
398
361
  </div>
@@ -0,0 +1,17 @@
1
+ import type { AttendanceData, CellData, GridClassNames, MonthView } from "./calendar/types";
2
+ export type AttendanceCalendarProps = {
3
+ view?: MonthView;
4
+ onChangeView: (next: MonthView) => void;
5
+ attendanceData?: AttendanceData;
6
+ onDateClick?: (day: number, month: number, year: number) => void;
7
+ showNavigation?: boolean;
8
+ showWeekDays?: boolean;
9
+ className?: string;
10
+ classNames?: GridClassNames;
11
+ cellSize?: number;
12
+ cellHeight?: number;
13
+ cellWidth?: number;
14
+ renderCell?: (state: CellData) => React.ReactNode;
15
+ };
16
+ export default function AttendanceCalendar({ view, onChangeView, attendanceData, onDateClick, showNavigation, showWeekDays, className, classNames, cellSize, cellHeight, cellWidth, renderCell, }: AttendanceCalendarProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=attendance-calendar.d.ts.map