1
0
Fork 0
mirror of synced 2024-06-14 00:14:39 +12:00
budibase/packages/standard-components/src/forms/DateTimeField.svelte

142 lines
3.7 KiB
Svelte
Raw Normal View History

2021-01-29 07:53:40 +13:00
<script>
import Flatpickr from "svelte-flatpickr"
import Field from "./Field.svelte"
2021-01-29 07:53:40 +13:00
import "flatpickr/dist/flatpickr.css"
import "@spectrum-css/inputgroup/dist/index-vars.css"
import { generateID } from "../helpers"
2021-01-29 07:53:40 +13:00
export let field
export let label
export let placeholder
export let enableTime
2021-01-29 07:53:40 +13:00
let fieldState
let fieldApi
let open = false
let flatpickr
$: flatpickrId = `${$fieldState?.id}-${generateID()}-wrapper`
2021-01-29 08:41:46 +13:00
$: flatpickrOptions = {
element: `#${flatpickrId}`,
enableTime: enableTime || false,
2021-01-29 08:41:46 +13:00
altInput: true,
altFormat: enableTime ? "F j Y, H:i" : "F j, Y",
2021-01-29 08:41:46 +13:00
}
2021-01-29 07:53:40 +13:00
const handleChange = event => {
const [dates] = event.detail
fieldApi.setValue(dates[0])
}
const clearDateOnBackspace = event => {
if (["Backspace", "Clear", "Delete"].includes(event.key)) {
fieldApi.setValue(null)
flatpickr.close()
}
}
const onOpen = () => {
open = true
document.addEventListener("keyup", clearDateOnBackspace)
}
const onClose = () => {
open = false
document.removeEventListener("keyup", clearDateOnBackspace)
// Manually blur all input fields since flatpickr creates a second
// duplicate input field.
// We need to blur both because the focus styling does not get properly
// applied.
const els = document.querySelectorAll(`#${flatpickrId} input`)
els.forEach(el => el.blur())
2021-01-29 07:53:40 +13:00
}
</script>
<Field {label} {field} type="datetime" bind:fieldState bind:fieldApi>
2021-01-29 07:53:40 +13:00
{#if fieldState}
<Flatpickr
bind:flatpickr
value={$fieldState.value}
on:open={onOpen}
on:close={onClose}
2021-01-29 08:41:46 +13:00
options={flatpickrOptions}
2021-01-29 07:53:40 +13:00
on:change={handleChange}
element={`#${flatpickrId}`}>
2021-01-29 07:53:40 +13:00
<div
id={flatpickrId}
2021-01-29 07:53:40 +13:00
aria-disabled="false"
aria-invalid={!$fieldState.valid}
class:is-invalid={!$fieldState.valid}
2021-01-29 07:53:40 +13:00
class="flatpickr spectrum-InputGroup spectrum-Datepicker"
class:is-focused={open}
2021-01-29 07:53:40 +13:00
aria-readonly="false"
aria-required="false"
aria-haspopup="true">
<div
on:click={flatpickr?.open}
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-invalid={!$fieldState.valid}>
{#if !$fieldState.valid}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true">
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
2021-01-29 07:53:40 +13:00
<input
data-input
type="text"
class="spectrum-Textfield-input spectrum-InputGroup-input"
aria-invalid={!$fieldState.valid}
2021-01-29 07:53:40 +13:00
{placeholder}
id={$fieldState.fieldId}
2021-01-29 08:41:46 +13:00
value={$fieldState.value} />
2021-01-29 07:53:40 +13:00
</div>
<button
type="button"
class="spectrum-Picker spectrum-InputGroup-button"
tabindex="-1"
class:is-invalid={!$fieldState.valid}
on:click={flatpickr?.open}>
2021-01-29 07:53:40 +13:00
<svg
class="spectrum-Icon spectrum-Icon--sizeM"
focusable="false"
aria-hidden="true"
aria-label="Calendar">
<use xlink:href="#spectrum-icon-18-Calendar" />
</svg>
</button>
</div>
</Flatpickr>
{#if open}
<div class="overlay" on:mousedown|self={flatpickr?.close} />
{/if}
2021-01-29 07:53:40 +13:00
{/if}
</Field>
2021-01-29 07:53:40 +13:00
<style>
.spectrum-Textfield-input {
pointer-events: none;
}
.spectrum-Textfield:hover {
cursor: pointer;
}
2021-01-29 07:53:40 +13:00
.flatpickr {
width: 100%;
overflow: hidden;
2021-01-29 07:53:40 +13:00
}
.flatpickr .spectrum-Textfield {
width: 100%;
2021-01-29 07:53:40 +13:00
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 999;
}
2021-01-29 07:53:40 +13:00
</style>