npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mobile-react-infinite-calendar

v1.2.1

Published

A mobile-optimized infinite scroll calendar component for React

Readme

React Infinite Calendar Mobile

모바일 최적화된 무한 스크롤 캘린더 컴포넌트 (한국 공휴일 지원)

A mobile-optimized infinite scroll calendar component for React with Korean holidays support.

특징

  • 🔄 무한 스크롤: 월간 부드러운 무한 스크롤
  • 📱 모바일 최적화: 터치 친화적 디자인과 반응형 레이아웃
  • 🎯 자동 포커스: IntersectionObserver를 통한 자동 월 감지
  • 📅 날짜 선택기: 내장된 연도/월 드롭다운 선택기
  • 🎉 한국 공휴일 지원: API 키 설정으로 한국 공휴일 표시
  • 🚀 동적 이벤트 로딩: API 기반 스마트 이벤트 로딩 및 캐싱
  • 🎨 커스터마이징: 유연한 테마 및 스타일 옵션
  • 🌐 다국어 지원: 여러 언어 지원 (ko, en, ja, zh, de, fr, it, es)
  • 고성능: 가상화 렌더링으로 부드러운 성능
  • 🔧 최적화된 상태 관리: 격리된 로컬 상태로 성능 최적화
  • 📦 TypeScript: 완벽한 TypeScript 지원
  • 🏗️ 모듈러 아키텍처: 비즈니스 로직과 UI 완전 분리
  • 🌐 브라우저 호환성: 모던 브라우저 및 Safari 12.1+ 지원

설치

npm install mobile-react-infinite-calendar

Peer Dependencies

다음 패키지들이 설치되어 있어야 합니다:

npm install react react-dom date-fns

브라우저 호환성

지원 브라우저

| 브라우저 | 최소 버전 | 비고 | | -------------- | --------- | ----------------- | | Chrome | 58+ | 완전 지원 | | Firefox | 55+ | 완전 지원 | | Safari | 12.1+ | 완전 지원 | | iOS Safari | 12.2+ | 모바일 최적화 | | Edge | 79+ | 완전 지원 |

🔑 핵심 기능 호환성

  • IntersectionObserver: Safari 12.1+ 지원
  • CSS Grid/Flexbox: 모든 모던 브라우저
  • Touch Events: 모바일 Safari 완전 지원
  • Date API: 네이티브 JavaScript Date 사용

📱 모바일 Safari 최적화

이 패키지는 모바일 Safari에서 발생할 수 있는 터치 이슈들을 미리 방지합니다:

  • Passive Scroll Events: 터치 성능 최적화
  • Bounce Effect 제어: iOS 스크롤 바운스 효과 처리
  • Touch Scrolling: -webkit-overflow-scrolling: touch 적용
  • 주소창 동적 높이: 자동 높이 계산으로 대응

터치 최적화 기능:

  • 🚫 스크롤 바운스 중 무한 로딩 방지
  • ⚡ 하드웨어 가속 스크롤 활성화
  • 📏 동적 뷰포트 높이 자동 대응
  • 🎯 버튼/셀렉트 터치 최적화:
    • 최소 44px 터치 타겟 크기 보장
    • touch-action: manipulation 으로 더블탭 지연 제거
    • 모바일에서 hover 효과 자동 비활성화
    • iOS 하이라이트 제거

빠른 시작

import { InfiniteCalendar } from "mobile-react-infinite-calendar";

// 가장 간단한 사용법 (한국 공휴일 지원)
function App() {
  return <InfiniteCalendar holidayServiceKey="your_api_key_here" />;
}

사용 가이드

1. 기본 사용법

import { InfiniteCalendar } from "mobile-react-infinite-calendar";

function App() {
  return (
    <InfiniteCalendar
      holidayServiceKey="your_api_key_here"
      onDayAction={(date, dayInfo) => {
        console.log("날짜 클릭:", date.toDateString());
        if (dayInfo?.events.length > 0) {
          console.log(`이벤트 ${dayInfo.events.length}개`);
        }
      }}
    />
  );
}

2. 이벤트 관리

// 간단한 방식 (권장)
const events = [
  {
    date: '2024-01-15',
    title: '팀 미팅',
    color: '#3b82f6'
  },
  {
    date: '2024-01-20',
    title: '프로젝트 검토'
    // color, id 생략 시 자동 처리
  }
]

// 원본 데이터를 포함한 이벤트
const eventsWithOriginalData = [
  {
    date: '2024-01-15',
    title: '팀 미팅',
    color: '#3b82f6',
    originalData: {
      meetingId: 123,
      location: '회의실 A',
      participants: ['김철수', '이영희'],
      agenda: '프로젝트 진행 상황 검토'
    }
  }
]

<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  events={eventsWithOriginalData}
  onDayAction={(date, dayInfo) => {
    // 원본 데이터 접근
    const event = dayInfo?.events[0]
    if (event?.originalData) {
      console.log('미팅 위치:', event.originalData.location)
      console.log('참석자:', event.originalData.participants)
    }
    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'
  }
]

3. 한국 공휴일 설정

// 🔑 API 키 설정 (필수)
<InfiniteCalendar holidayServiceKey="your_api_key_here" />

// 커스텀 공휴일 추가 (자동 공휴일 + 커스텀)
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
  holidayServiceKey="your_api_key_here"
  holidays={customHolidays}
/>

한국 공휴일 API 키 발급

  1. 공공데이터포털 접속
  2. "특일정보" API 검색 및 신청
  3. 발급받은 키를 holidayServiceKey에 설정
// 개발 환경 설정
// .env 파일
REACT_APP_HOLIDAY_API_KEY=your_api_key_here

// 사용
<InfiniteCalendar
  holidayServiceKey={process.env.REACT_APP_HOLIDAY_API_KEY}
/>

지원되는 공휴일:

  • 🎌 신정, 설날, 추석 등 주요 공휴일
  • 🏛️ 어린이날, 현충일, 광복절 등 국가 기념일
  • 🌸 부처님오신날 등 종교 기념일
  • 📅 대체공휴일 및 임시공휴일

사용 가능한 색상:

  • 'red' 🔴 (기본값) - 공휴일
  • 'green' 🟢 - 개인 기념일
  • 'purple' 🟣 - 특별 행사
  • 'orange' 🟠 - 마감일, 알림
  • 'pink' 🩷 - 생일, 기념일
  • 'yellow' 🟡 - 일반 이벤트
  • '#hex' - 커스텀 색상 (예: '#4ecdc4', '#ff6b6b')

4. UI 커스터마이징

// 헤더 커스터마이징
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    header: {
      show: true,
      monthTitle: true,
      todayButton: false,    // 오늘 버튼 숨김
      weekDays: false,       // 요일 헤더 숨김
      datePicker: true
    }
  }}
/>

// 높이 설정
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    height: 600        // 고정 높이 (px)
    // height: 'auto'  // 자동 높이 (기본값)
    // height: '100vh' // CSS 단위도 가능
  }}
/>

// 자동 높이 + 하단 네비게이션 고려
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    autoHeight: {
      bottomOffset: 80,   // 하단 네비게이션 높이
      minHeight: 300      // 최소 높이
    }
  }}
/>

// 모바일 Safari에서 더 부드러운 스크롤
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    height: 'auto',
    autoHeight: {
      bottomOffset: 100,  // Safari 주소창 고려
      topOffset: 60       // 상단 네비게이션 고려
    }
  }}
/>

// 스타일 커스터마이징
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    classNames: {
      container: 'my-calendar-container',
      header: 'custom-header bg-gray-100',
      dayCell: 'hover:bg-blue-50 rounded-lg',
      todayButton: 'btn-primary'
    }
  }}
/>

// 최소 UI (임베디드용)
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    header: false,  // 전체 헤더 숨김
    height: 400     // 고정 높이 권장
  }}
/>

5. 디버그 및 개발 도구

// 간단한 디버깅 (ERROR, WARN, INFO만 출력)
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    debug: true
  }}
/>

// 상세한 디버그 설정
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    debug: {
      enabled: true,
      level: 'info',           // 로그 레벨: 'error' | 'warn' | 'info' | 'debug'
      showPerformance: false   // 성능 로그 표시 여부
    }
  }}
/>

// 개발 환경에서만 활성화
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  options={{
    debug: process.env.NODE_ENV === 'development'
  }}
/>

고급 기능

1. 동적 이벤트 로딩

// API 기반 동적 이벤트 로딩
const fetchEvents = async (startDate: Date, endDate: Date) => {
  const response = await fetch(`/api/events?start=${startDate.toISOString()}&end=${endDate.toISOString()}`)
  return response.json()
}

<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  dynamicEvents={fetchEvents}
  dynamicEventMapping={{
    id: 'eventId',
    title: 'eventName',
    date: 'eventDate',
    startTime: 'startTime',
    endTime: 'endTime',
    color: 'eventColor'
  }}
  onDayAction={(date, dayInfo) => {
    // 동적 이벤트의 원본 데이터 접근
    const event = dayInfo?.events[0]
    if (event?.originalData) {
      console.log('원본 API 데이터:', event.originalData)
      // API에서 받은 모든 필드에 접근 가능
    }
  }}
  onDynamicEventLoad={(startDate, endDate, events) => {
    console.log(`로드된 이벤트: ${events.length}개 (${startDate.toDateString()} ~ ${endDate.toDateString()})`)
  }}
/>

// 커스텀 데이터 변환
<InfiniteCalendar
  holidayServiceKey="your_api_key_here"
  dynamicEvents={fetchEvents}
  dynamicEventTransform={(apiData) => ({
    id: apiData.id || Math.random().toString(),
    title: apiData.subject || 'Untitled',
    date: apiData.scheduledDate,
    color: apiData.priority === 'high' ? '#ff4444' : '#4444ff',
    originalData: apiData  // 원본 데이터 보존
  })}
/>

동적 이벤트 특징:

  • 🔄 자동 로딩: 스크롤 시 필요한 월의 이벤트만 로드
  • 💾 스마트 캐싱: 이미 로드된 월은 캐시에서 빠르게 표시
  • 📅 선행 로딩: 현재 월 기준 ±2개월 미리 로드
  • 🎯 점프 감지: 데이트피커로 먼 날짜 이동 시 확장 로드
  • 🔄 재시도 로직: 네트워크 오류 시 자동 재시도
  • 📊 유연한 매핑: 다양한 API 응답 구조 지원

2. 다국어 지원

// 영어 사용자
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 - 스페인어

3. 고급 훅 사용

import { useCalendarComposer } from "su-react-infinite-calendar";

function CustomCalendarControls() {
  const { activeMonth, setActiveMonth, monthsData, addNextMonth } =
    useCalendarComposer({
      events: [],
      holidays: [],
      holidayServiceKey: "your_api_key_here",
    });

  return (
    <button onClick={() => setActiveMonth(new Date())}>Go to Today</button>
  );
}

4. 전체 옵션 예시

<InfiniteCalendar
  events={events}
  holidays={customHolidays}
  holidayServiceKey="your_api_key_here"
  dynamicEvents={fetchEvents}
  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(),
    debug: process.env.NODE_ENV === "development",
  }}
/>

타입 정의

CalendarEvent

// 제네릭을 사용한 유연한 이벤트 타입
interface CalendarEvent<T = any> {
  date: string;        // YYYY-MM-DD 형식 (필수)
  title?: string;      // 툴팁이나 클릭 시 표시용
  color?: string;      // 도트 색상 (기본: 빨강)
  id?: string;         // 고유 식별자 (자동 생성 가능)
  originalData?: T;    // 원본 데이터를 그대로 보관
}

// 사용 예시
type MyApiEvent = {
  eventId: number;
  eventName: string;
  startDateTime: string;
  endDateTime: string;
  location: string;
  participants: string[];
};

const events: CalendarEvent<MyApiEvent>[] = [{
  date: '2024-01-15',
  title: '팀 미팅',
  color: '#1a73e8',
  originalData: {
    eventId: 123,
    eventName: '월간 팀 미팅',
    startDateTime: '2024-01-15T10:00:00',
    endDateTime: '2024-01-15T11:30:00',
    location: '회의실 A',
    participants: ['김철수', '이영희']
  }
}];

Holiday

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')
}

CalendarOptions

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)
      };

  // 기타 UI 옵션
  initialDate?: Date;
}

API Reference

Props

| Prop | Type | Default | Description | | ----------------------- | ---------------------------------------------------------------------------------- | --------- | --------------------------- | | events | CalendarEvent[] | [] | 정적 이벤트 배열 | | holidays | Holiday[] | [] | 커스텀 공휴일 배열 | | holidayServiceKey | string | - | 공휴일 API 키 (한국만 해당) | | 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 | - | 날짜 클릭 시 콜백 | | locale | string | 'ko-KR' | 로케일 설정 | | options | CalendarOptions | - | UI/스타일 옵션 |

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.