mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 10:21:05 +00:00
parent
45da25ce1b
commit
6ca56d67a6
23 changed files with 602 additions and 21 deletions
145
src/components/DatePicker/DatePicker.svelte
Normal file
145
src/components/DatePicker/DatePicker.svelte
Normal file
|
@ -0,0 +1,145 @@
|
|||
<script>
|
||||
let className = undefined;
|
||||
export { className as class };
|
||||
export let id = Math.random();
|
||||
export let short = false;
|
||||
export let datePickerType = 'simple';
|
||||
export let dateFormat = 'm/d/Y';
|
||||
export let locale = 'en';
|
||||
export let value = '';
|
||||
export let appendTo = document.body;
|
||||
export let minDate = null;
|
||||
export let maxDate = null;
|
||||
export let light = false;
|
||||
export let style = undefined;
|
||||
|
||||
import { createEventDispatcher, setContext, afterUpdate, onDestroy } from 'svelte';
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import { createCalendar } from './flatpickr';
|
||||
import { cx } from '../../lib';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let inputs = writable([]);
|
||||
let inputIds = derived(inputs, _ => _.map(({ id }) => id));
|
||||
let inputsById = derived(inputs, _ => _.reduce((a, c) => ({ ...a, [c.id]: c }), {}));
|
||||
let labelTextEmpty = derived(inputs, _ => _.filter(({ labelText }) => !!labelText).length === 0);
|
||||
let inputValue = writable(value);
|
||||
let mode = writable(datePickerType);
|
||||
let range = derived(mode, _ => _ === 'range');
|
||||
let hasCalendar = derived(mode, _ => _ === 'single' || _ === 'range');
|
||||
|
||||
let calendar = undefined;
|
||||
let datePickerRef = undefined;
|
||||
let inputRef = undefined;
|
||||
let inputRefTo = undefined;
|
||||
|
||||
setContext('DatePicker', {
|
||||
range,
|
||||
inputValue,
|
||||
hasCalendar,
|
||||
add: data => {
|
||||
inputs.update(_ => [..._, data]);
|
||||
},
|
||||
declareRef: ({ id, ref }) => {
|
||||
if ($inputIds.indexOf(id) === 0) {
|
||||
inputRef = ref;
|
||||
} else {
|
||||
inputRefTo = ref;
|
||||
}
|
||||
},
|
||||
updateValue: ({ id, type, value }) => {
|
||||
if ((!calendar && type === 'input') || type === 'change') {
|
||||
inputValue.set(value);
|
||||
}
|
||||
|
||||
if (!calendar && type === 'change') {
|
||||
dispatch('change', value);
|
||||
}
|
||||
},
|
||||
blurInput: relatedTarget => {
|
||||
if (calendar && !calendar.calendarContainer.contains(relatedTarget)) {
|
||||
calendar.close();
|
||||
}
|
||||
},
|
||||
openCalendar: () => {
|
||||
calendar.open();
|
||||
},
|
||||
focusCalendar: () => {
|
||||
(
|
||||
calendar.selectedDateElem ||
|
||||
calendar.todayDateElem ||
|
||||
calendar.calendarContainer.querySelector('.flatpickr-day[tabindex]') ||
|
||||
calendar.calendarContainer
|
||||
).focus();
|
||||
}
|
||||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
if ($hasCalendar && !calendar) {
|
||||
calendar = createCalendar({
|
||||
options: {
|
||||
appendTo,
|
||||
dateFormat,
|
||||
defaultDate: $inputValue,
|
||||
locale,
|
||||
maxDate,
|
||||
minDate,
|
||||
mode: $mode
|
||||
},
|
||||
base: inputRef,
|
||||
input: inputRefTo,
|
||||
dispatch: event => {
|
||||
const detail = { selectedDates: calendar.selectedDates };
|
||||
|
||||
if ($range) {
|
||||
detail.dateStr = {
|
||||
from: inputRef.value,
|
||||
to: inputRefTo.value
|
||||
};
|
||||
} else {
|
||||
detail.dateStr = inputRef.value;
|
||||
}
|
||||
|
||||
return dispatch(event, detail);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (calendar && !$range) {
|
||||
calendar.setDate($inputValue);
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (calendar) {
|
||||
calendar.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// $: hasCalendar.set($mode === 'single' || $mode === 'range');
|
||||
$: inputValue.set(value);
|
||||
$: value = $inputValue;
|
||||
</script>
|
||||
|
||||
<svelte:body
|
||||
on:click={({ target }) => {
|
||||
if (!calendar || !calendar.isOpen) {
|
||||
return;
|
||||
}
|
||||
if (datePickerRef && datePickerRef.contains(target)) {
|
||||
return;
|
||||
}
|
||||
if (!calendar.calendarContainer.contains(target)) {
|
||||
calendar.close();
|
||||
}
|
||||
}} />
|
||||
|
||||
<div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}>
|
||||
<div
|
||||
bind:this={datePickerRef}
|
||||
class={cx('--date-picker', short && '--date-picker--short', light && '--date-picker--light', datePickerType && `--date-picker--${datePickerType}`, datePickerType === 'range' && $labelTextEmpty && '--date-picker--nolabel')}
|
||||
{id}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue