Skip to content
Open
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
17 changes: 17 additions & 0 deletions aform/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ Vue component exported from @stonecrop/aform.
import { ADatePicker } from '@stonecrop/aform'
```

### ADateSelection

Vue component exported from @stonecrop/aform.

```typescript
import { ADateSelection } from '@stonecrop/aform'
```

### ADateTime

Vue component exported from @stonecrop/aform.

```typescript
import { ADateTime } from '@stonecrop/aform'
```

### ADropdown

Vue component exported from @stonecrop/aform.
Expand Down Expand Up @@ -136,6 +152,7 @@ Defined props for AForm components
export type ComponentProps = {
schema?: SchemaTypes;
label?: string;
selectRange?: boolean;
mask?: string;
required?: boolean;
mode?: FormMode;
Expand Down
67 changes: 51 additions & 16 deletions aform/src/components/form/ADate.vue
Original file line number Diff line number Diff line change
@@ -1,50 +1,81 @@
<template>
<div>
<template v-if="mode === 'display'">
<span class="aform_display-value">{{ inputDate ? new Date(inputDate).toLocaleDateString() : '' }}</span>
<span class="aform_display-value">{{ modelValue ? new Date(inputDate).toLocaleDateString() : '' }}</span>
<label>{{ label }}</label>
</template>
<template v-else>
<input
:id="uuid"
ref="date"
v-model="inputDate"
class="adate-input"
:value="inputDate"
type="date"
:disabled="mode === 'read'"
:required="required"
@click="showPicker" />
@click.prevent="
() => {
showPicker = !showPicker
}
" />
<label :for="uuid">{{ label }}</label>
<p v-show="validation.errorMessage" v-html="validation.errorMessage"></p>
<ADateSelection
v-if="showPicker"
ref="picker"
class="picker"
:select-range="false"
:show-time="false"
@get-date="handleDate" />
</template>
</div>
</template>

<script setup lang="ts">
import { useTemplateRef } from 'vue'
import { useTemplateRef, ref, computed, watch } from 'vue'
import { onClickOutside } from '@vueuse/core'

import { ComponentProps } from '../../types'
import ADateSelection from './ADateSelection.vue'
import type { ComponentProps } from '../../types'

const { label = 'Date', required, mode, uuid, validation = { errorMessage: '&nbsp;' } } = defineProps<ComponentProps>()

const inputDate = defineModel<string | number | Date>({
// format the date to be compatible with the native input datepicker
set: value => new Date(value).toISOString().split('T')[0],
const modelValue = defineModel<string | Date>()

const currentDate = ref(modelValue.value ? new Date(modelValue.value) : new Date())
const inputDate = computed({
get: () => currentDate.value.toISOString().split('T')[0],
set: (value: string) => {
currentDate.value = new Date(value)
modelValue.value = value
},
})
const dateRef = useTemplateRef<HTMLInputElement>('date')

const showPicker = () => {
if (dateRef.value) {
if ('showPicker' in HTMLInputElement.prototype) {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker
// TODO: re-check browser support and compatibility; figure out alternative ways
// to spawn the native datepicker and eventually replace with ADatepicker
dateRef.value.showPicker()

const pickerRef = useTemplateRef('picker')
const showPicker = ref(false)

onClickOutside(pickerRef, () => (showPicker.value = false))

watch(
() => modelValue.value,
newValue => {
if (newValue) {
currentDate.value = new Date(newValue)
}
}
)

const handleDate = (data: { selected: Date }) => {
currentDate.value = data.selected
modelValue.value = inputDate.value
}
</script>

<style scoped>
.adate-input {
overflow: auto;
}
div {
min-width: 40ch;
width: 100%;
Expand Down Expand Up @@ -102,4 +133,8 @@ input:focus {
input:focus + label {
color: var(--sc-input-active-label-color);
}
.picker {
position: absolute;
top: 50px;
}
</style>
Loading
Loading