{"_id":"@bw-ui/datepicker-multidate","_rev":"2-22ebd07648700fda56fc58b6e9dfe5f9","name":"@bw-ui/datepicker-multidate","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@bw-ui/datepicker-multidate","version":"1.0.0","keywords":["datepicker","multidate","multi-date","multiple-dates","calendar","date-selection","bw-ui"],"author":{"name":"BW UI"},"license":"MIT","_id":"@bw-ui/datepicker-multidate@1.0.0","maintainers":[{"name":"rchoudhary.dev","email":"rchoudhary.dev@gmail.com"}],"homepage":"https://github.com/bw-ui/bw-datepicker","bugs":{"url":"https://github.com/bw-ui/bw-datepicker/issues"},"dist":{"shasum":"198c5d35cbf84e14e8f919453b2a2c4a91d1e96c","tarball":"https://registry.npmjs.org/@bw-ui/datepicker-multidate/-/datepicker-multidate-1.0.0.tgz","fileCount":6,"integrity":"sha512-P6uGCaZFUMyS9G/Y/r43t9jbOGzbe/qggU6ocfTu/rxnaA5KqJHvxyJh8KQV2dI6W6oxkipRoTEmFyz2vMqd8A==","signatures":[{"sig":"MEUCID+x1xxQAUpe25OtaOxBZzAaYO38AKHMjYkl2Fab7X7EAiEAiB+rsIta/XUAk+mVVfVX/Jaw17haFEQGIChODlZuVEw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48951},"main":"dist/bw-multidate.min.js","type":"module","types":"src/index.d.ts","module":"dist/bw-multidate.esm.min.js","exports":{".":{"import":"./dist/bw-multidate.esm.min.js","require":"./dist/bw-multidate.min.js"},"./css":"./dist/bw-multidate.min.css"},"gitHead":"aa5702f44b5e49d0916f3fd601b691f782118f57","scripts":{"build":"node build.js"},"_npmUser":{"name":"rchoudhary.dev","email":"rchoudhary.dev@gmail.com"},"repository":{"url":"git+https://github.com/bw-ui/bw-datepicker.git","type":"git"},"_npmVersion":"10.9.3","description":"Multi-date selection plugin for @bw-ui/datepicker - Select multiple individual dates","directories":{},"_nodeVersion":"22.20.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.20.0"},"peerDependencies":{"@bw-ui/datepicker":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/datepicker-multidate_1.0.0_1764606157329_0.3817640271597307","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bw-ui/datepicker-multidate","version":"1.0.1","description":"Multi-date selection plugin for @bw-ui/datepicker - Select multiple individual dates","main":"dist/bw-multidate.min.js","module":"dist/bw-multidate.esm.min.js","exports":{".":{"import":"./dist/bw-multidate.esm.min.js","require":"./dist/bw-multidate.min.js"},"./css":"./dist/bw-multidate.min.css"},"types":"src/index.d.ts","scripts":{"build":"node build.js"},"keywords":["datepicker","multidate","multi-date","multiple-dates","calendar","date-selection","bw-ui"],"author":{"name":"BW UI"},"license":"MIT","peerDependencies":{"@bw-ui/datepicker":"^1.0.0"},"devDependencies":{"esbuild":"^0.20.0"},"repository":{"type":"git","url":"git+https://github.com/bw-ui/bw-datepicker.git"},"bugs":{"url":"https://github.com/bw-ui/bw-datepicker/issues"},"homepage":"https://github.com/bw-ui/bw-datepicker","type":"module","_id":"@bw-ui/datepicker-multidate@1.0.1","gitHead":"aa5702f44b5e49d0916f3fd601b691f782118f57","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-PN6z8V4ZNoasYJ/0S0JkdqncvTyut6E/2MIEQG3iSU+yFl2IOwVucyssiWf8kB9fr52285jzLuZXKazk5YUUuQ==","shasum":"e06566bee77de299b593ce7c6d69b71be03b7dbe","tarball":"https://registry.npmjs.org/@bw-ui/datepicker-multidate/-/datepicker-multidate-1.0.1.tgz","fileCount":6,"unpackedSize":49287,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDl2aldtxGsC2cvTc+wStHxzPNd+dpffGhAdEpxLqvcDQIgRkEQFVJwIFRG7hG/zXZUY+VMe3Um0x/RaOMSMORFf/M="}]},"_npmUser":{"name":"rchoudhary.dev","email":"rchoudhary.dev@gmail.com"},"directories":{},"maintainers":[{"name":"rchoudhary.dev","email":"rchoudhary.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/datepicker-multidate_1.0.1_1764606297602_0.8900907172955861"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-01T16:22:37.240Z","modified":"2025-12-01T16:24:58.044Z","1.0.0":"2025-12-01T16:22:37.493Z","1.0.1":"2025-12-01T16:24:57.789Z"},"bugs":{"url":"https://github.com/bw-ui/bw-datepicker/issues"},"author":{"name":"BW UI"},"license":"MIT","homepage":"https://github.com/bw-ui/bw-datepicker","keywords":["datepicker","multidate","multi-date","multiple-dates","calendar","date-selection","bw-ui"],"repository":{"type":"git","url":"git+https://github.com/bw-ui/bw-datepicker.git"},"description":"Multi-date selection plugin for @bw-ui/datepicker - Select multiple individual dates","maintainers":[{"name":"rchoudhary.dev","email":"rchoudhary.dev@gmail.com"}],"readme":"# @bw-ui/datepicker-multidate\r\n\r\nMulti-date selection plugin for [@bw-ui/datepicker](https://github.com/bw-ui/bw-datepicker).\r\n\r\nSelect multiple individual dates with toggle behavior, count limits, and flexible configuration.\r\n\r\n![Version](https://img.shields.io/npm/v/@bw-ui/datepicker-multidate)\r\n![License](https://img.shields.io/npm/l/@bw-ui/datepicker-multidate)\r\n![Size](https://img.shields.io/bundlephobia/minzip/@bw-ui/datepicker-multidate)\r\n\r\n[Live Demo](https://bw-ui.github.io/bw-datepicker) • [npm](https://www.npmjs.com/package/@bw-ui/datepicker)\r\n\r\n## Features\r\n\r\n- ✅ Toggle date selection (click to add/remove)\r\n- ✅ Maximum/minimum date limits\r\n- ✅ Sorted date output\r\n- ✅ Count badge display (header or footer)\r\n- ✅ Clear all button\r\n- ✅ Input synchronization\r\n- ✅ Auto-close on max dates\r\n- ✅ Configurable error timeout\r\n- ✅ Dark theme support\r\n- ✅ Works with Dual Calendar plugin\r\n- ✅ Full keyboard accessibility\r\n- ✅ TypeScript support\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @bw-ui/datepicker @bw-ui/datepicker-multidate\r\n```\r\n\r\n---\r\n\r\n## Quick Start\r\n\r\n### ES Modules\r\n\r\n```javascript\r\nimport { DatePickerCore } from '@bw-ui/datepicker';\r\nimport { MultiDatePlugin } from '@bw-ui/datepicker-multidate';\r\n\r\n// Import styles\r\nimport '@bw-ui/datepicker/css';\r\nimport '@bw-ui/datepicker-multidate/css';\r\n\r\n// Create picker and add plugin\r\nconst picker = new DatePickerCore('#date-input');\r\npicker.use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n});\r\n\r\n// Access plugin API\r\nconst multidate = picker.getPlugin('multidate');\r\nconsole.log(multidate.getDates());\r\n```\r\n\r\n### Script Tags (CDN)\r\n\r\n```html\r\n<link\r\n  rel=\"stylesheet\"\r\n  href=\"https://unpkg.com/@bw-ui/datepicker/dist/bw-datepicker.min.css\"\r\n/>\r\n<link\r\n  rel=\"stylesheet\"\r\n  href=\"https://unpkg.com/@bw-ui/datepicker-multidate/dist/bw-multidate.min.css\"\r\n/>\r\n\r\n<script src=\"https://unpkg.com/@bw-ui/datepicker\"></script>\r\n<script src=\"https://unpkg.com/@bw-ui/datepicker-multidate\"></script>\r\n\r\n<script>\r\n  // Create picker and add plugin\r\n  const picker = new BWDatePicker('#date-input');\r\n  picker.use(BWMultiDate.MultiDatePlugin, {\r\n    maxDates: 5,\r\n  });\r\n\r\n  // Access plugin API\r\n  const multidate = picker.getPlugin('multidate');\r\n  console.log(multidate.getDates());\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## Accessing the Plugin API\r\n\r\n**Important:** The `.use()` method returns the picker instance (for chaining), NOT the plugin instance. Use `.getPlugin('multidate')` to access the plugin API.\r\n\r\n```javascript\r\n// ❌ WRONG - This doesn't work\r\nconst multidate = picker.use(MultiDatePlugin, options);\r\nmultidate.getDates(); // ERROR: multidate is the picker, not the plugin!\r\n\r\n// ✅ CORRECT - Use getPlugin()\r\npicker.use(MultiDatePlugin, options);\r\nconst multidate = picker.getPlugin('multidate');\r\nmultidate.getDates(); // Works!\r\n```\r\n\r\n### Method 1: Separate Statements\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#date-input');\r\npicker.use(MultiDatePlugin, { maxDates: 5 });\r\n\r\n// Later, access the plugin\r\nconst multidate = picker.getPlugin('multidate');\r\nconst dates = multidate.getDates();\r\n```\r\n\r\n### Method 2: Chaining (still need getPlugin)\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#date-input').use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n});\r\n\r\n// .use() returns picker, so this works\r\nconst multidate = picker.getPlugin('multidate');\r\n```\r\n\r\n### Method 3: Use Callbacks (No getPlugin needed)\r\n\r\n```javascript\r\nnew DatePickerCore('#date-input').use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n  onChange: (allDates) => {\r\n    // Access dates directly in callback\r\n    console.log('Selected dates:', allDates);\r\n  },\r\n  onSelect: (date, allDates) => {\r\n    console.log('Just selected:', date);\r\n    console.log('All dates:', allDates);\r\n  },\r\n});\r\n```\r\n\r\n---\r\n\r\n## Options\r\n\r\nAll options are optional. Here are the defaults:\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  // Selection Limits\r\n  maxDates: null, // Maximum dates allowed (null = unlimited)\r\n  minDates: null, // Minimum dates for validation (null = no minimum)\r\n\r\n  // Display Format\r\n  format: 'YYYY-MM-DD', // Date format in input field\r\n  separator: ', ', // Separator between dates in input\r\n  maxDisplayDates: 3, // After this, show \"X dates selected\" instead\r\n\r\n  // Behavior\r\n  closeOnSelect: false, // Close picker after EVERY selection\r\n  closeOnMaxDates: true, // Close picker when maxDates is reached\r\n  sortDates: true, // Keep dates sorted chronologically\r\n\r\n  // UI Elements\r\n  showCountBadge: true, // Show \"X selected\" badge\r\n  badgePosition: 'footer', // Badge position: 'footer' | 'header'\r\n  showClearButton: true, // Show \"Clear All\" button\r\n  clearButtonText: 'Clear All', // Text for clear button\r\n  errorTimeout: 3000, // Error auto-hide timeout in ms (0 = never hide)\r\n\r\n  // Callbacks\r\n  onSelect: null, // Called when a date is selected\r\n  onDeselect: null, // Called when a date is deselected\r\n  onChange: null, // Called on any selection change\r\n});\r\n```\r\n\r\n### Options Reference Table\r\n\r\n| Option            | Type                   | Default        | Description                                                               |\r\n| ----------------- | ---------------------- | -------------- | ------------------------------------------------------------------------- |\r\n| `maxDates`        | `number \\| null`       | `null`         | Maximum selectable dates. `null` = unlimited                              |\r\n| `minDates`        | `number \\| null`       | `null`         | Minimum dates required for `.validate()`. `null` = no minimum             |\r\n| `format`          | `string`               | `'YYYY-MM-DD'` | Date format for input display. Supports: `YYYY`, `MM`, `DD`, `M`, `D`     |\r\n| `separator`       | `string`               | `', '`         | Separator between dates in input field                                    |\r\n| `maxDisplayDates` | `number`               | `3`            | When more dates selected, shows \"X dates selected\" instead of listing all |\r\n| `closeOnSelect`   | `boolean`              | `false`        | If `true`, closes picker after every date selection                       |\r\n| `closeOnMaxDates` | `boolean`              | `true`         | If `true`, auto-closes picker when `maxDates` is reached                  |\r\n| `sortDates`       | `boolean`              | `true`         | If `true`, keeps dates sorted chronologically                             |\r\n| `showCountBadge`  | `boolean`              | `true`         | Shows \"X selected\" badge                                                  |\r\n| `badgePosition`   | `'footer' \\| 'header'` | `'footer'`     | Where to show the count badge                                             |\r\n| `showClearButton` | `boolean`              | `true`         | Shows the \"Clear All\" button                                              |\r\n| `clearButtonText` | `string`               | `'Clear All'`  | Text displayed on clear button                                            |\r\n| `errorTimeout`    | `number`               | `3000`         | How long error messages display (ms). `0` = never auto-hide               |\r\n| `onSelect`        | `function`             | `null`         | Callback: `(date: Date, allDates: Date[]) => void`                        |\r\n| `onDeselect`      | `function`             | `null`         | Callback: `(date: Date, allDates: Date[]) => void`                        |\r\n| `onChange`        | `function`             | `null`         | Callback: `(allDates: Date[]) => void`                                    |\r\n\r\n---\r\n\r\n## Callbacks\r\n\r\nCallbacks let you react to selection changes without needing to call `getPlugin()`.\r\n\r\n### onSelect\r\n\r\nCalled when a date is **added** to selection.\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  onSelect: (date, allDates) => {\r\n    console.log('Selected date:', date); // The date just selected\r\n    console.log('All selected dates:', allDates); // Array of all selected dates\r\n    console.log('Total count:', allDates.length);\r\n  },\r\n});\r\n```\r\n\r\n### onDeselect\r\n\r\nCalled when a date is **removed** from selection (clicked again to toggle off).\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  onDeselect: (date, allDates) => {\r\n    console.log('Deselected date:', date); // The date just removed\r\n    console.log('Remaining dates:', allDates); // Array of remaining dates\r\n  },\r\n});\r\n```\r\n\r\n### onChange\r\n\r\nCalled on **any** selection change (select, deselect, clear, setDates).\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  onChange: (allDates) => {\r\n    console.log('All dates:', allDates);\r\n\r\n    // Update UI\r\n    document.getElementById('count').textContent = allDates.length;\r\n\r\n    // Enable/disable submit button\r\n    submitBtn.disabled = allDates.length === 0;\r\n  },\r\n});\r\n```\r\n\r\n### Using All Callbacks Together\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n  minDates: 2,\r\n\r\n  onSelect: (date, allDates) => {\r\n    console.log(`✅ Added: ${date.toDateString()}`);\r\n    console.log(`   Total: ${allDates.length}/5`);\r\n  },\r\n\r\n  onDeselect: (date, allDates) => {\r\n    console.log(`❌ Removed: ${date.toDateString()}`);\r\n    console.log(`   Remaining: ${allDates.length}`);\r\n  },\r\n\r\n  onChange: (allDates) => {\r\n    // Update your UI here\r\n    updateSelectedDatesDisplay(allDates);\r\n\r\n    // Validate for form submission\r\n    const isValid = allDates.length >= 2;\r\n    submitButton.disabled = !isValid;\r\n  },\r\n});\r\n```\r\n\r\n---\r\n\r\n## Plugin API Methods\r\n\r\nAccess via `picker.getPlugin('multidate')`:\r\n\r\n```javascript\r\nconst multidate = picker.getPlugin('multidate');\r\n```\r\n\r\n### getDates()\r\n\r\nGet all selected dates as an array.\r\n\r\n```javascript\r\nconst dates = multidate.getDates();\r\n// Returns: [Date, Date, Date, ...]\r\n// Returns empty array [] if nothing selected\r\n```\r\n\r\n### getCount()\r\n\r\nGet the number of selected dates.\r\n\r\n```javascript\r\nconst count = multidate.getCount();\r\n// Returns: 3\r\n```\r\n\r\n### isSelected(date)\r\n\r\nCheck if a specific date is selected.\r\n\r\n```javascript\r\nconst selected = multidate.isSelected(new Date(2025, 0, 15));\r\n// Returns: true or false\r\n```\r\n\r\n### addDate(date)\r\n\r\nAdd a date to selection (if not already selected).\r\n\r\n```javascript\r\nconst success = multidate.addDate(new Date(2025, 0, 20));\r\n// Returns: true if added, false if already selected or maxDates reached\r\n```\r\n\r\n### removeDate(date)\r\n\r\nRemove a date from selection.\r\n\r\n```javascript\r\nconst success = multidate.removeDate(new Date(2025, 0, 15));\r\n// Returns: true if removed, false if wasn't selected\r\n```\r\n\r\n### toggleDate(date)\r\n\r\nToggle a date (add if not selected, remove if selected).\r\n\r\n```javascript\r\nconst result = multidate.toggleDate(new Date(2025, 0, 25));\r\n// Returns: { added: Date | null, removed: Date | null }\r\n\r\nif (result.added) {\r\n  console.log('Date was added');\r\n}\r\nif (result.removed) {\r\n  console.log('Date was removed');\r\n}\r\n```\r\n\r\n### setDates(dates)\r\n\r\nSet dates directly (replaces all current selections).\r\n\r\n```javascript\r\nconst success = multidate.setDates([\r\n  new Date(2025, 0, 10),\r\n  new Date(2025, 0, 15),\r\n  new Date(2025, 0, 20),\r\n]);\r\n// Returns: true if set, false if exceeds maxDates\r\n```\r\n\r\n### clear()\r\n\r\nClear all selections.\r\n\r\n```javascript\r\nmultidate.clear();\r\n```\r\n\r\n### getFirst()\r\n\r\nGet the first (earliest) selected date.\r\n\r\n```javascript\r\nconst first = multidate.getFirst();\r\n// Returns: Date or null if nothing selected\r\n```\r\n\r\n### getLast()\r\n\r\nGet the last (latest) selected date.\r\n\r\n```javascript\r\nconst last = multidate.getLast();\r\n// Returns: Date or null if nothing selected\r\n```\r\n\r\n### validate()\r\n\r\nValidate selection against `minDates` requirement.\r\n\r\n```javascript\r\nconst { valid, error } = multidate.validate();\r\n\r\nif (!valid) {\r\n  console.log(error); // \"Minimum 2 dates required\"\r\n}\r\n```\r\n\r\n### destroy()\r\n\r\nClean up the plugin (called automatically when picker is destroyed).\r\n\r\n```javascript\r\nmultidate.destroy();\r\n```\r\n\r\n---\r\n\r\n## Events\r\n\r\nListen for events via the DatePicker's event bus:\r\n\r\n```javascript\r\npicker.on('multidate:select', (e) => {\r\n  console.log('Selected:', e.date);\r\n  console.log('All dates:', e.dates);\r\n  console.log('Count:', e.count);\r\n});\r\n\r\npicker.on('multidate:deselect', (e) => {\r\n  console.log('Deselected:', e.date);\r\n  console.log('Remaining:', e.dates);\r\n  console.log('Count:', e.count);\r\n});\r\n\r\npicker.on('multidate:change', (e) => {\r\n  console.log('Dates:', e.dates);\r\n  console.log('Count:', e.count);\r\n  console.log('Added:', e.added); // Date or null\r\n  console.log('Removed:', e.removed); // Date or null\r\n});\r\n\r\npicker.on('multidate:clear', () => {\r\n  console.log('All dates cleared');\r\n});\r\n\r\npicker.on('multidate:error', (e) => {\r\n  console.log('Error:', e.error);\r\n});\r\n```\r\n\r\n### Events vs Callbacks\r\n\r\nBoth work similarly. Use whichever fits your code style:\r\n\r\n```javascript\r\n// Callback approach (in options)\r\npicker.use(MultiDatePlugin, {\r\n  onChange: (dates) => console.log(dates),\r\n});\r\n\r\n// Event approach (after setup)\r\npicker.on('multidate:change', (e) => console.log(e.dates));\r\n```\r\n\r\n---\r\n\r\n## Examples\r\n\r\n### Basic Multi-Date Selection\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates');\r\npicker.use(MultiDatePlugin);\r\n\r\n// Get selected dates\r\nconst multidate = picker.getPlugin('multidate');\r\nconsole.log(multidate.getDates());\r\n```\r\n\r\n### Limited Selection (Max 5 Dates)\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates');\r\npicker.use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n  closeOnMaxDates: true, // Auto-close when 5 dates selected\r\n  onChange: (allDates) => {\r\n    console.log(`Selected ${allDates.length}/5 dates`);\r\n  },\r\n});\r\n```\r\n\r\n### Badge in Header\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  showCountBadge: true,\r\n  badgePosition: 'header', // Small badge in top-right of header\r\n});\r\n```\r\n\r\n### Form Validation with minDates\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates');\r\npicker.use(MultiDatePlugin, {\r\n  minDates: 3, // User must select at least 3 dates\r\n});\r\n\r\n// On form submit\r\ndocument.querySelector('form').addEventListener('submit', (e) => {\r\n  const multidate = picker.getPlugin('multidate');\r\n  const { valid, error } = multidate.validate();\r\n\r\n  if (!valid) {\r\n    e.preventDefault();\r\n    alert(error); // \"Minimum 3 dates required\"\r\n    return;\r\n  }\r\n\r\n  // Form is valid, proceed with submission\r\n  const selectedDates = multidate.getDates();\r\n  console.log('Submitting dates:', selectedDates);\r\n});\r\n```\r\n\r\n### Custom Display Format\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  format: 'DD/MM/YYYY', // European format\r\n  separator: ' | ', // Pipe separator\r\n  maxDisplayDates: 5, // Show up to 5 dates before switching to count\r\n});\r\n\r\n// Input will show: \"15/01/2025 | 20/01/2025 | 25/01/2025\"\r\n// Or if more than 5: \"6 dates selected\"\r\n```\r\n\r\n### Custom Error Timeout\r\n\r\n```javascript\r\npicker.use(MultiDatePlugin, {\r\n  maxDates: 5,\r\n  errorTimeout: 5000, // Error shows for 5 seconds\r\n  // errorTimeout: 0,    // Error never auto-hides\r\n});\r\n```\r\n\r\n### Pre-selected Dates\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates');\r\npicker.use(MultiDatePlugin);\r\n\r\n// Set initial dates after plugin is registered\r\nconst multidate = picker.getPlugin('multidate');\r\nmultidate.setDates([\r\n  new Date(2025, 0, 10),\r\n  new Date(2025, 0, 15),\r\n  new Date(2025, 0, 20),\r\n]);\r\n```\r\n\r\n### With Dual Calendar Plugin\r\n\r\n```javascript\r\nimport { DualCalendarPlugin } from '@bw-ui/datepicker-dual';\r\nimport { MultiDatePlugin } from '@bw-ui/datepicker-multidate';\r\n\r\nconst picker = new DatePickerCore('#dates');\r\npicker.use(DualCalendarPlugin); // Add dual calendar first\r\npicker.use(MultiDatePlugin, {\r\n  maxDates: 10,\r\n});\r\n```\r\n\r\n### Full Configuration Example\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates', {\r\n  mode: 'popup',\r\n});\r\n\r\npicker.use(MultiDatePlugin, {\r\n  // Limits\r\n  maxDates: 5,\r\n  minDates: 2,\r\n\r\n  // Display\r\n  format: 'MM.DD.YYYY',\r\n  separator: ' | ',\r\n  maxDisplayDates: 2,\r\n\r\n  // Behavior\r\n  closeOnSelect: false,\r\n  closeOnMaxDates: true,\r\n  sortDates: true,\r\n\r\n  // UI\r\n  showCountBadge: true,\r\n  badgePosition: 'footer',\r\n  showClearButton: true,\r\n  clearButtonText: 'Remove All',\r\n  errorTimeout: 3000,\r\n\r\n  // Callbacks\r\n  onSelect: (date, allDates) => {\r\n    console.log('Selected:', date.toDateString());\r\n    console.log('Total:', allDates.length);\r\n  },\r\n  onDeselect: (date, allDates) => {\r\n    console.log('Deselected:', date.toDateString());\r\n    console.log('Remaining:', allDates.length);\r\n  },\r\n  onChange: (allDates) => {\r\n    // Update UI\r\n    document.getElementById('selected-count').textContent = allDates.length;\r\n\r\n    // Validate\r\n    const multidate = picker.getPlugin('multidate');\r\n    const { valid } = multidate.validate();\r\n    document.getElementById('submit-btn').disabled = !valid;\r\n  },\r\n});\r\n\r\n// Access API later\r\nconst multidate = picker.getPlugin('multidate');\r\nconsole.log('Currently selected:', multidate.getDates());\r\nconsole.log('Count:', multidate.getCount());\r\nconsole.log('Is valid:', multidate.validate().valid);\r\n```\r\n\r\n---\r\n\r\n## Styling\r\n\r\n### CSS Classes\r\n\r\n| Class                         | Description                                     |\r\n| ----------------------------- | ----------------------------------------------- |\r\n| `.bw-datepicker--multidate`   | Added to picker container when plugin is active |\r\n| `.bw-multidate-selected`      | Applied to selected day cells                   |\r\n| `.bw-multidate-badge`         | The count badge element                         |\r\n| `.bw-multidate-badge--header` | Badge when positioned in header                 |\r\n| `.bw-multidate-footer`        | Footer container                                |\r\n| `.bw-multidate-clear`         | Clear button                                    |\r\n| `.bw-multidate-error`         | Error message                                   |\r\n\r\n### Custom Colors\r\n\r\n```css\r\n/* Custom selected date color */\r\n.bw-multidate-selected {\r\n  background-color: #10b981 !important; /* Emerald green */\r\n}\r\n\r\n/* Custom footer badge */\r\n.bw-multidate-badge {\r\n  background: #eff6ff;\r\n  color: #3b82f6;\r\n  border-color: #bfdbfe;\r\n}\r\n\r\n/* Custom header badge */\r\n.bw-multidate-badge--header {\r\n  background: #10b981;\r\n  color: #fff;\r\n}\r\n\r\n/* Custom clear button */\r\n.bw-multidate-clear {\r\n  background: #f3f4f6;\r\n  color: #374151;\r\n}\r\n\r\n.bw-multidate-clear:hover {\r\n  background: #fee2e2;\r\n  color: #dc2626;\r\n}\r\n```\r\n\r\n### Dark Theme\r\n\r\nDark theme styles are automatically applied when the picker has `.bw-datepicker--dark` class.\r\n\r\n```javascript\r\nconst picker = new DatePickerCore('#dates', {\r\n  theme: 'dark', // If your core supports this\r\n});\r\n```\r\n\r\nOr add the class manually:\r\n\r\n```javascript\r\npicker.getPickerElement().classList.add('bw-datepicker--dark');\r\n```\r\n\r\n---\r\n\r\n## TypeScript\r\n\r\nFull TypeScript support included:\r\n\r\n```typescript\r\nimport { DatePickerCore } from '@bw-ui/datepicker';\r\nimport {\r\n  MultiDatePlugin,\r\n  MultiDateInstance,\r\n  MultiDateOptions,\r\n} from '@bw-ui/datepicker-multidate';\r\n\r\n// Typed options\r\nconst options: MultiDateOptions = {\r\n  maxDates: 5,\r\n  minDates: 2,\r\n  badgePosition: 'header',\r\n  onChange: (dates: Date[]) => {\r\n    console.log(dates);\r\n  },\r\n};\r\n\r\n// Create picker\r\nconst picker = new DatePickerCore('#date');\r\npicker.use(MultiDatePlugin, options);\r\n\r\n// Typed plugin instance\r\nconst multidate = picker.getPlugin('multidate') as MultiDateInstance;\r\n\r\n// All methods are typed\r\nconst dates: Date[] = multidate.getDates();\r\nconst count: number = multidate.getCount();\r\nconst isSelected: boolean = multidate.isSelected(new Date());\r\nconst { valid, error }: { valid: boolean; error: string | null } =\r\n  multidate.validate();\r\n```\r\n\r\n---\r\n\r\n## Browser Support\r\n\r\n- Chrome 60+\r\n- Firefox 55+\r\n- Safari 12+\r\n- Edge 79+\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT © BW UI\r\n","readmeFilename":"README.md"}