diff --git a/src/components/time-unit.ts b/src/components/time-unit.ts
new file mode 100644
index 0000000..77b5407
--- /dev/null
+++ b/src/components/time-unit.ts
@@ -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`
+ ${this.renderStepChanger(Direction.UP)}
+
+ ${this.renderStepChanger(Direction.DOWN)}
+
`;
+ }
+
+ 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`
+ this.onStepChangerClick(direction)}>
+
+
+
+ `;
+ }
+
+ 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;
+ }
+ `;
+ }
+}
diff --git a/src/const.ts b/src/const.ts
index 54dd41d..7cfc5f0 100644
--- a/src/const.ts
+++ b/src/const.ts
@@ -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)',
+};
diff --git a/src/partials.ts b/src/partials.ts
index c4e6254..48c49da 100644
--- a/src/partials.ts
+++ b/src/partials.ts
@@ -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): TemplateResult {
- const onInputChange = ({ target: { value } }: { target: HTMLInputElement }): void => {
- unit.setStringValue(value);
- serviceFn();
- };
-
- return html`
-
- ${Partial.stepChanger(Direction.UP, unit, serviceFn)}
-
- ${Partial.stepChanger(Direction.DOWN, unit, serviceFn)}
-
- `;
- }
-
- private static stepChanger(
- direction: Direction,
- unit: TimeUnit,
- serviceFn: () => Promise
- ): TemplateResult {
- const onIconClick = (): void => {
- unit.stepUpdate(direction);
- serviceFn();
- };
-
- return html`
-
-
-
-
- `;
- }
-
static error(error: string, origConfig: TimePickerCardConfig): TemplateResult {
- const config = { error, origConfig };
- return html``;
+ const errorCard = document.createElement('hui-error-card') as LovelaceCard;
+ errorCard.setConfig({
+ type: 'error',
+ error,
+ origConfig,
+ });
+
+ return html`${errorCard}`;
}
}
diff --git a/src/styles.ts b/src/styles.ts
deleted file mode 100644
index 72287de..0000000
--- a/src/styles.ts
+++ /dev/null
@@ -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;
- }
-`;
diff --git a/src/time-picker-card.ts b/src/time-picker-card.ts
index d40c539..bb80da7 100644
--- a/src/time-picker-card.ts
+++ b/src/time-picker-card.ts
@@ -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`
- ${Partial.unit(this.hour, this.serviceFn.bind(this))}
+
:
- ${Partial.unit(this.minute, this.serviceFn.bind(this))}
+
`;
}
@@ -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;
+ }
+ `;
}
}
diff --git a/src/types.ts b/src/types.ts
index ce98d78..6046c9e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -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;