react-attendance-calendar 2.4.4 → 2.4.5

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,310 @@ 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
122
  ```tsx
128
- // Center (default) — [←] January 2024 [→]
129
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="center" />
130
-
131
- // Left — January 2024 [← →]
132
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="left" />
133
-
134
- // Right — [← →] January 2024
135
- <AttendanceCalendar view={view} onChangeView={setView} monthTitlePosition="right" />
123
+ <Calendar.Title
124
+ format={(monthName, year) => (
125
+ <span className="text-lg font-medium">
126
+ {monthName} / {year}
127
+ </span>
128
+ )}
129
+ />
136
130
  ```
137
131
 
138
- ### Custom Styling
132
+ ### Custom cell rendering
133
+
134
+ 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.
139
135
 
140
136
  ```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"
137
+ <Calendar.Grid
138
+ renderCell={(cell) => (
139
+ <div
140
+ className={`w-full aspect-square grid place-items-center rounded-xl text-sm ${
141
+ cell.isPresent
142
+ ? "bg-green-100 text-green-700"
143
+ : cell.isAbsent
144
+ ? "bg-red-100 text-red-700"
145
+ : cell.isToday
146
+ ? "bg-blue-600 text-white"
147
+ : "text-slate-600"
148
+ }`}
149
+ >
150
+ {cell.day}
151
+ {cell.isPresent && <span className="text-[10px]">✓</span>}
152
+ {cell.isAbsent && <span className="text-[10px]">✗</span>}
153
+ </div>
154
+ )}
147
155
  />
148
156
  ```
149
157
 
150
- ### Today cell (`todayCellClassName`)
158
+ ### Headless with `useCalendar()`
151
159
 
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.
160
+ For a completely custom UI, use the hook inside a `Calendar.Root`:
153
161
 
154
162
  ```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"
161
- />
163
+ import { Calendar, useCalendar } from "react-attendance-calendar";
164
+
165
+ function HeadlessCalendar() {
166
+ const { view, monthName, goPrev, goNext, cells, currentMonthData, today, columns } =
167
+ useCalendar();
168
+
169
+ // Build any UI you want with full access to calendar state
170
+ return <div>{/* your custom markup */}</div>;
171
+ }
172
+
173
+ function App() {
174
+ const [view, setView] = useState({ year: 2024, monthIndex: 0 });
175
+
176
+ return (
177
+ <Calendar.Root view={view} onChangeView={setView} attendanceData={data}>
178
+ <HeadlessCalendar />
179
+ </Calendar.Root>
180
+ );
181
+ }
162
182
  ```
163
183
 
164
- ### Custom Cell Sizes
184
+ ### Custom cell sizes
165
185
 
166
186
  ```tsx
167
- // Square cells with custom size
168
- <AttendanceCalendar
169
- view={view}
170
- onChangeView={setView}
171
- cellSize={60} // 60px x 60px cells
172
- />
187
+ // Square cells
188
+ <AttendanceCalendar view={view} onChangeView={setView} cellSize={50} />
173
189
 
174
190
  // Custom width and height
175
- <AttendanceCalendar
176
- view={view}
177
- onChangeView={setView}
178
- cellWidth={80} // 80px wide
179
- cellHeight={50} // 50px tall
180
- />
191
+ <AttendanceCalendar view={view} onChangeView={setView} cellWidth={80} cellHeight={50} />
181
192
 
182
- // Small compact calendar
193
+ // Compact
183
194
  <AttendanceCalendar
184
195
  view={view}
185
196
  onChangeView={setView}
186
- cellSize={32} // 32px x 32px cells
187
- cellClassName="text-xs"
197
+ cellSize={32}
198
+ classNames={{ cell: "rounded-full text-xs" }}
188
199
  />
189
200
  ```
190
201
 
191
- ### Complete Example with Custom Styling
202
+ ### Multi-month data
192
203
 
193
- ```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";
204
+ Pass an array to `attendanceData` to pre-load multiple months. Navigation between loaded months is instant.
201
205
 
202
- function App() {
203
- const [view, setView] = useState<MonthView>({
206
+ ```tsx
207
+ const data: AttendanceData = [
208
+ {
204
209
  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
- };
234
-
235
- 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>
253
- );
254
- }
210
+ monthIndex: 0,
211
+ presentDays: new Set([1, 2, 3, 5, 8, 9, 10]),
212
+ absentDays: new Set([4, 11]),
213
+ },
214
+ {
215
+ year: 2024,
216
+ monthIndex: 1,
217
+ presentDays: new Set([1, 2, 5, 6, 7]),
218
+ absentDays: new Set([3, 4, 8]),
219
+ },
220
+ ];
255
221
 
256
- export default App;
222
+ <AttendanceCalendar view={view} onChangeView={setView} attendanceData={data} />;
257
223
  ```
258
224
 
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
225
+ ## API Reference
284
226
 
285
- ```typescript
286
- type MonthView = {
287
- year: number; // e.g., 2024
288
- monthIndex: number; // 0-11 (0 = January)
289
- };
227
+ ### `AttendanceCalendar` (pre-composed)
290
228
 
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
- };
229
+ | Prop | Type | Default | Description |
230
+ | --- | --- | --- | --- |
231
+ | `view` | `MonthView` | current month | Current month and year |
232
+ | `onChangeView` | `(view: MonthView) => void` | **required** | Month navigation callback |
233
+ | `attendanceData` | `AttendanceData` | — | Present/absent days (single or array) |
234
+ | `onDateClick` | `(day, month, year) => void` | — | Date click callback |
235
+ | `showNavigation` | `boolean` | `true` | Show header with nav buttons |
236
+ | `showWeekDays` | `boolean` | `true` | Show weekday labels |
237
+ | `className` | `string` | — | Root container class |
238
+ | `classNames` | `GridClassNames` | — | Cell style overrides (see below) |
239
+ | `cellSize` | `number` | — | Square cell size in px |
240
+ | `cellWidth` | `number` | — | Cell width in px |
241
+ | `cellHeight` | `number` | — | Cell height in px |
242
+ | `renderCell` | `(state: CellData) => ReactNode` | — | Custom cell renderer |
297
243
 
298
- // Support both single month and multiple months
299
- type AttendanceData = MonthAttendanceData | MonthAttendanceData[];
244
+ ### `GridClassNames`
300
245
 
301
- type MonthTitlePosition = "left" | "center" | "right";
246
+ ```typescript
247
+ type GridClassNames = {
248
+ cell?: string; // Base class for all cells
249
+ present?: string; // Present-day cells
250
+ absent?: string; // Absent-day cells
251
+ today?: string; // Today's cell (merged last, wins over present/absent)
252
+ outside?: string; // Days outside current month
253
+ };
302
254
  ```
303
255
 
304
- ## 🎨 Styling
305
-
306
- The component uses Tailwind CSS classes with a modern design system:
307
-
308
- ### Default Theme
309
-
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
317
-
318
- ### Responsive Behavior
256
+ ### `CellData`
319
257
 
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
258
+ Passed to `renderCell`:
324
259
 
325
- ### Customization
326
-
327
- Override any styling using the `className` props and size controls:
328
-
329
- #### Size Control
330
-
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
260
+ ```typescript
261
+ type CellData = {
262
+ day: number;
263
+ date: Date;
264
+ inCurrentMonth: boolean;
265
+ isPresent: boolean;
266
+ isAbsent: boolean;
267
+ isToday: boolean;
268
+ isClickable: boolean;
269
+ };
270
+ ```
335
271
 
336
- #### Styling Options
272
+ ### Compound Components
337
273
 
338
- All Tailwind classes are supported:
274
+ | Component | Props | Description |
275
+ | --- | --- | --- |
276
+ | `Calendar.Root` | `view`, `onChangeView`, `attendanceData`, `onDateClick`, `className`, `children` | Context provider and container |
277
+ | `Calendar.Header` | `className`, `children` | Flex wrapper for title + nav |
278
+ | `Calendar.Title` | `className`, `format?` | Month/year heading |
279
+ | `Calendar.PrevTrigger` | all `<button>` props | Previous month button |
280
+ | `Calendar.NextTrigger` | all `<button>` props | Next month button |
281
+ | `Calendar.WeekDays` | `className`, `dayClassName`, `labels?` | Weekday labels row |
282
+ | `Calendar.Grid` | `className`, `classNames`, `cellSize`, `cellHeight`, `cellWidth`, `renderCell` | Date grid |
339
283
 
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`
284
+ ### `useCalendar()` Hook
344
285
 
345
- ## 🔄 Multi-Month Data Format
286
+ Returns all calendar state when used inside `Calendar.Root`:
346
287
 
347
- The `attendanceData` prop supports two formats:
288
+ ```typescript
289
+ const {
290
+ view, // MonthView — current month/year
291
+ monthName, // string — e.g. "January"
292
+ today, // { day, month, year }
293
+ currentMonthData,// MonthAttendanceData | undefined
294
+ columns, // number — 7 or 14 (responsive)
295
+ cells, // { day, inCurrentMonth }[]
296
+ weekdayLabels, // string[]
297
+ goPrev, // () => void
298
+ goNext, // () => void
299
+ onDateClick, // ((day, month, year) => void) | undefined
300
+ } = useCalendar();
301
+ ```
348
302
 
349
- ### Single Month (Legacy Format)
303
+ ### Types
350
304
 
351
305
  ```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]),
306
+ type MonthView = {
307
+ year: number;
308
+ monthIndex: number; // 0-11
357
309
  };
358
- ```
359
310
 
360
- ### Multiple Months (New Format)
311
+ type MonthAttendanceData = {
312
+ year: number;
313
+ monthIndex: number;
314
+ presentDays: Set<number>;
315
+ absentDays: Set<number>;
316
+ };
361
317
 
362
- ```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
- ];
318
+ type AttendanceData = MonthAttendanceData | MonthAttendanceData[];
378
319
  ```
379
320
 
380
- **Benefits of Multi-Month Format:**
321
+ ## Default Theme
322
+
323
+ - **Present** — emerald green (`emerald-500`) with white text
324
+ - **Absent** — amber orange (`amber-500`) with white text
325
+ - **Today** (no data) — dark slate (`slate-900`) with white text
326
+ - **Today** (present/absent) — status color + ring highlight
327
+ - **Outside month** — faded with light border
328
+ - **Navigation** — rounded buttons with hover/active effects
329
+
330
+ ## Responsive Behavior
381
331
 
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
332
+ - Cells use `w-full aspect-square` by default fluid with no overflow
333
+ - Container >= 700px: switches to 14-column layout
334
+ - Narrow / mobile: 7-column layout with touch-friendly sizing
335
+ - Use `cellSize`, `cellWidth`, or `cellHeight` for fixed pixel dimensions
388
336
 
389
- ## 📝 License
337
+ ## License
390
338
 
391
339
  MIT © [Alamin](https://github.com/alamincodes)
392
340
 
393
341
  ---
394
342
 
395
343
  <div align="center">
396
- <a href="https://github.com/alamincodes/attendance-calendar">GitHub</a> •
344
+ <a href="https://github.com/alamincodes/attendance-calendar">GitHub</a> •
397
345
  <a href="https://www.npmjs.com/package/react-attendance-calendar">npm</a>
398
346
  </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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attendance-calendar.d.ts","sourceRoot":"","sources":["../src/attendance-calendar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,cAAc,EACd,SAAS,EACV,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,KAAK,CAAC,SAAS,CAAC;CACnD,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,IAAI,EACJ,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAqB,EACrB,YAAmB,EACnB,SAAS,EACT,UAAU,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,GACX,EAAE,uBAAuB,2CA0BzB"}