Extract time-unit component. Refactor styles. Refactor error partial.

This commit is contained in:
2020-05-05 02:47:04 +03:00
parent 1a827de177
commit fdc9c5bd22
6 changed files with 156 additions and 119 deletions
+109
View File
@@ -0,0 +1,109 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';
import { TimeUnit } from '../models';
import { Direction } from '../types';
@customElement('time-unit')
export class TimeUnitComponent extends LitElement {
@property() private unit?: TimeUnit;
render(): TemplateResult {
if (!this.unit) {
throw new Error('Missing unit in time-unit. This should never happen :)');
}
return html`<div class="time-unit">
${this.renderStepChanger(Direction.UP)}
<input
class="time-input"
type="number"
placeholder="MM"
min="0"
max="60"
.value="${this.unit.toString()}"
@change=${this.onInputChange}
/>
${this.renderStepChanger(Direction.DOWN)}
</div>`;
}
onInputChange({ target: { value } }: { target: HTMLInputElement }): void {
this.unit!.setStringValue(value);
this.emitUpdate();
}
onStepChangerClick(direction: Direction): void {
this.unit!.stepUpdate(direction);
this.emitUpdate();
}
private emitUpdate(): void {
const event = new CustomEvent('update');
this.dispatchEvent(event);
}
private renderStepChanger(direction: Direction): TemplateResult {
return html`
<div class="time-picker-icon" @click=${() => this.onStepChangerClick(direction)}>
<ha-icon .icon="mdi:arrow-${direction}"></ha-icon>
<mwc-ripple id="ripple"></mwc-ripple>
</div>
`;
}
static get styles(): CSSResult {
return css`
.time-unit {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 8px;
}
.time-picker-icon {
width: 30px;
padding: 8px;
text-align: center;
cursor: pointer;
}
.time-input {
width: 30px;
padding: 8px 8px 6px;
background: var(--time-picker-card-background-color);
border: 0;
border-bottom: 2px solid var(--time-picker-card-background-color);
color: var(--text-color, #fff);
text-align: center;
font-size: 1em;
-moz-appearance: textfield;
transition: border-color 0.2s ease-in-out;
}
.time-input:focus {
outline: none;
}
.time-input:invalid {
box-shadow: none;
outline: none;
border: 0;
border-bottom: 2px solid red;
}
.time-input::-webkit-inner-spin-button,
.time-input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
`;
}
}
+4
View File
@@ -1,3 +1,7 @@
import * as pkg from '../package.json';
export const CARD_VERSION = pkg.version;
export const STYLE_VARIABLES = {
'--time-picker-card-background-color': 'rgb(37, 47, 68)',
};
+10 -45
View File
@@ -1,51 +1,16 @@
import { html, TemplateResult } from 'lit-element';
import { TimePickerCardConfig, Direction } from './types';
import { TimeUnit } from './models';
import { TimePickerCardConfig } from './types';
import { LovelaceCard } from 'custom-card-helpers';
export class Partial {
static unit(unit: TimeUnit, serviceFn: () => Promise<void>): TemplateResult {
const onInputChange = ({ target: { value } }: { target: HTMLInputElement }): void => {
unit.setStringValue(value);
serviceFn();
};
return html`
<div class="time-unit">
${Partial.stepChanger(Direction.UP, unit, serviceFn)}
<input
class="time-input"
type="number"
placeholder="MM"
min="0"
max="60"
.value="${unit.toString()}"
@change=${onInputChange}
/>
${Partial.stepChanger(Direction.DOWN, unit, serviceFn)}
</div>
`;
}
private static stepChanger(
direction: Direction,
unit: TimeUnit,
serviceFn: () => Promise<void>
): TemplateResult {
const onIconClick = (): void => {
unit.stepUpdate(direction);
serviceFn();
};
return html`
<div class="time-picker-icon" @click=${onIconClick}>
<ha-icon .icon="mdi:arrow-${direction}"></ha-icon>
<mwc-ripple id="ripple"></mwc-ripple>
</div>
`;
}
static error(error: string, origConfig: TimePickerCardConfig): TemplateResult {
const config = { error, origConfig };
return html`<hui-error-card ._config="${config}"></hui-error-card>`;
const errorCard = document.createElement('hui-error-card') as LovelaceCard;
errorCard.setConfig({
type: 'error',
error,
origConfig,
});
return html`${errorCard}`;
}
}
-60
View File
@@ -1,60 +0,0 @@
import { css } from 'lit-element';
export const styleVariables = {
'--time-picker-card-background-color': 'rgb(37, 47, 68)',
};
export const styles = css`
.time-picker-ha-card {
padding: 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.time-unit {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 8px;
}
.time-picker-icon {
width: 30px;
padding: 8px;
text-align: center;
cursor: pointer;
}
.time-input {
width: 30px;
padding: 8px;
background: var(--time-picker-card-background-color);
border: 0;
color: var(--text-color, #fff);
text-align: center;
font-size: 1em;
}
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type='number'] {
-moz-appearance: textfield;
}
input[type='number']:focus {
outline: none;
}
input[type='number']:invalid {
box-shadow: none;
outline: none;
border: 0;
border-bottom: 2px solid red;
}
`;
+30 -13
View File
@@ -1,10 +1,18 @@
import { HomeAssistant } from 'custom-card-helpers';
import { HassEntity } from 'home-assistant-js-websocket';
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from 'lit-element';
import { CARD_VERSION } from './const';
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';
import './components/time-unit';
import { CARD_VERSION, STYLE_VARIABLES } from './const';
import { Hour, Minute } from './models';
import { Partial } from './partials';
import { styles, styleVariables } from './styles';
import { TimePickerCardConfig } from './types';
console.info(
@@ -20,6 +28,14 @@ export class TimePickerCard extends LitElement {
@property() private hour?: Hour;
@property() private minute?: Minute;
connectedCallback(): void {
super.connectedCallback();
Object.entries(STYLE_VARIABLES).forEach(([variable, value]) =>
this.style.setProperty(variable, value)
);
}
private get entity(): HassEntity | undefined {
if (!this.config) {
return;
@@ -44,15 +60,14 @@ export class TimePickerCard extends LitElement {
);
}
this.setStyleVarialbes();
this.hour = new Hour(this.entity?.attributes.hour ?? 0, this.config.hour_step);
this.minute = new Minute(this.entity?.attributes.minute ?? 0, this.config.minute_step);
return html`
<ha-card class="time-picker-ha-card">
${Partial.unit(this.hour, this.serviceFn.bind(this))}
<time-unit .unit=${this.hour} @update=${this.serviceFn.bind(this)}></time-unit>
<div class="time-separator">:</div>
${Partial.unit(this.minute, this.serviceFn.bind(this))}
<time-unit .unit=${this.minute} @update=${this.serviceFn.bind(this)}></time-unit>
</ha-card>
`;
}
@@ -86,13 +101,15 @@ export class TimePickerCard extends LitElement {
});
}
private setStyleVarialbes(): void {
Object.entries(styleVariables).forEach(([variable, value]) =>
this.style.setProperty(variable, value)
);
}
static get styles(): CSSResult {
return styles;
return css`
.time-picker-ha-card {
padding: 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
`;
}
}
+3 -1
View File
@@ -1,4 +1,6 @@
export interface TimePickerCardConfig {
import { LovelaceCardConfig } from 'custom-card-helpers';
export interface TimePickerCardConfig extends LovelaceCardConfig {
entity: string;
hour_step?: number;
minute_step?: number;