react-jalali-events-calendar 1.0.1

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 ADDED
@@ -0,0 +1,159 @@
1
+ ### πŸ“… Persian Calendar for React & Next.js
2
+ A fully customizable Persian calendar component for React and Next.js with support for events, holidays, tooltips, RTL layout, and modern UI.
3
+
4
+ ## ✨ Features:
5
+
6
+ - βœ… Accurate Gregorian ↔ Jalali date conversion
7
+ - βœ… Event & holiday support
8
+ - βœ… Holiday detection
9
+ - βœ… Tooltip with Persian & Gregorian dates
10
+ - βœ… Highlights today’s date
11
+ - βœ… Shows previous & next month days
12
+ - βœ… Fully responsive
13
+ - βœ… RTL-first design
14
+ - βœ… External month navigation control
15
+ - βœ… No external calendar dependencies
16
+
17
+
18
+ ## πŸ“¦ Installation:
19
+
20
+ ```bash
21
+ npm install react-persian-calendar
22
+ ```
23
+ or
24
+ ```bash
25
+ yarn add react-persian-calendar
26
+ ```
27
+
28
+ ## ⚠️ Tailwind CSS Requirement
29
+
30
+ This calendar **requires Tailwind CSS** to be installed in your project.
31
+
32
+ All styles, layout, responsiveness, and tooltips are built using Tailwind utility classes.
33
+ Without Tailwind CSS, the calendar **will not render correctly**.
34
+
35
+ ### Install Tailwind CSS
36
+
37
+ If you are using Next.js or React, follow the official guide:
38
+
39
+ πŸ‘‰ https://tailwindcss.com/docs/installation
40
+
41
+ After installation, make sure Tailwind is properly configured in your project.
42
+
43
+ ## πŸš€ Basic Usage:
44
+
45
+ ```tsx
46
+ import { useState } from "react";
47
+ import { Calendar } from "react-persian-calendar";
48
+
49
+ function App() {
50
+ const [currentDate, setCurrentDate] = useState("");
51
+ const [goNext, setGoNext] = useState(false);
52
+ const [goPrev, setGoPrev] = useState(false);
53
+
54
+ return (
55
+ <Calendar
56
+ goNext={goNext}
57
+ goPrev={goPrev}
58
+ setCurrentDate={setCurrentDate}
59
+ setNext={() => setGoNext(false)}
60
+ setPrev={() => setGoPrev(false)}
61
+ />
62
+ );
63
+ }
64
+ ```
65
+ ## 🧠 Props:
66
+
67
+ | Prop | Type | Description |
68
+ | --------------------------- | -------------------------- | ------------------------------------- |
69
+ | `setCurrentDate` | `(value: string) => void` | Returns formatted current date string |
70
+ | `goNext` | `boolean` | Navigate to next month |
71
+ | `goPrev` | `boolean` | Navigate to previous month |
72
+ | `setNext` | `(value: boolean) => void` | Reset next navigation trigger |
73
+ | `setPrev` | `(value: boolean) => void` | Reset previous navigation trigger |
74
+ | `showEvents` | `boolean` | Enable event tooltips |
75
+ | `headerColor` | `string` | Header background color |
76
+ | `headerTextColor` | `string` | Header text color |
77
+ | `daysBgColor` | `string` | Current month days background |
78
+ | `daysTextColor` | `string` | Current month days text color |
79
+ | `holidaysBgColor` | `string` | Holiday background color |
80
+ | `holidayTextColor` | `string` | Holiday text color |
81
+ | `currentDayBgColor` | `string` | Today background color |
82
+ | `currentDaytextColor` | `string` | Today text color |
83
+ | `outsideMonthDaysBg` | `string` | Outside month days background |
84
+ | `outsideMonthDaysTextColor` | `string` | Outside month days text color |
85
+ | `borderColor` | `string` | Calendar border color |
86
+
87
+ ## 🎨 Full Customization Example:
88
+
89
+ ```tsx
90
+ <Calendar
91
+ setCurrentDate={setCurrentDate}
92
+ goNext={goNext}
93
+ goPrev={goPrev}
94
+ setNext={setGoNext}
95
+ setPrev={setGoPrev}
96
+ showEvents={true}
97
+ headerColor="#F1F4F9"
98
+ headerTextColor="#111827"
99
+ daysBgColor="#ffffff"
100
+ daysTextColor="#111827"
101
+ holidaysBgColor="#FEE2E2"
102
+ holidayTextColor="#DC2626"
103
+ currentDayBgColor="#2563EB"
104
+ currentDaytextColor="#ffffff"
105
+ outsideMonthDaysBg="#F9FAFB"
106
+ outsideMonthDaysTextColor="#9CA3AF"
107
+ borderColor="#D1D5DB"
108
+ />
109
+ ```
110
+ ## πŸ“‘ Events Data Source:
111
+ By default, the calendar fetches events from:
112
+ ```http
113
+ GET https://badesaba.ir/api/site/getDataCalendar/{month}/{year}
114
+ ```
115
+
116
+ ## Expected Response Shape:
117
+ ```ts
118
+ type Event = {
119
+ event: string;
120
+ holiday: boolean;
121
+ };
122
+
123
+ type CalendarData = {
124
+ date: string; // YYYY-MM-DD (Gregorian)
125
+ events: Event[];
126
+ };
127
+ ```
128
+ ## 🧭 Event Tooltip
129
+
130
+ - Appears on hover
131
+ - Displays:
132
+ - Jalali date
133
+ - Gregorian date
134
+ - Event list
135
+ - Holidays are visually highlighted
136
+
137
+
138
+
139
+ ## πŸ›  Built With:
140
+ - React
141
+ - Next.js (App Router compatible)
142
+ - TypeScript
143
+ - Tailwind CSS
144
+ - RTL layout support
145
+
146
+ ## ⚠️ Important Notes:
147
+ This component must be used inside a Client Component
148
+ Required at the top of the file:
149
+ ```tsx
150
+ "use client";
151
+ ```
152
+
153
+ ## πŸ“„ License:
154
+ MIT License
155
+ Free for personal and commercial use.
156
+
157
+ ## ❀️ Contributing:
158
+ Issues and Pull Requests are welcome!
159
+ Feel free to improve or extend this calendar 🌱
@@ -0,0 +1,24 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type Props = {
4
+ setCurrentDate: (value: string) => void;
5
+ goNext: boolean;
6
+ goPrev: boolean;
7
+ headerColor?: string;
8
+ headerTextColor?: string;
9
+ showEvents?: boolean;
10
+ holidaysBgColor?: string;
11
+ daysTextColor?: string;
12
+ currentDayBgColor?: string;
13
+ currentDaytextColor?: string;
14
+ holidayTextColor?: string;
15
+ daysBgColor?: string;
16
+ outsideMonthDaysBg?: string;
17
+ outsideMonthDaysTextColor?: string;
18
+ borderColor?: string;
19
+ setNext: (value: boolean) => void;
20
+ setPrev: (value: boolean) => void;
21
+ };
22
+ declare function Calendar({ setCurrentDate, headerColor, showEvents, goNext, goPrev, headerTextColor, setNext, daysBgColor, setPrev, holidaysBgColor, daysTextColor, holidayTextColor, currentDayBgColor, currentDaytextColor, borderColor, outsideMonthDaysBg, outsideMonthDaysTextColor, }: Props): react_jsx_runtime.JSX.Element;
23
+
24
+ export { Calendar };
@@ -0,0 +1,24 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type Props = {
4
+ setCurrentDate: (value: string) => void;
5
+ goNext: boolean;
6
+ goPrev: boolean;
7
+ headerColor?: string;
8
+ headerTextColor?: string;
9
+ showEvents?: boolean;
10
+ holidaysBgColor?: string;
11
+ daysTextColor?: string;
12
+ currentDayBgColor?: string;
13
+ currentDaytextColor?: string;
14
+ holidayTextColor?: string;
15
+ daysBgColor?: string;
16
+ outsideMonthDaysBg?: string;
17
+ outsideMonthDaysTextColor?: string;
18
+ borderColor?: string;
19
+ setNext: (value: boolean) => void;
20
+ setPrev: (value: boolean) => void;
21
+ };
22
+ declare function Calendar({ setCurrentDate, headerColor, showEvents, goNext, goPrev, headerTextColor, setNext, daysBgColor, setPrev, holidaysBgColor, daysTextColor, holidayTextColor, currentDayBgColor, currentDaytextColor, borderColor, outsideMonthDaysBg, outsideMonthDaysTextColor, }: Props): react_jsx_runtime.JSX.Element;
23
+
24
+ export { Calendar };
package/dist/index.js ADDED
@@ -0,0 +1,434 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Calendar: () => Calendar
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/Calendar.tsx
28
+ var import_react = require("react");
29
+ var import_jsx_runtime = require("react/jsx-runtime");
30
+ function gregorianToJalali(gy, gm, gd) {
31
+ const g_d_m = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
32
+ const gy2 = gm > 2 ? gy + 1 : gy;
33
+ let days = 355666 + 365 * gy + Math.floor((gy2 + 3) / 4) - Math.floor((gy2 + 99) / 100) + Math.floor((gy2 + 399) / 400) + gd + g_d_m[gm - 1];
34
+ let jy = -1595 + 33 * Math.floor(days / 12053);
35
+ days %= 12053;
36
+ jy += 4 * Math.floor(days / 1461);
37
+ days %= 1461;
38
+ if (days > 365) {
39
+ jy += Math.floor((days - 1) / 365);
40
+ days = (days - 1) % 365;
41
+ }
42
+ let jm, jd;
43
+ if (days < 186) {
44
+ jm = 1 + Math.floor(days / 31);
45
+ jd = 1 + days % 31;
46
+ } else {
47
+ jm = 7 + Math.floor((days - 186) / 30);
48
+ jd = 1 + (days - 186) % 30;
49
+ }
50
+ return [jy, jm, jd];
51
+ }
52
+ function jalaliToGregorian(jy, jm, jd) {
53
+ jy += 1595;
54
+ let days = -355668 + 365 * jy + Math.floor(jy / 33) * 8 + Math.floor((jy % 33 + 3) / 4) + jd + (jm < 7 ? (jm - 1) * 31 : (jm - 7) * 30 + 186);
55
+ let gy = 400 * Math.floor(days / 146097);
56
+ days %= 146097;
57
+ if (days > 36524) {
58
+ gy += 100 * Math.floor(--days / 36524);
59
+ days %= 36524;
60
+ if (days >= 365) days++;
61
+ }
62
+ gy += 4 * Math.floor(days / 1461);
63
+ days %= 1461;
64
+ if (days > 365) {
65
+ gy += Math.floor((days - 1) / 365);
66
+ days = (days - 1) % 365;
67
+ }
68
+ let gd = days + 1;
69
+ const sal_a = [
70
+ 0,
71
+ 31,
72
+ gy % 4 === 0 && gy % 100 !== 0 || gy % 400 === 0 ? 29 : 28,
73
+ 31,
74
+ 30,
75
+ 31,
76
+ 30,
77
+ 31,
78
+ 31,
79
+ 30,
80
+ 31,
81
+ 30,
82
+ 31
83
+ ];
84
+ let gm;
85
+ for (gm = 0; gm < 13 && gd > sal_a[gm]; gm++) gd -= sal_a[gm];
86
+ return [gy, gm, gd];
87
+ }
88
+ function isLeapJalaliYear(jy) {
89
+ const fm = jy % 33;
90
+ return fm === 1 || fm === 5 || fm === 9 || fm === 13 || fm === 17 || fm === 22 || fm === 26 || fm === 30;
91
+ }
92
+ function jalaliMonthLength(jy, jm) {
93
+ if (jm <= 6) return 31;
94
+ if (jm <= 11) return 30;
95
+ return isLeapJalaliYear(jy) ? 30 : 29;
96
+ }
97
+ function Calendar({
98
+ setCurrentDate,
99
+ headerColor,
100
+ showEvents,
101
+ goNext,
102
+ goPrev,
103
+ headerTextColor,
104
+ setNext,
105
+ daysBgColor,
106
+ setPrev,
107
+ holidaysBgColor,
108
+ daysTextColor,
109
+ holidayTextColor,
110
+ currentDayBgColor,
111
+ currentDaytextColor,
112
+ borderColor,
113
+ outsideMonthDaysBg,
114
+ outsideMonthDaysTextColor
115
+ }) {
116
+ const gregorianMonthsFa = [
117
+ "",
118
+ "\u0698\u0627\u0646\u0648\u06CC\u0647",
119
+ "\u0641\u0648\u0631\u06CC\u0647",
120
+ "\u0645\u0627\u0631\u0633",
121
+ "\u0622\u0648\u0631\u06CC\u0644",
122
+ "\u0645\u0647",
123
+ "\u0698\u0648\u0626\u0646",
124
+ "\u0698\u0648\u0626\u06CC\u0647",
125
+ "\u0627\u0648\u062A",
126
+ "\u0633\u067E\u062A\u0627\u0645\u0628\u0631",
127
+ "\u0627\u06A9\u062A\u0628\u0631",
128
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
129
+ "\u062F\u0633\u0627\u0645\u0628\u0631"
130
+ ];
131
+ const now = /* @__PURE__ */ new Date();
132
+ const tehranOffset = 3.5;
133
+ const utc = now.getTime() + now.getTimezoneOffset() * 6e4;
134
+ const tehranDate = new Date(utc + 36e5 * tehranOffset);
135
+ const [gy, gm, gd] = [
136
+ tehranDate.getFullYear(),
137
+ tehranDate.getMonth() + 1,
138
+ tehranDate.getDate()
139
+ ];
140
+ const [todayYear, todayMonth, todayDate] = gregorianToJalali(gy, gm, gd);
141
+ const [currentYear, setCurrentYear] = (0, import_react.useState)(todayYear);
142
+ const [currentMonth, setCurrentMonth] = (0, import_react.useState)(todayMonth);
143
+ const [calendarData, setCalendarData] = (0, import_react.useState)([]);
144
+ const weekDays = [
145
+ "\u0634\u0646\u0628\u0647",
146
+ "\u06CC\u06A9\u0634\u0646\u0628\u0647",
147
+ "\u062F\u0648\u0634\u0646\u0628\u0647",
148
+ "\u0633\u0647\u200C\u0634\u0646\u0628\u0647",
149
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
150
+ "\u067E\u0646\u062C\u200C\u0634\u0646\u0628\u0647",
151
+ "\u062C\u0645\u0639\u0647"
152
+ ];
153
+ (0, import_react.useEffect)(() => {
154
+ const fetchData = async () => {
155
+ try {
156
+ const response = await fetch(
157
+ `https://badesaba.ir/api/site/getDataCalendar/${currentMonth}/${currentYear}`
158
+ );
159
+ const data = await response.json();
160
+ setCalendarData(data);
161
+ } catch {
162
+ console.log("Error fetching calendar data:");
163
+ }
164
+ };
165
+ fetchData();
166
+ }, [currentMonth, currentYear]);
167
+ (0, import_react.useEffect)(() => {
168
+ const weekDays2 = [
169
+ "\u0634\u0646\u0628\u0647",
170
+ "\u06CC\u06A9\u0634\u0646\u0628\u0647",
171
+ "\u062F\u0648\u0634\u0646\u0628\u0647",
172
+ "\u0633\u0647\u200C\u0634\u0646\u0628\u0647",
173
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
174
+ "\u067E\u0646\u062C\u0634\u0646\u0628\u0647",
175
+ "\u062C\u0645\u0639\u0647"
176
+ ];
177
+ const months = [
178
+ "\u0641\u0631\u0648\u0631\u062F\u06CC\u0646",
179
+ "\u0627\u0631\u062F\u06CC\u0628\u0647\u0634\u062A",
180
+ "\u062E\u0631\u062F\u0627\u062F",
181
+ "\u062A\u06CC\u0631",
182
+ "\u0645\u0631\u062F\u0627\u062F",
183
+ "\u0634\u0647\u0631\u06CC\u0648\u0631",
184
+ "\u0645\u0647\u0631",
185
+ "\u0622\u0628\u0627\u0646",
186
+ "\u0622\u0630\u0631",
187
+ "\u062F\u06CC",
188
+ "\u0628\u0647\u0645\u0646",
189
+ "\u0627\u0633\u0641\u0646\u062F"
190
+ ];
191
+ const now2 = /* @__PURE__ */ new Date();
192
+ const tehranOffset2 = 3.5;
193
+ const utc2 = now2.getTime() + now2.getTimezoneOffset() * 6e4;
194
+ const tehranDate2 = new Date(utc2 + 36e5 * tehranOffset2);
195
+ const [gy2, gm2, gd2] = [
196
+ tehranDate2.getFullYear(),
197
+ tehranDate2.getMonth() + 1,
198
+ tehranDate2.getDate()
199
+ ];
200
+ const [jy, jm, jd] = gregorianToJalali(gy2, gm2, gd2);
201
+ const weekdayIndex = tehranDate2.getDay();
202
+ const weekdayName = weekDays2[(weekdayIndex + 1) % 7];
203
+ const monthName = months[jm - 1];
204
+ setCurrentDate(`${weekdayName}\u060C ${jd} ${monthName} ${jy}`);
205
+ }, [currentMonth, currentYear]);
206
+ const days = (0, import_react.useMemo)(() => {
207
+ const result = [];
208
+ const daysInMonth = jalaliMonthLength(currentYear, currentMonth);
209
+ const [startGy, startGm, startGd] = jalaliToGregorian(
210
+ currentYear,
211
+ currentMonth,
212
+ 1
213
+ );
214
+ const startDate = new Date(startGy, startGm - 1, startGd);
215
+ const firstDayOfWeek = (startDate.getDay() + 1) % 7;
216
+ let prevMonth = currentMonth - 1;
217
+ let prevYear = currentYear;
218
+ if (prevMonth < 1) {
219
+ prevMonth = 12;
220
+ prevYear--;
221
+ }
222
+ const prevDaysInMonth = jalaliMonthLength(prevYear, prevMonth);
223
+ for (let i = 0; i < firstDayOfWeek; i++) {
224
+ const date = prevDaysInMonth - firstDayOfWeek + 1 + i;
225
+ result.push({
226
+ year: prevYear,
227
+ month: prevMonth,
228
+ date,
229
+ currentMonth: false
230
+ });
231
+ }
232
+ for (let i = 1; i <= daysInMonth; i++) {
233
+ result.push({
234
+ year: currentYear,
235
+ month: currentMonth,
236
+ date: i,
237
+ currentMonth: true
238
+ });
239
+ }
240
+ let nextMonth = currentMonth + 1;
241
+ let nextYear = currentYear;
242
+ if (nextMonth > 12) {
243
+ nextMonth = 1;
244
+ nextYear++;
245
+ }
246
+ let nextDate = 1;
247
+ while (result.length < 42) {
248
+ result.push({
249
+ year: nextYear,
250
+ month: nextMonth,
251
+ date: nextDate++,
252
+ currentMonth: false
253
+ });
254
+ }
255
+ return result;
256
+ }, [currentYear, currentMonth]);
257
+ const handlePrevMonth = (0, import_react.useCallback)(() => {
258
+ let newMonth = currentMonth - 1;
259
+ let newYear = currentYear;
260
+ if (newMonth < 1) {
261
+ newMonth = 12;
262
+ newYear--;
263
+ }
264
+ setCurrentMonth(newMonth);
265
+ setCurrentYear(newYear);
266
+ setPrev(false);
267
+ }, [currentMonth, currentYear]);
268
+ const handleNextMonth = (0, import_react.useCallback)(() => {
269
+ let newMonth = currentMonth + 1;
270
+ let newYear = currentYear;
271
+ if (newMonth > 12) {
272
+ newMonth = 1;
273
+ newYear++;
274
+ }
275
+ setCurrentMonth(newMonth);
276
+ setCurrentYear(newYear);
277
+ setNext(false);
278
+ }, [currentMonth, currentYear]);
279
+ (0, import_react.useEffect)(() => {
280
+ if (goNext) {
281
+ handleNextMonth();
282
+ }
283
+ if (goPrev) {
284
+ handlePrevMonth();
285
+ }
286
+ }, [goNext, goPrev, handleNextMonth, handlePrevMonth]);
287
+ const calendarMap = (0, import_react.useMemo)(() => {
288
+ const map = /* @__PURE__ */ new Map();
289
+ calendarData.forEach((item) => {
290
+ map.set(item.date, item.events);
291
+ });
292
+ return map;
293
+ }, [calendarData]);
294
+ const getEventsForDate = (year, month, date) => {
295
+ var _a;
296
+ const [gy2, gm2, gd2] = jalaliToGregorian(year, month, date);
297
+ const key = `${gy2}-${String(gm2).padStart(2, "0")}-${String(gd2).padStart(
298
+ 2,
299
+ "0"
300
+ )}`;
301
+ return (_a = calendarMap.get(key)) != null ? _a : [];
302
+ };
303
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto h-full flex flex-col", dir: "rtl", children: [
304
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
305
+ "div",
306
+ {
307
+ style: {
308
+ ...headerTextColor ? { color: headerTextColor } : {},
309
+ ...headerColor ? { backgroundColor: headerColor } : { backgroundColor: "#F1F4F9" },
310
+ ...borderColor ? { borderColor } : { borderColor: "#d9d7e0" }
311
+ },
312
+ className: `grid-cols-7 hidden 350:grid text-center bg-[#F1F4F9] border border-b-0 font-semibold rounded-t-[10px] py-2.5`,
313
+ children: weekDays.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "350:text-[13px]", children: day }, index))
314
+ }
315
+ ),
316
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
317
+ "div",
318
+ {
319
+ style: {
320
+ backgroundColor: headerColor ? headerColor : "#F1F4F9"
321
+ },
322
+ className: `grid-cols-7 grid 350:hidden text-center bg-[#F1F4F9] font-semibold rounded-t-[10px] py-2.5`,
323
+ children: weekDays.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-12 350:hidden", children: day[0] }, index))
324
+ }
325
+ ),
326
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
327
+ "div",
328
+ {
329
+ style: borderColor ? { borderColor } : { borderColor: "#d9d7e0" },
330
+ className: "grid grid-cols-7 flex-1 border-l-0 border-b-0 border",
331
+ children: days.map((d, i) => {
332
+ const events = getEventsForDate(d.year, d.month, d.date);
333
+ const isHolidayDay = events.some((event) => event.holiday);
334
+ const columnIndex = i % 7;
335
+ let tooltipPosition = "";
336
+ if (columnIndex <= 1) {
337
+ tooltipPosition = "right-0";
338
+ } else if (columnIndex >= 5) {
339
+ tooltipPosition = "left-0";
340
+ } else {
341
+ tooltipPosition = "left-1/2 -translate-x-1/2";
342
+ }
343
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
344
+ "div",
345
+ {
346
+ style: {
347
+ ...!d.currentMonth && outsideMonthDaysBg ? { backgroundColor: outsideMonthDaysBg } : {},
348
+ ...!d.currentMonth && outsideMonthDaysTextColor ? { color: outsideMonthDaysTextColor } : !d.currentMonth ? { color: "#99a1af " } : {},
349
+ ...daysBgColor && d.currentMonth ? { backgroundColor: daysBgColor } : {},
350
+ ...daysTextColor && d.currentMonth ? { color: daysTextColor } : {},
351
+ ...holidayTextColor && isHolidayDay && d.currentMonth ? { color: holidayTextColor } : {},
352
+ ...isHolidayDay && holidaysBgColor && d.currentMonth ? { backgroundColor: holidaysBgColor } : {},
353
+ ...d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth && currentDayBgColor ? { backgroundColor: currentDayBgColor } : {},
354
+ ...d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth && currentDaytextColor ? { backgroundColor: currentDaytextColor } : {},
355
+ ...borderColor ? { borderColor } : { borderColor: "#d9d7e0" }
356
+ },
357
+ className: `
358
+ border-r-0 border-t-0 border p-[5px]
359
+ flex justify-center items-center 390:text-14 390:p-[10px] 700:p-[15px]
360
+ relative text-12 group
361
+ ${d.currentMonth ? "" : ""}
362
+ ${d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth ? "bg-blue-500 text-white" : ""}
363
+ ${isHolidayDay && d.currentMonth ? "text-red-500" : ""}
364
+ `,
365
+ children: [
366
+ d.date,
367
+ showEvents && d.currentMonth && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
368
+ "div",
369
+ {
370
+ className: `
371
+ absolute hidden group-hover:block
372
+ bg-white border z-50 border-gray-300 overflow-hidden rounded shadow-lg
373
+ top-full mt-2 w-[220px] text-sm text-right ${tooltipPosition}
374
+ `,
375
+ children: (() => {
376
+ const [gy2, gm2, gd2] = jalaliToGregorian(
377
+ d.year,
378
+ d.month,
379
+ d.date
380
+ );
381
+ const gregorianMonthName = gregorianMonthsFa[gm2];
382
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
383
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
384
+ "div",
385
+ {
386
+ className: `
387
+ flex p-2 justify-between mb-2 pb-2
388
+ bg-linear-to-r from-[#00A1EE] to-[#1349E6] font-semibold text-white
389
+ ${isHolidayDay ? "from-red-500 via-red-600 to-rose-700" : ""}
390
+ `,
391
+ children: [
392
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: weekDays[i % 7] }),
393
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
394
+ d.year,
395
+ "/",
396
+ d.month,
397
+ "/",
398
+ d.date
399
+ ] })
400
+ ]
401
+ }
402
+ ),
403
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-[11px] px-2 text-gray-700 mb-2 pb-2 border-b border-gray-200", children: [
404
+ gd2,
405
+ " ",
406
+ gregorianMonthName,
407
+ " ",
408
+ gy2
409
+ ] }),
410
+ events.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-2 pt-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "list-disc pr-4 flex flex-col", children: events.map((event, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
411
+ "li",
412
+ {
413
+ className: `text-10 ${isHolidayDay ? "text-red-600" : "text-[#23242e]"}`,
414
+ children: event.event
415
+ },
416
+ index
417
+ )) }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-10 p-2 pt-0 text-[#23242e]", children: "\u0631\u0648\u06CC\u062F\u0627\u062F\u06CC \u0648\u062C\u0648\u062F \u0646\u062F\u0627\u0631\u062F" })
418
+ ] });
419
+ })()
420
+ }
421
+ )
422
+ ]
423
+ },
424
+ i
425
+ );
426
+ })
427
+ }
428
+ )
429
+ ] });
430
+ }
431
+ // Annotate the CommonJS export names for ESM import in node:
432
+ 0 && (module.exports = {
433
+ Calendar
434
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,407 @@
1
+ // src/Calendar.tsx
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ function gregorianToJalali(gy, gm, gd) {
5
+ const g_d_m = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
6
+ const gy2 = gm > 2 ? gy + 1 : gy;
7
+ let days = 355666 + 365 * gy + Math.floor((gy2 + 3) / 4) - Math.floor((gy2 + 99) / 100) + Math.floor((gy2 + 399) / 400) + gd + g_d_m[gm - 1];
8
+ let jy = -1595 + 33 * Math.floor(days / 12053);
9
+ days %= 12053;
10
+ jy += 4 * Math.floor(days / 1461);
11
+ days %= 1461;
12
+ if (days > 365) {
13
+ jy += Math.floor((days - 1) / 365);
14
+ days = (days - 1) % 365;
15
+ }
16
+ let jm, jd;
17
+ if (days < 186) {
18
+ jm = 1 + Math.floor(days / 31);
19
+ jd = 1 + days % 31;
20
+ } else {
21
+ jm = 7 + Math.floor((days - 186) / 30);
22
+ jd = 1 + (days - 186) % 30;
23
+ }
24
+ return [jy, jm, jd];
25
+ }
26
+ function jalaliToGregorian(jy, jm, jd) {
27
+ jy += 1595;
28
+ let days = -355668 + 365 * jy + Math.floor(jy / 33) * 8 + Math.floor((jy % 33 + 3) / 4) + jd + (jm < 7 ? (jm - 1) * 31 : (jm - 7) * 30 + 186);
29
+ let gy = 400 * Math.floor(days / 146097);
30
+ days %= 146097;
31
+ if (days > 36524) {
32
+ gy += 100 * Math.floor(--days / 36524);
33
+ days %= 36524;
34
+ if (days >= 365) days++;
35
+ }
36
+ gy += 4 * Math.floor(days / 1461);
37
+ days %= 1461;
38
+ if (days > 365) {
39
+ gy += Math.floor((days - 1) / 365);
40
+ days = (days - 1) % 365;
41
+ }
42
+ let gd = days + 1;
43
+ const sal_a = [
44
+ 0,
45
+ 31,
46
+ gy % 4 === 0 && gy % 100 !== 0 || gy % 400 === 0 ? 29 : 28,
47
+ 31,
48
+ 30,
49
+ 31,
50
+ 30,
51
+ 31,
52
+ 31,
53
+ 30,
54
+ 31,
55
+ 30,
56
+ 31
57
+ ];
58
+ let gm;
59
+ for (gm = 0; gm < 13 && gd > sal_a[gm]; gm++) gd -= sal_a[gm];
60
+ return [gy, gm, gd];
61
+ }
62
+ function isLeapJalaliYear(jy) {
63
+ const fm = jy % 33;
64
+ return fm === 1 || fm === 5 || fm === 9 || fm === 13 || fm === 17 || fm === 22 || fm === 26 || fm === 30;
65
+ }
66
+ function jalaliMonthLength(jy, jm) {
67
+ if (jm <= 6) return 31;
68
+ if (jm <= 11) return 30;
69
+ return isLeapJalaliYear(jy) ? 30 : 29;
70
+ }
71
+ function Calendar({
72
+ setCurrentDate,
73
+ headerColor,
74
+ showEvents,
75
+ goNext,
76
+ goPrev,
77
+ headerTextColor,
78
+ setNext,
79
+ daysBgColor,
80
+ setPrev,
81
+ holidaysBgColor,
82
+ daysTextColor,
83
+ holidayTextColor,
84
+ currentDayBgColor,
85
+ currentDaytextColor,
86
+ borderColor,
87
+ outsideMonthDaysBg,
88
+ outsideMonthDaysTextColor
89
+ }) {
90
+ const gregorianMonthsFa = [
91
+ "",
92
+ "\u0698\u0627\u0646\u0648\u06CC\u0647",
93
+ "\u0641\u0648\u0631\u06CC\u0647",
94
+ "\u0645\u0627\u0631\u0633",
95
+ "\u0622\u0648\u0631\u06CC\u0644",
96
+ "\u0645\u0647",
97
+ "\u0698\u0648\u0626\u0646",
98
+ "\u0698\u0648\u0626\u06CC\u0647",
99
+ "\u0627\u0648\u062A",
100
+ "\u0633\u067E\u062A\u0627\u0645\u0628\u0631",
101
+ "\u0627\u06A9\u062A\u0628\u0631",
102
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
103
+ "\u062F\u0633\u0627\u0645\u0628\u0631"
104
+ ];
105
+ const now = /* @__PURE__ */ new Date();
106
+ const tehranOffset = 3.5;
107
+ const utc = now.getTime() + now.getTimezoneOffset() * 6e4;
108
+ const tehranDate = new Date(utc + 36e5 * tehranOffset);
109
+ const [gy, gm, gd] = [
110
+ tehranDate.getFullYear(),
111
+ tehranDate.getMonth() + 1,
112
+ tehranDate.getDate()
113
+ ];
114
+ const [todayYear, todayMonth, todayDate] = gregorianToJalali(gy, gm, gd);
115
+ const [currentYear, setCurrentYear] = useState(todayYear);
116
+ const [currentMonth, setCurrentMonth] = useState(todayMonth);
117
+ const [calendarData, setCalendarData] = useState([]);
118
+ const weekDays = [
119
+ "\u0634\u0646\u0628\u0647",
120
+ "\u06CC\u06A9\u0634\u0646\u0628\u0647",
121
+ "\u062F\u0648\u0634\u0646\u0628\u0647",
122
+ "\u0633\u0647\u200C\u0634\u0646\u0628\u0647",
123
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
124
+ "\u067E\u0646\u062C\u200C\u0634\u0646\u0628\u0647",
125
+ "\u062C\u0645\u0639\u0647"
126
+ ];
127
+ useEffect(() => {
128
+ const fetchData = async () => {
129
+ try {
130
+ const response = await fetch(
131
+ `https://badesaba.ir/api/site/getDataCalendar/${currentMonth}/${currentYear}`
132
+ );
133
+ const data = await response.json();
134
+ setCalendarData(data);
135
+ } catch {
136
+ console.log("Error fetching calendar data:");
137
+ }
138
+ };
139
+ fetchData();
140
+ }, [currentMonth, currentYear]);
141
+ useEffect(() => {
142
+ const weekDays2 = [
143
+ "\u0634\u0646\u0628\u0647",
144
+ "\u06CC\u06A9\u0634\u0646\u0628\u0647",
145
+ "\u062F\u0648\u0634\u0646\u0628\u0647",
146
+ "\u0633\u0647\u200C\u0634\u0646\u0628\u0647",
147
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
148
+ "\u067E\u0646\u062C\u0634\u0646\u0628\u0647",
149
+ "\u062C\u0645\u0639\u0647"
150
+ ];
151
+ const months = [
152
+ "\u0641\u0631\u0648\u0631\u062F\u06CC\u0646",
153
+ "\u0627\u0631\u062F\u06CC\u0628\u0647\u0634\u062A",
154
+ "\u062E\u0631\u062F\u0627\u062F",
155
+ "\u062A\u06CC\u0631",
156
+ "\u0645\u0631\u062F\u0627\u062F",
157
+ "\u0634\u0647\u0631\u06CC\u0648\u0631",
158
+ "\u0645\u0647\u0631",
159
+ "\u0622\u0628\u0627\u0646",
160
+ "\u0622\u0630\u0631",
161
+ "\u062F\u06CC",
162
+ "\u0628\u0647\u0645\u0646",
163
+ "\u0627\u0633\u0641\u0646\u062F"
164
+ ];
165
+ const now2 = /* @__PURE__ */ new Date();
166
+ const tehranOffset2 = 3.5;
167
+ const utc2 = now2.getTime() + now2.getTimezoneOffset() * 6e4;
168
+ const tehranDate2 = new Date(utc2 + 36e5 * tehranOffset2);
169
+ const [gy2, gm2, gd2] = [
170
+ tehranDate2.getFullYear(),
171
+ tehranDate2.getMonth() + 1,
172
+ tehranDate2.getDate()
173
+ ];
174
+ const [jy, jm, jd] = gregorianToJalali(gy2, gm2, gd2);
175
+ const weekdayIndex = tehranDate2.getDay();
176
+ const weekdayName = weekDays2[(weekdayIndex + 1) % 7];
177
+ const monthName = months[jm - 1];
178
+ setCurrentDate(`${weekdayName}\u060C ${jd} ${monthName} ${jy}`);
179
+ }, [currentMonth, currentYear]);
180
+ const days = useMemo(() => {
181
+ const result = [];
182
+ const daysInMonth = jalaliMonthLength(currentYear, currentMonth);
183
+ const [startGy, startGm, startGd] = jalaliToGregorian(
184
+ currentYear,
185
+ currentMonth,
186
+ 1
187
+ );
188
+ const startDate = new Date(startGy, startGm - 1, startGd);
189
+ const firstDayOfWeek = (startDate.getDay() + 1) % 7;
190
+ let prevMonth = currentMonth - 1;
191
+ let prevYear = currentYear;
192
+ if (prevMonth < 1) {
193
+ prevMonth = 12;
194
+ prevYear--;
195
+ }
196
+ const prevDaysInMonth = jalaliMonthLength(prevYear, prevMonth);
197
+ for (let i = 0; i < firstDayOfWeek; i++) {
198
+ const date = prevDaysInMonth - firstDayOfWeek + 1 + i;
199
+ result.push({
200
+ year: prevYear,
201
+ month: prevMonth,
202
+ date,
203
+ currentMonth: false
204
+ });
205
+ }
206
+ for (let i = 1; i <= daysInMonth; i++) {
207
+ result.push({
208
+ year: currentYear,
209
+ month: currentMonth,
210
+ date: i,
211
+ currentMonth: true
212
+ });
213
+ }
214
+ let nextMonth = currentMonth + 1;
215
+ let nextYear = currentYear;
216
+ if (nextMonth > 12) {
217
+ nextMonth = 1;
218
+ nextYear++;
219
+ }
220
+ let nextDate = 1;
221
+ while (result.length < 42) {
222
+ result.push({
223
+ year: nextYear,
224
+ month: nextMonth,
225
+ date: nextDate++,
226
+ currentMonth: false
227
+ });
228
+ }
229
+ return result;
230
+ }, [currentYear, currentMonth]);
231
+ const handlePrevMonth = useCallback(() => {
232
+ let newMonth = currentMonth - 1;
233
+ let newYear = currentYear;
234
+ if (newMonth < 1) {
235
+ newMonth = 12;
236
+ newYear--;
237
+ }
238
+ setCurrentMonth(newMonth);
239
+ setCurrentYear(newYear);
240
+ setPrev(false);
241
+ }, [currentMonth, currentYear]);
242
+ const handleNextMonth = useCallback(() => {
243
+ let newMonth = currentMonth + 1;
244
+ let newYear = currentYear;
245
+ if (newMonth > 12) {
246
+ newMonth = 1;
247
+ newYear++;
248
+ }
249
+ setCurrentMonth(newMonth);
250
+ setCurrentYear(newYear);
251
+ setNext(false);
252
+ }, [currentMonth, currentYear]);
253
+ useEffect(() => {
254
+ if (goNext) {
255
+ handleNextMonth();
256
+ }
257
+ if (goPrev) {
258
+ handlePrevMonth();
259
+ }
260
+ }, [goNext, goPrev, handleNextMonth, handlePrevMonth]);
261
+ const calendarMap = useMemo(() => {
262
+ const map = /* @__PURE__ */ new Map();
263
+ calendarData.forEach((item) => {
264
+ map.set(item.date, item.events);
265
+ });
266
+ return map;
267
+ }, [calendarData]);
268
+ const getEventsForDate = (year, month, date) => {
269
+ var _a;
270
+ const [gy2, gm2, gd2] = jalaliToGregorian(year, month, date);
271
+ const key = `${gy2}-${String(gm2).padStart(2, "0")}-${String(gd2).padStart(
272
+ 2,
273
+ "0"
274
+ )}`;
275
+ return (_a = calendarMap.get(key)) != null ? _a : [];
276
+ };
277
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto h-full flex flex-col", dir: "rtl", children: [
278
+ /* @__PURE__ */ jsx(
279
+ "div",
280
+ {
281
+ style: {
282
+ ...headerTextColor ? { color: headerTextColor } : {},
283
+ ...headerColor ? { backgroundColor: headerColor } : { backgroundColor: "#F1F4F9" },
284
+ ...borderColor ? { borderColor } : { borderColor: "#d9d7e0" }
285
+ },
286
+ className: `grid-cols-7 hidden 350:grid text-center bg-[#F1F4F9] border border-b-0 font-semibold rounded-t-[10px] py-2.5`,
287
+ children: weekDays.map((day, index) => /* @__PURE__ */ jsx("p", { className: "350:text-[13px]", children: day }, index))
288
+ }
289
+ ),
290
+ /* @__PURE__ */ jsx(
291
+ "div",
292
+ {
293
+ style: {
294
+ backgroundColor: headerColor ? headerColor : "#F1F4F9"
295
+ },
296
+ className: `grid-cols-7 grid 350:hidden text-center bg-[#F1F4F9] font-semibold rounded-t-[10px] py-2.5`,
297
+ children: weekDays.map((day, index) => /* @__PURE__ */ jsx("p", { className: "text-12 350:hidden", children: day[0] }, index))
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsx(
301
+ "div",
302
+ {
303
+ style: borderColor ? { borderColor } : { borderColor: "#d9d7e0" },
304
+ className: "grid grid-cols-7 flex-1 border-l-0 border-b-0 border",
305
+ children: days.map((d, i) => {
306
+ const events = getEventsForDate(d.year, d.month, d.date);
307
+ const isHolidayDay = events.some((event) => event.holiday);
308
+ const columnIndex = i % 7;
309
+ let tooltipPosition = "";
310
+ if (columnIndex <= 1) {
311
+ tooltipPosition = "right-0";
312
+ } else if (columnIndex >= 5) {
313
+ tooltipPosition = "left-0";
314
+ } else {
315
+ tooltipPosition = "left-1/2 -translate-x-1/2";
316
+ }
317
+ return /* @__PURE__ */ jsxs(
318
+ "div",
319
+ {
320
+ style: {
321
+ ...!d.currentMonth && outsideMonthDaysBg ? { backgroundColor: outsideMonthDaysBg } : {},
322
+ ...!d.currentMonth && outsideMonthDaysTextColor ? { color: outsideMonthDaysTextColor } : !d.currentMonth ? { color: "#99a1af " } : {},
323
+ ...daysBgColor && d.currentMonth ? { backgroundColor: daysBgColor } : {},
324
+ ...daysTextColor && d.currentMonth ? { color: daysTextColor } : {},
325
+ ...holidayTextColor && isHolidayDay && d.currentMonth ? { color: holidayTextColor } : {},
326
+ ...isHolidayDay && holidaysBgColor && d.currentMonth ? { backgroundColor: holidaysBgColor } : {},
327
+ ...d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth && currentDayBgColor ? { backgroundColor: currentDayBgColor } : {},
328
+ ...d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth && currentDaytextColor ? { backgroundColor: currentDaytextColor } : {},
329
+ ...borderColor ? { borderColor } : { borderColor: "#d9d7e0" }
330
+ },
331
+ className: `
332
+ border-r-0 border-t-0 border p-[5px]
333
+ flex justify-center items-center 390:text-14 390:p-[10px] 700:p-[15px]
334
+ relative text-12 group
335
+ ${d.currentMonth ? "" : ""}
336
+ ${d.year === todayYear && d.month === todayMonth && d.date === todayDate && d.currentMonth ? "bg-blue-500 text-white" : ""}
337
+ ${isHolidayDay && d.currentMonth ? "text-red-500" : ""}
338
+ `,
339
+ children: [
340
+ d.date,
341
+ showEvents && d.currentMonth && /* @__PURE__ */ jsx(
342
+ "div",
343
+ {
344
+ className: `
345
+ absolute hidden group-hover:block
346
+ bg-white border z-50 border-gray-300 overflow-hidden rounded shadow-lg
347
+ top-full mt-2 w-[220px] text-sm text-right ${tooltipPosition}
348
+ `,
349
+ children: (() => {
350
+ const [gy2, gm2, gd2] = jalaliToGregorian(
351
+ d.year,
352
+ d.month,
353
+ d.date
354
+ );
355
+ const gregorianMonthName = gregorianMonthsFa[gm2];
356
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
357
+ /* @__PURE__ */ jsxs(
358
+ "div",
359
+ {
360
+ className: `
361
+ flex p-2 justify-between mb-2 pb-2
362
+ bg-linear-to-r from-[#00A1EE] to-[#1349E6] font-semibold text-white
363
+ ${isHolidayDay ? "from-red-500 via-red-600 to-rose-700" : ""}
364
+ `,
365
+ children: [
366
+ /* @__PURE__ */ jsx("span", { children: weekDays[i % 7] }),
367
+ /* @__PURE__ */ jsxs("span", { children: [
368
+ d.year,
369
+ "/",
370
+ d.month,
371
+ "/",
372
+ d.date
373
+ ] })
374
+ ]
375
+ }
376
+ ),
377
+ /* @__PURE__ */ jsxs("div", { className: "text-[11px] px-2 text-gray-700 mb-2 pb-2 border-b border-gray-200", children: [
378
+ gd2,
379
+ " ",
380
+ gregorianMonthName,
381
+ " ",
382
+ gy2
383
+ ] }),
384
+ events.length > 0 ? /* @__PURE__ */ jsx("div", { className: "p-2 pt-0", children: /* @__PURE__ */ jsx("ul", { className: "list-disc pr-4 flex flex-col", children: events.map((event, index) => /* @__PURE__ */ jsx(
385
+ "li",
386
+ {
387
+ className: `text-10 ${isHolidayDay ? "text-red-600" : "text-[#23242e]"}`,
388
+ children: event.event
389
+ },
390
+ index
391
+ )) }) }) : /* @__PURE__ */ jsx("p", { className: "text-10 p-2 pt-0 text-[#23242e]", children: "\u0631\u0648\u06CC\u062F\u0627\u062F\u06CC \u0648\u062C\u0648\u062F \u0646\u062F\u0627\u0631\u062F" })
392
+ ] });
393
+ })()
394
+ }
395
+ )
396
+ ]
397
+ },
398
+ i
399
+ );
400
+ })
401
+ }
402
+ )
403
+ ] });
404
+ }
405
+ export {
406
+ Calendar
407
+ };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "react-jalali-events-calendar",
3
+ "version": "1.0.1",
4
+ "description": "Persian (Jalali) calendar for React",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "sideEffects": false,
19
+ "peerDependencies": {
20
+ "react": ">=17",
21
+ "react-dom": ">=17",
22
+ "tailwindcss": ">=3.0.0"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.5.1",
29
+ "typescript": "^5.9.3",
30
+ "@types/react": "^19.0.0",
31
+ "@types/react-dom": "^19.0.0"
32
+ }
33
+ }