web-time-picker
Version:
1,118 lines (1,023 loc) • 30 kB
JavaScript
(function () {
'use strict';
class TimePickerHour extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
this.root.innerHTML = `
<style>
:host {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
position: absolute;
top: 50%;
left: 50%;
width: 36px;
height: 36px;
margin: -18px;
cursor: pointer;
will-change: transform;
border-radius: 50%;
z-index: 0;
user-select: none;
}
.bubble {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
width: 100%;
height: 100%;
border-radius: 50%;
z-index: 0;
opacity: 0;
transition: transform ease-out 64ms, opacity ease-out 16ms;
}
:host(:hover) .bubble {
opacity: 1;
background: var(--primary-color, #00bcd4);
transform: translate(-50%, -50%) scale(1);
transition: transform ease-in 100ms, opacity ease-in 16ms;
}
.container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
z-index: 1;
}
</style>
<slot></slot>
<div class="bubble"></div>
<div class="container"></div>
`;
this._onClick= this._onClick.bind(this);
this._renderHour = this._renderHour.bind(this);
}
set digitValue(value) {
if (value) {
this.setAttribute('digit-value', value);
} else {
this.removeAttribute('digit-value');
}
}
set timeFormat(value) {
this._timeFormat = value;
this._renderHour();
}
get timeFormat() {
return this._timeFormat || 'am';
}
get _container() {
return this.root.querySelector('.container');
}
set hour(value) {
this._hour = value;
this._renderHour();
}
set plateSize(value) {
this._plateSize = value;
}
get hour() {
return this._hour;
}
get plateSize() {
return this._plateSize || 200;
}
connectedCallback() {
this.addEventListener('click', this._onClick);
this.addEventListener('mouseover', this._mouseOver);
}
transform(deg) {
let x = this.plateSize / 2;
this.style.transform = `rotate(${deg}deg) translate(${x}px) rotate(-${deg}deg)`;
}
_renderHour() {
let hour = this.hour;
if (this.timeFormat !== 'am') {
hour += 12;
}
this._container.innerHTML = hour;
this.digitValue = hour;
}
_onClick(event) {
event.preventDefault();
event.stopPropagation();
this.dispatchEvent(new CustomEvent('hour-select', {
detail: this.hour
}));
}
_mouseOver(event) {
this.dispatchEvent(new CustomEvent('hour-indicating', {
detail: {
target: this,
hour: Number(this.hour)
}
}));
}
}
customElements.define('time-picker-hour', TimePickerHour);
class TimePickerPlate extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
position: relative;
width: var(--time-picker-plate-size, 200px);
height: var(--time-picker-plate-size, 200px);
padding: 0;
border-radius: 50%;
list-style: none;
font-size: 14px;
line-height: 36px;
padding: var(--time-picker-plate-padding, 160px 0 20px 0);
margin: 0 auto;
}
:host::before {
content: "";
position: absolute;
top: 0;
left: -20px;
width: 240px;
height: 240px;
background: var(--clock-background);
border-radius: 50%;
}
.center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--primary-color, #00bcd4);
}
.indicator {
position: absolute;
top: 80px;
left: 50%;
transform: translate(-50%, -50%);
opacity: 0;
height: 86px;
width: 2px;
background: var(--primary-color, #00bcd4);
}
.indicator.show {
opacity: 1;
}
</style>
<div class="indicator"></div>
<div class="center"></div>
`;
}
set size(value) {
this._size = value;
this.style.setPropertyValue('--time-picker-plate-size', `${value}px`);
}
set timeFormat(value) {
this._timeFormat = value;
this._notifyTimePickerHourElements(value);
}
get size() {
return this._size || 200;
}
/**
* Returns current time format, options are 'am', 'pm' or 24 hours
* @return {String|Number}
*/
get timeFormat() {
return this._timeFormat || 'am';
}
get _indicator() {
return this.root.querySelector('.indicator');
}
get renderTwentyFourHoursNeeded() {
if (this.timeFormat !== 'am' || this.timeFormat !== 'pm') {
return true;
}
return false;
}
_notifyTimePickerHourElements(timeFormat) {
const hourElements = document.querySelectorAll('time-picker-hour');
for (let hourElement of hourElements) {
hourElement.timeFormat = timeFormat;
}
}
}
customElements.define('time-picker-plate', TimePickerPlate);
class TimePickerHourPlate extends TimePickerPlate {
constructor() {
super();
this._onHourSelect = this._onHourSelect.bind(this);
this._onHourIndicating = this._onHourIndicating.bind(this);
this._onHourMouseOut = this._onHourMouseOut.bind(this);
}
connectedCallback() {
super.connectedCallback();
this._setupHours();
}
get hourSet() {
return [
[3, 0, 90],
[4, 30, 120],
[5, 60, 150],
[6, 90, 180],
[7, 120, 210],
[8, 150, 240],
[9, 180, 270],
[10, 210, 300],
[11, 240, 330],
[12, 270, 0],
[1, 300, 30],
[2, 330, 60]
];
}
_setupHours() {
let twentyFourHours = this.renderTwentyFourHoursNeeded;
let hours = this.hourSet;
// Promise.all([hourTasks])
for (let hour of hours) {
let timePickerHour = new TimePickerHour();
timePickerHour.transform(hour[1]);
timePickerHour.hour = hour[0];
timePickerHour.plateSize = this.size;
timePickerHour.addEventListener('hour-select',
this._onHourSelect
);
timePickerHour.addEventListener('hour-indicating', this._onHourIndicating);
timePickerHour.addEventListener('mouseout', this._onHourMouseOut);
requestAnimationFrame(() => {
this.root.appendChild(timePickerHour);
});
if (twentyFourHours) {
hour[0] = (hour[0] + 12);
let europeanTimePickerHour = new TimePickerHour();
europeanTimePickerHour.plateSize = (this.size - 72);
europeanTimePickerHour.transform(hour[1]);
europeanTimePickerHour.hour = hour[0];
europeanTimePickerHour.addEventListener('hour-select',
this._onHourSelect);
europeanTimePickerHour.addEventListener('hour-indicating',
this._onHourIndicating);
europeanTimePickerHour.addEventListener('mouseout', this._onHourMouseOut);
requestAnimationFrame(() => {
this.root.appendChild(europeanTimePickerHour);
});
}
}
}
_querySelectDigit(number) {
let query = `time-picker-hour[digit-value="${number}"]`;
return this.root.querySelector(query);
}
_onHourIndicating(event) {
let hour = event.detail.hour;
let height = 86;
let top = 80;
let digitOverIndicator;
if (hour > 12) {
hour -= 12;
height -= 36;
top += 18;
} else {
// set the current digit the hide
digitOverIndicator = hour;
digitOverIndicator += 12;
}
this._hideDigitUnderIndicator(digitOverIndicator);
this._rerenderIndicator(hour, height, top);
this._indicator.classList.add('show');
}
_hideDigitUnderIndicator(digit) {
if (digit) {
digit = this._querySelectDigit(digit);
digit.style.opacity = 0;
this._lastUnderIndicator = digit;
}
}
_rerenderIndicator(_hour, height, top) {
for (let hour of this.hourSet) {
let marginTop = 0;
let marginLeft = 0;
if (hour[0] === _hour) {
if (hour[0] >= 1 && hour[0] < 3) {
marginLeft = '-1px';
} else if (hour[0] === 3) {
marginTop = '-2px';
} else if (hour[0] > 3 && hour[0] < 6) {
marginTop = '-2px';
marginLeft = '-2px';
} else if (hour[0] === 6) {
marginLeft = '-2px';
} else if (hour[0] > 6 && hour[0] < 9) {
marginTop = `-3px`;
marginLeft = '-3px';
} else if (hour[0] === 9) {
marginTop = `-4px`;
} else if (hour[0] > 9 && hour[0] < 12) {
marginTop = `-3px`;
}
requestAnimationFrame(() => {
this._indicator.style.marginLeft = marginLeft;
this._indicator.style.marginTop = marginTop;
this._indicator.style.height = `${height}px`;
this._indicator.style.top = `${top}px`;
this._indicator.style.transform = `rotate(${hour[2]}deg) translate(-50%, -50%)`;
});
}
}
}
_onHourMouseOut() {
this._indicator.classList.remove('show');
if (this._lastUnderIndicator) {
this._lastUnderIndicator.style.opacity = 1;
this._lastUnderIndicator = undefined;
}
}
_onHourSelect(event) {
this.dispatchEvent(new CustomEvent('update-hour', {detail: event.detail}));
}
}
customElements.define('time-picker-hour-plate', TimePickerHourPlate);
class TimePickerMinutesPlate extends TimePickerPlate {
constructor() {
super();
this._onHourSelect = this._onHourSelect.bind(this);
this._onHourIndicating = this._onHourIndicating.bind(this);
this._onHourMouseOut = this._onHourMouseOut.bind(this);
}
connectedCallback() {
super.connectedCallback();
this._setupMinutes();
}
set size(value) {
super.size = value;
this._size = value;
this.style.setPropertyValue('--time-picker-plate-size', `${value}px`);
}
get size() {
return this._size || 200;
}
get _indicator() {
return this.root.querySelector('.indicator');
}
get minutesSet() {
return [
[15, 0, 90],
[16, 6, 96],
[17, 12, 102],
[18, 18, 108],
[19, 24, 114],
[20, 30, 120],
[21, 36, 126],
[22, 42, 132],
[23, 48, 138],
[24, 54, 144],
[25, 60, 150],
[26, 66, 156],
[27, 72, 162],
[28, 78, 168],
[29, 84, 174],
[30, 90, 180],
[31, 96, 186],
[32, 102, 192],
[33, 108, 198],
[34, 114, 204],
[35, 120, 210],
[36, 126, 216],
[37, 132, 222],
[38, 138, 228],
[39, 144, 234],
[40, 150, 240],
[41, 156, 246],
[42, 162, 252],
[43, 168, 258],
[44, 174, 264],
[45, 180, 270],
[46, 186, 276],
[47, 192, 282],
[48, 198, 288],
[49, 204, 294],
[50, 210, 300],
[51, 216, 306],
[52, 222, 312],
[53, 228, 318],
[54, 234, 324],
[55, 240, 330],
[56, 246, 336],
[57, 252, 342],
[58, 258, 348],
[59, 264, 354],
[60, 270, 0],
[1, 276, 6],
[2, 282, 12],
[3, 288, 18],
[4, 294, 24],
[5, 300, 30],
[6, 306, 36],
[7, 312, 42],
[8, 318, 48],
[9, 324, 54],
[10, 330, 60],
[11, 336, 66],
[12, 342, 72],
[13, 348, 78],
[14, 354, 84]
];
}
_setupMinutes() {
let hours = this.minutesSet;
// Promise.all([hourTasks])
for (let hour of hours) {
let timePickerHour = new TimePickerHour();
timePickerHour.transform(hour[1]);
timePickerHour.hour = hour[0];
timePickerHour.plateSize = this.size;
if (hour[0] !== 5 && hour[0] !== 10 && hour[0] !== 15 &&
hour[0] !== 20 && hour[0] !== 25 && hour[0] !== 30 &&
hour[0] !== 35 && hour[0] !== 40 && hour[0] !== 45 &&
hour[0] !== 50 && hour[0] !== 55 && hour[0] !== 60) {
timePickerHour.root.querySelector('.container').innerHTML = '';
timePickerHour.style.width = '18px';
timePickerHour.style.height = '18px';
timePickerHour.style.margin = '-9px';
} else {
timePickerHour.hour = hour[0];
}
timePickerHour.addEventListener('hour-select',
this._onHourSelect
);
timePickerHour.addEventListener('hour-indicating', this._onHourIndicating);
timePickerHour.addEventListener('mouseout', this._onHourMouseOut);
requestAnimationFrame(() => {
this.root.appendChild(timePickerHour);
});
}
}
_onHourIndicating(event) {
let hour = event.detail.hour;
this._rerenderIndicator(hour);
this._indicator.classList.add('show');
}
_rerenderIndicator(_minute) {
for (let minute of this.minutesSet) {
let marginTop = 0;
let marginLeft = 0;
if (minute[0] === _minute) {
if (minute[0] >= 5 && minute[0] < 15) {
marginLeft = '-1px';
} else if (minute[0] === 15) {
marginTop = '-2px';
} else if (minute[0] > 15 && minute[0] < 30) {
marginTop = '-2px';
marginLeft = '-2px';
} else if (minute[0] === 30) {
marginLeft = '-2px';
} else if (minute[0] > 30 && minute[0] < 45) {
marginTop = `-3px`;
marginLeft = '-3px';
} else if (minute[0] === 45) {
marginTop = `-4px`;
} else if (minute[0] > 45 && minute[0] < 60) {
marginTop = `-3px`;
}
requestAnimationFrame(() => {
this._indicator.style.marginLeft = marginLeft;
this._indicator.style.marginTop = marginTop;
this._indicator.style.transform = `rotate(${minute[2]}deg) translate(-50%, -50%)`;
});
}
}
}
_onHourMouseOut() {
this._indicator.classList.remove('show');
}
_onHourSelect(event) {
this.dispatchEvent(new CustomEvent('update-minutes', {detail: event.detail}));
}
}
customElements.define('time-picker-minutes-plate', TimePickerMinutesPlate);
class WebClockLite extends HTMLElement {
static get observedAttributes() {
return ['hour', 'minutes'];
}
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
this.root.innerHTML = `
<style>
:host {
display: flex;
height: 40px;
align-items: center;
flex-direction: row;
padding: 8px;
box-sizing: border-box;
color: var(--web-clock-color, #555);
cursor: default;
}
:host([picker]) {
cursor: pointer;
})
:host([picker-opened]) {
opacity: 0;
pointer-events: none;
}
.hour, .minutes {
padding: 0 8px;
}
</style>
<div class="hour"></div>
<span class="indicator">:</span>
<div class="minutes"></div>
`;
}
get time() {
return `${this.hour}:${this.minutes}`;
}
get hour() {
return this._hour;
}
get minutes() {
return this._minutes;
}
set hour(value) {
this._applyTimeUpdate('.hour', value);
this._hour = value;
}
set minutes(value) {
this._applyTimeUpdate('.minutes', value);
this._minutes = value;
}
_applyTimeUpdate(query, value) {
let target = this.root.querySelector(query);
requestAnimationFrame(() => {
target.innerHTML = value;
});
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) this[name] = newValue;
}
}
customElements.define('web-clock-lite', WebClockLite);
// TODO: Cleanup & add settings menu
/**
* @extends HTMLElement
*/
class TimePicker extends HTMLElement {
/**
* Attributes to observer
* @return {Array} []
*/
static get observedAttributes() {
return ['no-clock', 'hour', 'minutes'];
}
/**
* Calls super
*/
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
this._onUpdateHour = this._onUpdateHour.bind(this);
this._onUpdateMinutes = this._onUpdateMinutes.bind(this);
this._onWebClockClick = this._onWebClockClick.bind(this);
this._onHourClick = this._onHourClick.bind(this);
this._onMinutesClick = this._onMinutesClick.bind(this);
this._onOk = this._onOk.bind(this);
this._onCancel = this._onCancel.bind(this);
}
/**
* Stamps innerHTML
*/
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 80px;
box-shadow: 0 14px 45px rgba(0, 0, 0, 0.25),
0 10px 18px rgba(0, 0, 0, 0.22);
background: #FFF;
--time-picker-plate-size: 200px;
--time-picker-plate-padding: 22px 0 20px 0;
transition: transform ease-out 160ms, opacity ease-out 160ms, scale ease-out 160ms;
transform-origin: top left;
will-change: transform, height, width, opacity;
--primary-color: #00bcd4;
--primary-text-color: #555;
--clock-container-background: var(--primary-color);
}
.backdrop {
position: absolute;
top: 0;
left: 0;
}
.am-pm, .actions, time-picker-hour-plate, time-picker-minutes-plate {
width: 0;
height: 0;
opacity: 0;
margin: 0;
padding: 0;
pointer-events: none;
}
time-picker-hour-plate, time-picker-minutes-plate {
display: none;
}
:host([show-on-demand]), :host([show-on-demand]) .clock-container {
opacity: 0;
height: 0;
width: 0;
}
:host(.no-clock) {
opacity: 0;
pointer-events: none;
width: 0;
height: 0;
}
:host([show-on-demand] .picker-opened) :host(.picker-opened) {
opacity: 1;
}
:host(.picker-opened) .clock-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: 64px;
width: 100%;
background: var(--clock-container-background);
color: var(--clock-container-color);
transition: background ease-in 300ms;
pointer-events: auto;
}
:host(.picker-opened) {
z-index: 100;
}
.clock-container {
box-sizing: border-box;
}
.am-pm, .actions {
display: flex;
flex-direction: row;
}
.am-pm {
align-items: flex-end;
box-sizing: border-box;
}
.actions {
align-items: center;
box-sizing: border-box;
}
.am, .pm {
height: 40px;
width: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: var(--clock-background);
text-transform: uppercase;
}
button {
border: none;
border-radius: 3px;
text-transform: uppercase;
padding: 8px;
height: 40px;
min-width: 100px;
background: transparent;
cursor: pointer;
outline: none;
}
.flex {
flex: 1;
}
.flex-2 {
flex: 2;
}
:host(.picker-opened) {
opacity: 1;
display: flex;
flex-direction: column;
width: 100%;
height: auto;
max-width: 320px;
box-shadow: 0 14px 45px rgba(0, 0, 0, 0.25),
0 10px 18px rgba(0, 0, 0, 0.22);
background: #FFF;
--clock-background: rgba(0, 0, 0, 0.05);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: transform ease-in 300ms, opacity ease-in 300ms, scale ease-in 300ms;
}
:host(.picker-opened) .am-pm, :host(.picker-opened) .actions {
height: 64px;
width: 100%;
padding: 8px 24px;
pointer-events: auto;
}
:host(.picker-opened) .am-pm, :host(.picker-opened) .actions {
opacity: 1;
}
:host(.picker-opened[hour-picker]) time-picker-hour-plate,
:host(.picker-opened[minutes-picker]) time-picker-minutes-plate {
opacity: 1;
display: flex;
margin: auto;
width: var(--time-picker-plate-size);
height: var(--time-picker-plate-size);
padding: var(--time-picker-plate-padding);
pointer-events: auto;
}
</style>
<span class="clock-container">
<web-clock-lite style="cursor: pointer;"></web-clock-lite>
</span>
<div class="am-pm">
<span class="flex"></span>
<div class="am">am</div>
<span class="flex-2"></span>
<div class="pm">pm</div>
<span class="flex"></span>
</div>
<time-picker-hour-plate></time-picker-hour-plate>
<time-picker-minutes-plate></time-picker-minutes-plate>
<div class="actions">
<button class="cancel">cancel</button>
<span class="flex"></span>
<button class="ok">ok</button>
</div>
`;
if (this.noClock === false) {
this.webClock.addEventListener('click', this._onWebClockClick);
}
this.timeFormat = this.timeFormat;
this.hourPicker = true;
}
get webClock() {
return this.root.querySelector('web-clock-lite');
}
get plate() {
return this.root.querySelector('time-picker-hour-plate');
}
get minutesPlate() {
return this.root.querySelector('time-picker-minutes-plate');
}
get animations() {
return {
entry: {
opacity: 1,
transform: 'translateY(-50%) translateX(-50%) scale(1)'
},
out: {
opacity: 1,
transform: 'translateY(0) translateX(0) scale(1)'
},
shared: {
translate: (x, y) => {
return {opacity: '0.1', transform: `translateY(${y}px) translateX(${x}px) scale(0.1)`};
}
}
}
}
get time() {
return this._time || {hour: '8', minutes: '00'};
}
get cancelButton() {
return this.root.querySelector('.cancel');
}
get okButton() {
return this.root.querySelector('.ok');
}
get timeFormat() {
return this._timeFormat || 24;
}
get noClock() {
return this._noClock || false;
}
set opened(value) {
this._opened = value;
}
get opened() {
return this._opened;
}
set noClock(value) {
this._noClock = value;
if (value) {
this.classList.add('no-clock');
} else {
this.classList.remove('no-clock');
}
}
set hourPicker(value) {
this._timeFormat = value;
let plate = this.root.querySelector('time-picker-hour-plate');
let minutesPlate = this.root.querySelector('time-picker-minutes-plate');
if (value) {
plate.addEventListener('update-hour', this._onUpdateHour);
minutesPlate.removeEventListener('update-minutes', this._onUpdateMinutes);
this.removeAttribute('minutes-picker');
this.setAttribute('hour-picker', '');
} else {
plate.removeEventListener('update-hour', this._onUpdateHour);
minutesPlate.addEventListener('update-minutes', this._onUpdateMinutes);
this.removeAttribute('hour-picker');
this.setAttribute('minutes-picker', '');
}
}
set hour(value) {
this._onUpdateHour(value);
}
set minutes(value) {
this._onUpdateMinutes(value);
}
set time(value) {
this._time = value;
if (!this.webClockLiteReady) {
customElements.whenDefined('web-clock-lite').then(() => {
this._updateTime(value.hour, value.minutes);
this.webClockLiteReady = true;
});
return;
}
this._updateTime(value.hour, value.minutes);
}
_updateTime(hour, minutes) {
this.webClock.hour = hour;
this.webClock.minutes = minutes;
this.dispatchEvent(new CustomEvent('time-change', {detail: this.time}));
}
set timeFormat(value) {
let amPm = this.root.querySelector('.am-pm');
if (value !== 'am' && value !== 'pm') {
amPm.style.opacity = 0;
amPm.style.height = 0;
amPm.style.pointerEvents = 'none';
} else {
amPm.style.opacity = 1;
amPm.style.height = 'initial';
amPm.style.pointerEvents = 'auto';
}
this.plate.timeFormat = value;
}
/**
* Runs whenever attribute changes are detected
* @param {string} name The name of the attribute that changed.
* @param {string|object|array} oldValue
* @param {string|object|array} newValue
*/
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this[this._toJsProp(name)] = newValue;
}
}
_onHourClick() {
this.hourPicker = true;
}
_onMinutesClick() {
this.hourPicker = false;
}
_onUpdateHour(event) {
let hour = event.detail || event;
let time = this.time;
// place a 0 before the digit when length is shorter than 2
hour = this._transformToTime(hour);
time.hour = hour;
this._notify('time', time);
}
_onUpdateMinutes(event) {
let minutes = event.detail || event;
let time = this.time;
minutes = this._transformToTime(minutes);
time.minutes = minutes;
this._notify('time', time);
}
_transformToTime(number) {
// place a 0 before the digit when needed
if (String(number).length === 1) {
return number = `0${number}`;
}
return number;
}
_notify(prop, value) {
this[prop] = value;
}
_onWebClockClick(event) {
event.preventDefault();
if (this.opened) {
return;
}
this.open();
}
open() {
this.opened = true;
this.flip(true);
}
flip(opened) {
let animations;
// Get the first position.
var first = this.getBoundingClientRect();
let hourEl = this.webClock.root.querySelector('.hour');
let minutesEl = this.webClock.root.querySelector('.minutes');
// Get the last position.
if (opened) {
hourEl.addEventListener('click', this._onHourClick);
minutesEl.addEventListener('click', this._onMinutesClick);
this.removeEventListener('click', this._onWebClockClick);
this.okButton.addEventListener('click', this._onOk);
this.cancelButton.addEventListener('click', this._onCancel);
this.classList.add('picker-opened');
} else {
hourEl.removeEventListener('click', this._onHourClick);
minutesEl.removeEventListener('click', this._onMinutesClick);
this.addEventListener('click', this._onWebClockClick);
this.okButton.removeEventListener('click', this._onOk);
this.cancelButton.removeEventListener('click', this._onCancel);
this.classList.remove('picker-opened');
}
var last = this.getBoundingClientRect();
// Invert.
let top = first.top - last.top;
let left = first.left - last.left;
if (opened) {
let color = this.style.getPropertyValue('--primary-color');
animations = [
this.animations.shared.translate(left, top), this.animations.entry
];
requestAnimationFrame(() => {
this.style.setProperty('--clock-container-background', '#FFF');
});
requestAnimationFrame(() => {
this.style.setProperty('--clock-container-background', color);
});
this.style.setProperty('--web-clock-color', '#FFF');
} else {
let textColor = this.style.getPropertyValue('--primary-text-color');
animations = [
this.animations.shared.translate(left, top), this.animations.out
];
this.style.setProperty('--web-clock-color', textColor);
}
// Go from the inverted position to last.
var player = this.animate(animations, {
duration: 300,
easing: 'cubic-bezier(0,0,0.32,1)',
});
// Do any tidy up at the end
// of the animation.
player.addEventListener('finish', () => {
// Workaround for blurry hours bug.
if (opened) requestAnimationFrame(() => {
this.style.display = 'block';
this.plate.style.display = 'block';
this.minutesPlate.style.display = 'block';
});
else requestAnimationFrame(() => {
this.style.display = 'flex';
this.plate.style.display = 'block';
this.minutesPlate.style.display = 'block';
});
});
}
_onOk(event) {
event.stopPropagation();
event.preventDefault();
this.close('ok');
}
_onCancel(event) {
event.stopPropagation();
event.preventDefault();
this.close('cancel');
}
close(action) {
this.opened = false;
this.flip(false);
this.dispatchEvent(new CustomEvent('time-picker-action', {
detail: {
action: action,
time: this.time
}
}));
}
_toJsProp(string) {
var parts = string.split('-');
if (parts.length > 1) {
var upper = parts[1].charAt(0).toUpperCase();
string = parts[0] + upper + parts[1].slice(1).toLowerCase();
}
return string;
}
}
customElements.define('time-picker', TimePicker);
}());