
Company News
Andrew Becherer Joins Socket as Chief Information Security Officer
Socket’s first CISO brings deep experience securing high-growth SaaS companies as open source supply chain threats accelerate.
su-infinite-calendar
Advanced tools
모바일 최적화된 무한 스크롤 캘린더 컴포넌트 (한국 공휴일 자동 지원)
A mobile-optimized infinite scroll calendar component for React with automatic Korean holidays support.
npm install react-infinite-calendar
다음 패키지들이 설치되어 있어야 합니다:
npm install react react-dom date-fns
import { InfiniteCalendar } from "react-infinite-calendar";
// 가장 간단한 사용법 (한국 공휴일 자동 포함)
function App() {
return <InfiniteCalendar />;
}
import { InfiniteCalendar } from "react-infinite-calendar";
function App() {
return (
<InfiniteCalendar
onDayAction={(date, dayInfo) => {
console.log("날짜 클릭:", date.toDateString());
if (dayInfo?.events.length > 0) {
console.log(`이벤트 ${dayInfo.events.length}개`);
}
}}
/>
);
}
// 간단한 방식 (권장)
const events = [
{
date: '2024-01-15',
title: '팀 미팅',
color: '#3b82f6'
},
{
date: '2024-01-20',
title: '프로젝트 검토'
// color, id 생략 시 자동 처리
}
]
<InfiniteCalendar
events={events}
onDayAction={(date, dayInfo) => {
console.log(`날짜 클릭: ${date.toDateString()}`)
if (dayInfo?.events.length > 0) {
console.log(`이벤트 ${dayInfo.events.length}개`)
}
}}
/>
// 상세한 방식 (기존 호환성)
const detailedEvents = [
{
id: '1',
title: '팀 미팅',
startTime: '2024-01-15T10:00:00',
endTime: '2024-01-15T11:00:00',
color: '#3b82f6'
}
]
// 커스텀 공휴일 추가 (자동 공휴일 + 커스텀)
const customHolidays = [
{ name: '회사 창립일', date: '2024-03-15', color: 'green' },
{ name: '팀 워크샵', date: '2024-06-20', color: 'purple' },
{ name: '프로젝트 마감', date: '2024-12-31', color: 'orange' },
{ name: '생일', date: '2024-08-15', color: 'pink' },
{ name: '특별 이벤트', date: '2024-10-10', color: '#4ecdc4' } // hex 색상도 가능
]
<InfiniteCalendar holidays={customHolidays} />
// 사용 가능한 색상:
// - 'red' (기본값) - 공휴일
// - 'green' - 개인 기념일
// - 'purple' - 특별 행사
// - 'orange' - 마감일, 알림
// - 'pink' - 생일, 기념일
// - 'yellow' - 일반 이벤트
// - '#hex' - 커스텀 색상 (예: '#4ecdc4', '#ff6b6b')
// 헤더 커스터마이징
<InfiniteCalendar
options={{
header: {
show: true,
monthTitle: true,
todayButton: false, // 오늘 버튼 숨김
weekDays: false, // 요일 헤더 숨김
datePicker: true
}
}}
/>
// 높이 설정
<InfiniteCalendar
options={{
height: 600 // 고정 높이 (px)
// height: 'auto' // 자동 높이 (기본값)
// height: '100vh' // CSS 단위도 가능
}}
/>
// 자동 높이 + 하단 네비게이션 고려
<InfiniteCalendar
options={{
autoHeight: {
bottomOffset: 80, // 하단 네비게이션 높이
minHeight: 300 // 최소 높이
}
}}
/>
// 상단 헤더 + 하단 네비게이션 모두 고려
<InfiniteCalendar
options={{
autoHeight: {
topOffset: 60, // 상단 헤더 높이
bottomOffset: 80, // 하단 네비게이션 높이
minHeight: 400, // 최소 높이
maxHeight: 800 // 최대 높이
}
}}
/>
// 스타일 커스터마이징
<InfiniteCalendar
options={{
classNames: {
container: 'my-calendar-container',
header: 'custom-header bg-gray-100',
dayCell: 'hover:bg-blue-50 rounded-lg',
todayButton: 'btn-primary'
}
}}
/>
// 최소 UI (임베디드용)
<InfiniteCalendar
options={{
header: false, // 전체 헤더 숨김
height: 400 // 고정 높이 권장
}}
/>
// 간단한 디버깅 (ERROR, WARN, INFO만 출력)
<InfiniteCalendar
options={{
debug: true
}}
/>
// 상세한 디버그 설정
<InfiniteCalendar
options={{
debug: {
enabled: true,
level: 'info', // 로그 레벨: 'error' | 'warn' | 'info' | 'debug'
showPerformance: false // 성능 로그 표시 여부
}
}}
/>
// 개발 환경에서만 활성화
<InfiniteCalendar
options={{
debug: process.env.NODE_ENV === 'development'
}}
/>
// API 기반 동적 이벤트 로딩
const fetchEvents = async (startDate: Date, endDate: Date) => {
const response = await fetch(`/api/events?start=${startDate.toISOString()}&end=${endDate.toISOString()}`)
return response.json()
}
<InfiniteCalendar
dynamicEvents={fetchEvents}
dynamicEventMapping={{
id: 'eventId',
title: 'eventName',
date: 'eventDate',
startTime: 'startTime',
endTime: 'endTime',
color: 'eventColor'
}}
onDynamicEventLoad={(startDate, endDate, events) => {
console.log(`로드된 이벤트: ${events.length}개 (${startDate.toDateString()} ~ ${endDate.toDateString()})`)
}}
/>
// 커스텀 데이터 변환
<InfiniteCalendar
dynamicEvents={fetchEvents}
dynamicEventTransform={(apiData) => ({
id: apiData.id || Math.random().toString(),
title: apiData.subject || 'Untitled',
date: apiData.scheduledDate,
color: apiData.priority === 'high' ? '#ff4444' : '#4444ff'
})}
/>
동적 이벤트 특징:
// 자체 API 키 사용 (선택사항)
<InfiniteCalendar
holidayServiceKey={process.env.HOLIDAY_SERVICE_KEY}
/>
// 전체 옵션 사용
<InfiniteCalendar
events={events}
holidays={customHolidays}
holidayServiceKey={myServiceKey}
onDayAction={(date, dayInfo) => {
openEventModal(date, dayInfo?.events)
}}
options={{
header: {
show: true,
monthTitle: true,
todayButton: true,
weekDays: true,
datePicker: false
},
classNames: {
container: 'shadow-lg rounded-xl',
dayCell: 'custom-day-cell'
},
height: 'auto',
initialDate: new Date()
}}
/>
interface CalendarEvent {
id: string;
title: string;
startTime: string; // ISO date string
endTime: string; // ISO date string
description?: string;
color?: string;
metadata?: Record<string, any>;
}
interface Holiday {
id?: string; // Optional (auto-generated if not provided)
name: string;
date: string; // YYYY-MM-DD format
color?: string; // Text color for the date (default: 'red')
}
Supported Colors:
'red' 🔴 (default) - Public holidays, important dates'green' 🟢 - Personal celebrations, anniversaries'purple' 🟣 - Special occasions, cultural events'orange' 🟠 - Deadlines, reminders, warnings'pink' 🩷 - Birthdays, personal milestones'yellow' 🟡 - Casual events, notes'#ff6b6b', '#4ecdc4', '#45b7d1'type CountryCode = "KR" | "US" | "JP" | "CN" | "GB" | "DE" | "FR" | "IT" | "ES";
Currently supported for auto-holidays: KR (Korea) only
The component uses Tailwind CSS classes. You can customize the appearance by overriding the CSS classes or using CSS-in-JS solutions.
For advanced use cases, you can access the underlying Zustand store:
import { useCalendarUIStore } from "react-infinite-calendar";
function CustomCalendarControls() {
const { activeMonth, setActiveMonth } = useCalendarUIStore();
return (
<button onClick={() => setActiveMonth(new Date())}>Go to Today</button>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
events | CalendarEvent[] | [] | 정적 이벤트 배열 |
holidays | Holiday[] | [] | 커스텀 공휴일 배열 |
dynamicEvents | (startDate: Date, endDate: Date) => Promise<any[]> | - | 동적 이벤트 로딩 함수 |
dynamicEventMapping | object | - | API 응답 필드 매핑 |
dynamicEventTransform | (apiData: any) => CalendarEvent | - | 커스텀 데이터 변환 함수 |
onDynamicEventLoad | (startDate: Date, endDate: Date, events: CalendarEvent[]) => void | - | 동적 이벤트 로드 완료 콜백 |
onDayAction | (date: Date, dayInfo?: { events: CalendarEvent[], holidays: Holiday[] }) => void | - | 날짜 클릭 시 콜백 |
onEventClick | (event: CalendarEvent) => void | - | 이벤트 클릭 시 콜백 |
locale | string | 'ko-KR' | 로케일 설정 |
holidayServiceKey | string | - | 공휴일 API 키 (한국만 해당) |
options | CalendarOptions | - | UI/스타일 옵션 |
interface CalendarOptions {
// Display 옵션
header?:
| boolean
| {
show?: boolean;
monthTitle?: boolean;
todayButton?: boolean;
weekDays?: boolean;
datePicker?: boolean;
};
// 스타일 커스터마이징
classNames?: {
container?: string;
header?: string;
monthTitle?: string;
weekDay?: string;
dayCell?: string;
todayButton?: string;
};
// 높이 설정
height?: number | "auto" | string;
autoHeight?: {
topOffset?: number; // 상단 여백 (기본: 0)
bottomOffset?: number; // 하단 여백 (기본: 20)
minHeight?: number; // 최소 높이 (기본: 400)
maxHeight?: number; // 최대 높이 (기본: window.innerHeight)
};
// 디버그 옵션
debug?:
| boolean
| {
enabled?: boolean; // 로그 활성화/비활성화 (기본: false)
level?: "error" | "warn" | "info" | "debug"; // 로그 레벨 (기본: 'error')
showPerformance?: boolean; // 성능 로그 표시 (기본: false)
};
// 로그 레벨 설명:
// - 'error': 에러만 출력
// - 'warn': 에러 + 경고 출력
// - 'info': 에러 + 경고 + 정보 출력 (권장)
// - 'debug': 모든 로그 출력 (개발용)
// 기타 UI 옵션
initialDate?: Date;
}
import { InfiniteCalendar } from "react-infinite-calendar";
// 영어 사용자
function EnglishCalendar() {
const holidays = [
{ name: "Independence Day", date: "2024-07-04", color: "red" },
{ name: "Thanksgiving", date: "2024-11-28", color: "orange" },
];
return (
<InfiniteCalendar
locale="en-US" // 로케일 설정 필수
holidays={holidays} // 공휴일 직접 제공
/>
);
}
// 일본어 사용자
function JapaneseCalendar() {
return <InfiniteCalendar locale="ja-JP" holidays={myJapaneseHolidays} />;
}
ko-KR, ko - 한국어 (기본값, 공휴일 자동 로드)en-US, en - 영어ja-JP, ja - 일본어zh-CN, zh - 중국어de-DE, de - 독일어fr-FR, fr - 프랑스어it-IT, it - 이탈리아어es-ES, es - 스페인어별도 설정 없이 한국 공휴일이 자동으로 표시됩니다!
// 설정 없이 바로 사용 가능 - 한국 공휴일 자동 표시
<InfiniteCalendar />
패키지에 내장된 공휴일 서비스가 자동으로 다음을 제공합니다:
높은 사용량이나 커스터마이징이 필요한 경우:
<InfiniteCalendar holidayServiceKey="your_custom_key_here" />
| 브라우저 | 최소 버전 | 비고 |
|---|---|---|
| Chrome | 58+ | 완전 지원 |
| Firefox | 55+ | 완전 지원 |
| Safari | 12.1+ | 완전 지원 |
| iOS Safari | 12.2+ | 모바일 최적화 |
| Edge | 79+ | 완전 지원 |
이 패키지는 모바일 Safari에서 발생할 수 있는 터치 이슈들을 미리 방지합니다:
-webkit-overflow-scrolling: touch 적용// 모바일 Safari에서 더 부드러운 스크롤
<InfiniteCalendar
options={{
height: 'auto',
autoHeight: {
bottomOffset: 100, // Safari 주소창 고려
topOffset: 60 // 상단 네비게이션 고려
}
}}
/>
터치 최적화 기능:
touch-action: manipulation 으로 더블탭 지연 제거MIT
Contributions are welcome! Please feel free to submit a Pull Request.
FAQs
A mobile-optimized infinite scroll calendar component for React
The npm package su-infinite-calendar receives a total of 0 weekly downloads. As such, su-infinite-calendar popularity was classified as not popular.
We found that su-infinite-calendar demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket’s first CISO brings deep experience securing high-growth SaaS companies as open source supply chain threats accelerate.

Company News
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.