Skip to content

Commit

Permalink
Merge pull request #6 from svelte-plugins/enable-dates
Browse files Browse the repository at this point in the history
✨ feat(enable-dates): add support for enabled dates only
  • Loading branch information
dysfunc committed Jan 15, 2024
2 parents 61d5cd5 + b3b603b commit 03186be
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 24 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Try it in the [Svelte REPL](https://svelte.dev/repl/cae0ce6e92634878b6e1a587146d
| endDateTime | The end date time string in 24 hour format. | `string` (default: `00:00`)
| defaultYear | The year you want to show as the default. | `number` (default: `2023`)
| align | The edge alignment of the datepicker. | `string` (default: `left`)
| enabledDates | An array of date strings to enable only. | `array` (default: [...])
| disabledDates | An array of date strings to disable. | `array` (default: [...])
| isRange | Changes the date picker into a range picker and allows start and end date selection. | `boolean` (default: `false`)
| isMultipane | If true, two calendar months will be shown side-by-side instead of one. | `boolean` (default: `false`)
Expand Down
2 changes: 2 additions & 0 deletions docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 24 additions & 1 deletion docs/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,23 @@
</td>
<td valign="top"><code>[]</code></td>
</tr>
<tr>
<td valign="top">enabledDates</td>
<td valign="top"><code>array</code></td>
<td>
Determines which dates will be enabled only.
<div><small>Accepted format <b>'MM/DD/YYYY'</b></small></div>

<br/>

<ul class="clean">
<li><code>['1/1/2023']</code> - Enables January 1st, 2023</li>
<li><code>['1/1/2023', '1/2/2023']</code> - Enables January 1st and 2nd, 2023</li>
<li><code>['1/1/2023:1/10/2023']</code> - Enables the range January 1st to 10th, 2023</li>
</ul>
</td>
<td valign="top"><code>[]</code></td>
</tr>
<tr>
<td valign="top">dowLabels</td>
<td valign="top"><code>array</code></td>
Expand Down Expand Up @@ -305,12 +322,18 @@
<SinglePicker enableFutureDates />
</div>

<h3>Disable Dates</h3>
<h3>Disabled Dates</h3>

<div class="example">
<SinglePicker enableFutureDates disabledDates={['11/25/23:11/29/23', '12/10/23', '12/14/23:12/31/23', '1/7/24:1/14/24']} />
</div>

<h3>Enabled Dates</h3>

<div class="example">
<SinglePicker enableFutureDates enabledDates={['1/14/24:1/25/24']} />
</div>

<h3>Theme</h3>

<div class="example">
Expand Down
3 changes: 2 additions & 1 deletion docs/src/examples/single/single.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
export let disabledDates = [];
export let enableFutureDates = null;
export let enablePastDates = null;
export let enabledDates = [];
let startDate = new Date();
let dateFormat = 'MM/dd/yy';
Expand Down Expand Up @@ -56,7 +57,7 @@
$: formattedStartDate = formatDate(startDate);
</script>
<DatePicker bind:isOpen bind:startDate${showTimePicker ? ' showTimePicker' : ''}${disabledDates.length ? ' disabledDates={' + JSON.stringify(disabledDates)+'}': ''}${enableFutureDates !== null && enableFutureDates ? ' enableFutureDates' : ''}${enablePastDates !== null && !enablePastDates ? ' enablePastDates={false}' : ''}>
<DatePicker bind:isOpen bind:startDate${showTimePicker ? ' showTimePicker' : ''}${enabledDates.length ? ' enabledDates={' + JSON.stringify(enabledDates)+'}': ''}${disabledDates.length ? ' disabledDates={' + JSON.stringify(disabledDates)+'}': ''}${enableFutureDates !== null && enableFutureDates ? ' enableFutureDates' : ''}${enablePastDates !== null && !enablePastDates ? ' enablePastDates={false}' : ''}>
<input type="text" placeholder="Select date" bind:value={formattedStartDate} on:click={toggleDatePicker} />
</DatePicker>
Expand Down
5 changes: 5 additions & 0 deletions src/datepicker.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export interface DatePickerProps {
*/
disabledDates: string[];

/**
* An array of enabled dates.
*/
enabledDates: string[];

/**
* Callback function to handle day click events.
*/
Expand Down
71 changes: 49 additions & 22 deletions src/datepicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
*/
export let disabledDates = [];
/**
* An array of enabled dates.
* @type {Date[]}
*/
export let enabledDates = [];
/**
* Callback function to handle day click events.
* @type {(event: Object) => void}
Expand Down Expand Up @@ -420,7 +426,7 @@
* @param {string[]} disabled - An array of disabled dates.
* @returns {string[]} - An array of dates within the specified range.
*/
const getDatesInRange = (startDate, endDate, disabled) => {
const getDatesInRange = (startDate, endDate) => {
const dateRangeStart = new Date(startDate);
const dateRangeEnd = new Date(endDate);
const datesInRange = [];
Expand All @@ -429,7 +435,11 @@
const formattedDate = `${
dateRangeStart.getMonth() + 1
}/${dateRangeStart.getDate()}/${dateRangeStart.getFullYear()}`;
if (!disabled.includes(formattedDate)) {
if (
(!enabled && !disabled) ||
(enabled.length && enabled.includes(formattedDate)) ||
(disabled.length && !disabled.includes(formattedDate))
) {
datesInRange.push(formattedDate);
}
}
Expand Down Expand Up @@ -470,7 +480,7 @@
...(isRange && {
endDate,
endDateTime,
rangeDates: getDatesInRange(startDate, endDate, disabled)
rangeDates: getDatesInRange(startDate, endDate)
})
};
Expand Down Expand Up @@ -564,7 +574,11 @@
*/
const isDisabled = (day, month, year) => {
const selectedDateTimestamp = createTimestamp(year, month, day);
return disabled.map((d) => new Date(d).getTime()).includes(selectedDateTimestamp);
return (
(!enabled && !disabled) ||
(enabled.length && !enabled.map((d) => new Date(d).getTime()).includes(selectedDateTimestamp)) ||
(disabled.length && disabled.map((d) => new Date(d).getTime()).includes(selectedDateTimestamp))
);
};
/**
Expand Down Expand Up @@ -752,11 +766,40 @@
return `${hours}:${minutes}`;
};
/**
* Returns an array of timestamps from an array of date strings.
* @param {string[]} collection - An array of date strings.
* @returns {number[]} - An array of timestamps.
*/
const getDatesFromArray = (collection) => {
return collection.reduce((acc, date) => {
let newDates = [];
if (date instanceof Date) {
newDates = [date.getTime()];
} else if (typeof date === 'string' && date.includes(':')) {
const [rangeStart, rangeEnd] = date.split(':');
let dateRangeStart = new Date(rangeStart).getTime();
let dateRangeEnd = new Date(rangeEnd).getTime();
for (; dateRangeStart <= dateRangeEnd; dateRangeStart += MILLISECONDS_IN_DAY) {
newDates = [...newDates, dateRangeStart];
}
} else {
newDates = [new Date(date).getTime()];
}
return [...acc, ...newDates];
}, []);
};
$: startDate = startDate ? getTimestamp(startDate) : null;
$: endDate = endDate ? getTimestamp(endDate) : null;
$: if (startDate || endDate) {
updateCalendars();
}
$: todayMonth = today && today.getMonth();
$: todayDay = today && today.getDate();
$: todayYear = today && today.getFullYear();
Expand All @@ -768,24 +811,8 @@
$: endDateCalendar = calendarize(new Date(endDateYear, endDateMonth), startOfWeek);
$: !isRange && (endDate = null);
$: theme !== null && document.documentElement.setAttribute('data-picker-theme', theme);
$: disabled = disabledDates.reduce((acc, date) => {
let newDates = [];
if (date instanceof Date) {
newDates = [date.getTime()];
} else if (typeof date === 'string' && date.includes(':')) {
const [rangeStart, rangeEnd] = date.split(':');
let dateRangeStart = new Date(rangeStart).getTime();
let dateRangeEnd = new Date(rangeEnd).getTime();
for (; dateRangeStart <= dateRangeEnd; dateRangeStart += MILLISECONDS_IN_DAY) {
newDates = [...newDates, dateRangeStart];
}
} else {
newDates = [new Date(date).getTime()];
}
return [...acc, ...newDates];
}, []);
$: disabled = getDatesFromArray(disabledDates);
$: enabled = getDatesFromArray(enabledDates);
$: if (!startDate && !endDate) {
startDateYear = Number(defaultYear);
Expand Down
1 change: 1 addition & 0 deletions src/datepicker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const config = {
align: 'left',
theme: '',
disabledDates: [],
enabledDates: [],
onDayClick: () => {},
showYearControls: true,
showPresets: false,
Expand Down

0 comments on commit 03186be

Please sign in to comment.