UNPKG

sober

Version:

Sober is a library of UI components designed with reference to Material You.

149 lines (148 loc) 5.26 kB
import { useElement, useProps } from './core/element.js'; import { dateFormat } from './core/utils/dateFormat.js'; const name = 's-date-picker'; const props = useProps({ $value: '', $min: '', $max: '', $label: '', $positiveText: '确定', $negativeText: '取消', $format: 'yyyy-MM-dd', $locale: '' }); const style = /*css*/ ` :host{ display: inline-block; vertical-align: middle; font-size: .875rem; --date-picker-border-radius: 4px; --date-picker-border-color: var(--s-color-outline, ${"#70787D" /* Theme.colorOutline */}); --date-picker-border-width: 1px; --date-picker-padding: 16px; --date-picker-height: 48px; } s-dialog{ display: block; } .field{ --field-border-radius: var(--date-picker-border-radius); --field-border-color: var(--date-picker-border-color); --field-border-width: var(--date-picker-border-width); --field-padding: var(--date-picker-padding); height: var(--date-picker-height); position: relative; cursor: pointer; } .view{ width: 100%; padding-top: 0; padding-bottom: 0; padding: 0 var(--date-picker-padding); } svg{ width: 24px; height: 24px; padding: 2px; box-sizing: border-box; flex-shrink: 0; margin-left: min(0px, calc((var(--date-picker-padding) * -1) + 12px)); margin-right: max(0px, calc(var(--date-picker-padding) - 4px)); fill: var(--s-color-on-surface-variant, ${"#40484C" /* Theme.colorOnSurfaceVariant */}); } .ripple{ border-radius: var(--date-picker-border-radius); } .date{ border: none; width: 360px; border-radius: 0; } .positive, .negative{ border-radius: 20px; } `; const template = /*html*/ ` <s-dialog part="dialog"> <slot name="trigger" slot="trigger"> <s-field class="field" fixed="false" part="field"> <div class="label" part="label" slot="label"></div> <div class="view"></div> <svg viewBox="0 -960 960 960" slot="end"> <path d="M320-400q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm160 0q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm160 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Z"></path> </svg> <s-ripple slot="custom" class="ripple" attached="true"></s-ripple> </s-field> </slot> <s-date class="date" part="date"></s-date> <s-ripple class="negative" slot="action" part="negative">${props.negativeText}</s-ripple> <s-ripple class="positive" slot="action" part="positive">${props.positiveText}</s-ripple> </s-dialog> `; export class DatePicker extends useElement({ style, template, props, setup(shadowRoot) { const dialog = shadowRoot.querySelector('s-dialog'); const dateElement = shadowRoot.querySelector('s-date'); const negative = shadowRoot.querySelector('.negative'); const positive = shadowRoot.querySelector('.positive'); const field = shadowRoot.querySelector('s-field'); const label = shadowRoot.querySelector('.label'); const view = shadowRoot.querySelector('.view'); const state = { date: '' }; dialog.addEventListener('show', () => { field.fixed = true; field.focused = true; if (!state.date) { view.textContent = this.label; view.style.opacity = '0'; } }); dialog.onclose = () => { field.focused = false; if (!state.date) { field.fixed = false; } }; positive.onclick = () => { this.value = dateElement.value; view.style.removeProperty('opacity'); this.dispatchEvent(new Event('change')); }; return { value: { get: () => state.date, set: (value) => { state.date = value; if (value === '') { dateElement.value = dateFormat(new Date()); field.fixed = false; view.textContent = ''; return; } field.fixed = true; view.textContent = dateFormat(value, this.format); dateElement.value = value; } }, locale: { get: () => dateElement.locale, set: (value) => dateElement.locale = value }, min: { get: () => dateElement.min, set: (value) => dateElement.min = value }, max: { get: () => dateElement.max, set: (value) => dateElement.max = value }, label: (value) => label.textContent = value, positiveText: (value) => positive.textContent = value, negativeText: (value) => negative.textContent = value, }; } }) { } DatePicker.define(name);