@m4ore/ios-date-picker
v1.0.4
Published
iOS-styled date picker component with wheel picker and calendar grid for web applications
Maintainers
Readme
iOS Date Picker
iOS 風格的日期選擇器元件,結合滾輪式年月切換與日曆式日期選擇,提供原生般的操作體驗。
Live Demo - 前往 Storybook 查看元件展示與互動文件
特色
- iOS 原生風格 - 符合 iOS Human Interface Guidelines
- 雙模式整合 - 滾輪快速切換年月 + 日曆直覺選日期
- 零框架依賴 - 純 JavaScript,可整合至任何專案
- 觸控最佳化 - 44px 觸擊區域、CSS Scroll Snap 滑動吸附
- 兩種使用模式 - 全頁式嵌入 / 彈窗式呼叫
- 彈性配置 - 內建預設組態,支援自訂擴充
快速開始
方式一:Vite / Webpack / 現代打包工具
安裝
npm install @m4ore/ios-date-picker vanilla-calendar-pro@^2.9.0main.js
import { createDatePicker, DatePickerModal } from "@m4ore/ios-date-picker";
import "@m4ore/ios-date-picker/css";
import "vanilla-calendar-pro/build/vanilla-calendar.min.css";
document.addEventListener("DOMContentLoaded", () => {
// 全頁式
createDatePicker("my-picker", "birthday", {
onConfirm: (date) => console.log("選擇的日期:", date),
});
// 彈窗式(如需使用)
DatePickerModal.init();
document.querySelector(".date-fields").addEventListener("click", () => {
DatePickerModal.open({
preset: "birthday",
fields: {
year: document.getElementById("birth-year"),
month: document.getElementById("birth-month"),
day: document.getElementById("birth-day"),
},
});
});
});index.html
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Date Picker Demo</title>
</head>
<body>
<!-- 全頁式容器 -->
<div id="my-picker"></div>
<!-- 彈窗式欄位(如需使用) -->
<div class="date-fields">
<input type="text" id="birth-year" placeholder="年" readonly />
<span>/</span>
<input type="text" id="birth-month" placeholder="月" readonly />
<span>/</span>
<input type="text" id="birth-day" placeholder="日" readonly />
</div>
<!-- 彈窗結構(如需使用) -->
<div class="overlay" id="date-picker-overlay"></div>
<div class="bottom-sheet" id="date-picker-bottom-sheet">
<div class="bottom-sheet__header">
<div class="grabber"></div>
</div>
<div class="bottom-sheet__content">
<div id="date-picker-container"></div>
</div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>方式二:CDN(純 HTML,無打包工具)
將以下程式碼貼入 HTML 檔案即可運作:
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Date Picker Demo</title>
<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/build/vanilla-calendar.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@m4ore/ios-date-picker@1/dist/ios-date-picker.css" />
</head>
<body>
<div id="my-picker"></div>
<!-- JS -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/vanilla-calendar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@m4ore/ios-date-picker@1/dist/ios-date-picker.min.js"></script>
<script>
const { createDatePicker } = IOSDatePickerLib;
createDatePicker("my-picker", "birthday", {
imgPath: "https://cdn.jsdelivr.net/npm/@m4ore/ios-date-picker@1/img",
onConfirm: (date) => console.log("選擇的日期:", date),
});
</script>
</body>
</html>使用模式
| 比較項目 | 全頁式 | 彈窗式 |
|---------|--------|--------|
| 顯示方式 | 直接嵌入頁面 | 點擊後彈出 |
| 適用情境 | 表單主要就是選日期 | 日期是表單中的一個欄位 |
| API | createDatePicker() | DatePickerModal.open() |
| 關閉方式 | 不需關閉,常駐顯示 | 確認/返回/下滑關閉 |
全頁式模式
const picker = createDatePicker('my-picker', 'birthday', {
onConfirm: (date) => {
console.log('選擇的日期:', date); // 2024-06-15
}
});彈窗式模式
HTML 結構
放在 </body> 之前,不要放在 <form> 裡面:
<!-- 日期欄位 -->
<div class="date-fields">
<input type="text" id="birth-year" placeholder="年" readonly>
<span>/</span>
<input type="text" id="birth-month" placeholder="月" readonly>
<span>/</span>
<input type="text" id="birth-day" placeholder="日" readonly>
</div>
<!-- 彈窗結構 -->
<div class="overlay" id="date-picker-overlay"></div>
<div class="bottom-sheet" id="date-picker-bottom-sheet">
<div class="bottom-sheet__header">
<div class="grabber"></div>
</div>
<div class="bottom-sheet__content">
<div id="date-picker-container"></div>
</div>
</div>JavaScript
// 初始化(只需執行一次)
DatePickerModal.init();
// 綁定點擊事件
document.querySelector('.date-fields').addEventListener('click', () => {
DatePickerModal.open({
preset: 'birthday',
fields: {
year: document.getElementById('birth-year'),
month: document.getElementById('birth-month'),
day: document.getElementById('birth-day')
}
});
});內建預設
| 預設類型 | 標題 | 預設日期 | 日期範圍 |
|---------|------|---------|---------|
| birthday | 生日 | 2000-01-01 | 1900-01-01 ~ 今日 |
| memberCreated | 會員建立時間 | 今日 | 2015 ~ 今日 |
| accounting | 帳務日期 | 今日 | 2015 ~ 今日 |
| orderManagement | 訂單日期 | 今日 | 2015 ~ 今日 |
API
createDatePicker()
createDatePicker(containerId, presetType, options)| 參數 | 類型 | 必填 | 說明 |
|------|------|------|------|
| containerId | string | ✓ | 容器元素 ID |
| presetType | string | ✓ | 預設類型 |
| options | object | - | 自訂選項 |
options
| 選項 | 類型 | 預設值 | 說明 |
|------|------|--------|------|
| title | string | '選擇日期' | 導覽列標題 |
| defaultDate | string | 今日日期 | 初始顯示日期 |
| currentValue | string | null | 欄位目前已選值,優先於 defaultDate |
| minDate | string | '1900-01-01' | 最小可選日期 |
| maxDate | string | null | 最大可選日期,可設為 'today' |
| minYear | number | 1900 | 年份滾輪最小年份 |
| maxYear | number | 今年 + 10 | 年份滾輪最大年份 |
| imgPath | string | '../img' | 圖示資料夾路徑 |
| onConfirm | function | null | 點擊確認時觸發 |
| onBack | function | null | 點擊返回時觸發 |
| onDateChange | function | null | 選擇日期變更時觸發 |
日期格式說明
所有日期參數皆使用 YYYY-MM-DD 格式(ISO 8601):
{
defaultDate: '2000-01-01', // 固定日期
defaultDate: 'today', // 特殊值:今日
minDate: '2020-01-01', // 最早可選 2020-01-01
maxDate: '2025-12-31', // 最晚可選 2025-12-31
maxDate: 'today', // 特殊值:最晚可選今日
currentValue: '2024-06-15', // 欄位已有值時傳入
}imgPath 設定
// Vite/Webpack:通常不需設定,使用預設即可
// CDN:必須設定完整路徑
imgPath: 'https://cdn.jsdelivr.net/npm/@m4ore/ios-date-picker@1/img'Callback 函式
{
onConfirm: (date) => {
console.log(date); // '2024-06-15'
},
onBack: () => {
console.log('使用者點擊返回');
},
onDateChange: (date) => {
console.log('日期變更為:', date); // 每次點擊日期都會觸發
}
}DatePickerModal
// 初始化
DatePickerModal.init(config)
// 開啟
DatePickerModal.open({
preset: 'birthday',
fields: { year, month, day },
imgPath: 'img'
})
// 關閉
DatePickerModal.close()樣式客製化
.ios-date-picker {
--picker-selected: #FF812A; /* 選中狀態 */
--picker-primary: #007AFF; /* iOS 藍 */
--picker-bg: #F2F2F7; /* 背景 */
--picker-body-height: 340px; /* 日曆區高度 */
}技術規格
| 項目 | 規格 |
|------|------|
| 依賴套件 | Vanilla Calendar Pro v2.9.x |
| 瀏覽器支援 | Chrome 80+, Safari 13+, Firefox 75+, Edge 80+ |
| 行動裝置 | iOS 13+, Android 8+ |
| 日期格式 | YYYY-MM-DD |
依賴套件
- Vanilla Calendar Pro v2.9.x (MIT License)
Q&A 常見問題
Q: 為什麼在 <script> 標籤中使用 import 會報錯?
錯誤訊息: Uncaught SyntaxError: Cannot use import statement outside a module
原因: import 是 ES Module 語法,只能在以下情況使用:
- 打包工具環境(Vite/Webpack)的
.js檔案中 <script type="module">中,但只能 import URL,不能 import 套件名稱
解決方式:
- 使用 Vite/Webpack:所有 import 都寫在
.js檔案中 - 純 HTML:使用 CDN 方式,用
<script src="...">載入
Q: 為什麼圖示(箭頭)會破圖?
原因: 打包工具環境下,預設的 imgPath 相對路徑可能找不到圖片。
解決方式: 設定 imgPath 為 CDN 路徑:
createDatePicker('my-picker', 'birthday', {
imgPath: 'https://cdn.jsdelivr.net/npm/@m4ore/ios-date-picker@1/img',
onConfirm: (date) => console.log(date)
});Q: 需要手動 import VanillaCalendar 嗎?
不需要。 套件內部已經處理好依賴,你只需要:
import { createDatePicker } from "@m4ore/ios-date-picker";
import "@m4ore/ios-date-picker/css";
import "vanilla-calendar-pro/build/vanilla-calendar.min.css";
// 直接使用,不需要 import VanillaCalendar
createDatePicker("my-picker", "birthday", {...});Q: Vite/Webpack 和 CDN 有什麼差別?
| 項目 | Vite/Webpack | CDN |
|------|-------------|-----|
| 安裝方式 | npm install | 無需安裝 |
| 引入方式 | import 在 .js 檔案中 | <script src="..."> 在 HTML 中 |
| 適用情境 | 現代前端專案 | 簡單網頁、快速原型 |
| 套件物件 | 直接 import 使用 | 從 IOSDatePickerLib 取得 |
授權
MIT License
© 2025 M4ORE Inc. All rights reserved.
