Merge pull request #1364 from dermotduffy/new-date-picker
Fix timeline date picker for iOS users
This commit is contained in:
@@ -32,7 +32,6 @@
|
||||
"home-assistant-js-websocket": "^8.0.0",
|
||||
"keycharm": "^0.4.0",
|
||||
"lit": "^2.3.1",
|
||||
"lit-flatpickr": "^0.4.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"masonry-layout": "^4.2.2",
|
||||
"moment": "^2.29.4",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
||||
import 'lit-flatpickr';
|
||||
import { LitFlatpickr } from 'lit-flatpickr';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||
import { localize } from '../localize/localize';
|
||||
import datePickerStyle from '../scss/date-picker.scss';
|
||||
import { stopEventFromActivatingCardWideActions } from '../utils/action';
|
||||
import { dispatchFrigateCardEvent } from '../utils/basic';
|
||||
|
||||
export interface DatePickerEvent {
|
||||
@@ -12,24 +12,33 @@ export interface DatePickerEvent {
|
||||
|
||||
@customElement('frigate-card-date-picker')
|
||||
export class FrigateCardDatePicker extends LitElement {
|
||||
protected _refInput: Ref<LitFlatpickr> = createRef();
|
||||
|
||||
public open(): void {
|
||||
this._refInput.value?.open();
|
||||
}
|
||||
protected _refInput: Ref<HTMLInputElement> = createRef();
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html` <lit-flatpickr
|
||||
${ref(this._refInput)}
|
||||
.onChange=${(dates: Date[]) => {
|
||||
if (dates.length) {
|
||||
// This is a single date picker, there should be only a single date.
|
||||
dispatchFrigateCardEvent<DatePickerEvent>(this, 'date-picker:change', {
|
||||
date: dates[0],
|
||||
});
|
||||
}
|
||||
}}
|
||||
></lit-flatpickr>`;
|
||||
return html`<input
|
||||
aria-label="${localize('timeline.select_date')}"
|
||||
title="${localize('timeline.select_date')}"
|
||||
${ref(this._refInput)}
|
||||
type="datetime-local"
|
||||
@input=${() => {
|
||||
const value = this._refInput.value?.value;
|
||||
if (value) {
|
||||
dispatchFrigateCardEvent<DatePickerEvent>(this, 'date-picker:change', {
|
||||
date: new Date(value),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ha-icon
|
||||
aria-label="${localize('timeline.select_date')}"
|
||||
title="${localize('timeline.select_date')}"
|
||||
.icon=${`mdi:calendar-search`}
|
||||
@click=${(ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
this._refInput.value?.showPicker();
|
||||
}}
|
||||
>
|
||||
</ha-icon>`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import add from 'date-fns/add';
|
||||
import differenceInSeconds from 'date-fns/differenceInSeconds';
|
||||
import endOfDay from 'date-fns/endOfDay';
|
||||
import startOfDay from 'date-fns/startOfDay';
|
||||
import sub from 'date-fns/sub';
|
||||
import {
|
||||
CSSResultGroup,
|
||||
@@ -334,22 +332,10 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
>
|
||||
</ha-icon>`
|
||||
: ''}
|
||||
<ha-icon
|
||||
.icon=${`mdi:calendar-search`}
|
||||
aria-label="${localize('timeline.select_date')}"
|
||||
title="${localize('timeline.select_date')}"
|
||||
@click=${() => {
|
||||
this._refDatePicker.value?.open();
|
||||
}}
|
||||
>
|
||||
</ha-icon>
|
||||
<frigate-card-date-picker
|
||||
${ref(this._refDatePicker)}
|
||||
@frigate-card:date-picker:change=${(ev: CustomEvent<DatePickerEvent>) => {
|
||||
this._timeline?.setWindow(
|
||||
startOfDay(ev.detail.date),
|
||||
endOfDay(ev.detail.date),
|
||||
);
|
||||
this._timeline?.moveTo(ev.detail.date);
|
||||
}}
|
||||
>
|
||||
</frigate-card-date-picker>
|
||||
|
||||
@@ -1,7 +1,50 @@
|
||||
// The lit-flatpickr element itself is hidden as we only want the popup
|
||||
// calender.
|
||||
lit-flatpickr {
|
||||
visibility: hidden;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
:host {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: var(--mdc-icon-size, 24px);
|
||||
height: var(--mdc-icon-size, 24px);
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
|
||||
padding: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack warning: Safari on iOS does not support showPicker with
|
||||
* datetime-local:
|
||||
* https://caniuse.com/mdn-api_htmlinputelement_showpicker_datetime_local_input
|
||||
*
|
||||
* The hack is to render the input element in front of the icon, with an
|
||||
* opacity of 0. This only works if the underlying input element accepts the
|
||||
* click at the exact place the user happens to click. From trial and error,
|
||||
* this seems to work better than expected / quite reliably, but had the user
|
||||
* manually changed icon sizes with Safari iOS their experience may vary.
|
||||
*/
|
||||
|
||||
// webkit-touch-callout used to "detect" Safari on iOS. See:
|
||||
// - https://stackoverflow.com/questions/30102792/css-media-query-to-target-only-ios-devices
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
input {
|
||||
// Need it to be in "front" but not visible to the naked eye.
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
@supports not (-webkit-touch-callout: none) {
|
||||
input {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
ha-icon {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@@ -170,6 +170,7 @@ div.vis-tooltip {
|
||||
}
|
||||
|
||||
.timeline-tools {
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
|
||||
@@ -3282,13 +3282,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"flatpickr@npm:^4.6.13":
|
||||
version: 4.6.13
|
||||
resolution: "flatpickr@npm:4.6.13"
|
||||
checksum: 2cca1b8dc974e7673b51174ee3f0679ae3a6b79525a0c53bf49b87455ef358354e64acfd60b312e44cef208aab9750a1a48df32a0914046a53de6d9403742304
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"flatted@npm:^3.1.0":
|
||||
version: 3.2.7
|
||||
resolution: "flatted@npm:3.2.7"
|
||||
@@ -3357,7 +3350,6 @@ __metadata:
|
||||
jsdom: ^21.1.1
|
||||
keycharm: ^0.4.0
|
||||
lit: ^2.3.1
|
||||
lit-flatpickr: ^0.4.0
|
||||
lodash-es: ^4.17.21
|
||||
masonry-layout: ^4.2.2
|
||||
moment: ^2.29.4
|
||||
@@ -4384,17 +4376,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lit-flatpickr@npm:^0.4.0":
|
||||
version: 0.4.0
|
||||
resolution: "lit-flatpickr@npm:0.4.0"
|
||||
dependencies:
|
||||
flatpickr: ^4.6.13
|
||||
lit: ^2.0.0
|
||||
tslib: ^1.11.0
|
||||
checksum: 2141902346bf3f2d291e1c3369317bb494641da48a3f69dabb891b7d065e2505b268c584cbc1859c36763374b9880399b17d93721539b2dc7d90c58988dba471
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lit-html@npm:^2.2.0, lit-html@npm:^2.6.0":
|
||||
version: 2.6.1
|
||||
resolution: "lit-html@npm:2.6.1"
|
||||
@@ -6571,7 +6552,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:^1.11.0, tslib@npm:^1.8.1":
|
||||
"tslib@npm:^1.8.1":
|
||||
version: 1.14.1
|
||||
resolution: "tslib@npm:1.14.1"
|
||||
checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd
|
||||
|
||||
Reference in New Issue
Block a user