Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat(enable-dates): add support for enabled dates only #6

Merged
merged 1 commit into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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