Compare commits

...
8 Commits
Author SHA1 Message Date
GeorgeSG 8e11f71b48 0.0.4 2020-05-07 20:37:44 +03:00
GeorgeSG c646fc9c9e Update default colors and variables 2020-05-07 20:37:33 +03:00
GeorgeSG 2791d8109c 0.0.3 2020-05-07 19:55:59 +03:00
GeorgeSG 14cc1a2c10 Add option to configure the AM/PM layout 2020-05-07 19:55:45 +03:00
GeorgeSG 76a52f0c9f Add some comments 2020-05-07 01:52:24 +03:00
GeorgeSG ce22ceb808 Refactor constants 2020-05-07 01:45:31 +03:00
GeorgeSG 45d3364959 Use ENTITY_DOMAIN in callService 2020-05-07 01:40:29 +03:00
GeorgeSG 6ac3d62823 Use computeDomain 2020-05-07 01:38:05 +03:00
15 changed files with 120 additions and 48 deletions
+28 -7
View File
@@ -15,11 +15,21 @@ Requires an [Input Datetime](https://www.home-assistant.io/integrations/input_da
## Screenshots
### Default config - card name shown, 24 hour mode
![Default theme with card name](examples/default_with_name.png)
### Custom config - hidden card name, 12 hour mode
![Default theme with no card name](examples/default_without_name.png)
![Cudtom theme ](examples/custom.png)
### Custom config - hidden card name, 12 hour mode with a "single" hour mode picker
![Default theme with single hour mode](examples/single_hour_mode.png)
### Using a custom theme
![Cudtom theme](examples/custom.png)
## Installation
@@ -54,8 +64,15 @@ hide:
| hour_mode | `12` or `24` | **Optional** | Hour format. If `12`, card will show AM/PM picker | `24` |
| hour_step | number | **Optional** | Hour change when clicking arrows | `1` |
| minute_step | number | **Optional** | Minute change when clicking arrows | `5` |
| layout | object | **Optional** | Card Layout configuration | `none` |
| hide | object | **Optional** | Hide object | `none` |
## Layout Object
| Name | Type | Requirement | Description | Default |
| --------- | -------------------- | ------------ | -------------------------------------------------------------------------------------------------- | -------- |
| hour_mode | `single` or `double` | **Optional** | Whether to show both AM/PM or just the current mode. In `single` mode, tap the value to change it. | `double` |
## Hide Object
| Name | Type | Requirement | Description | Default |
@@ -64,12 +81,16 @@ hide:
## Theme Variables
| Name | Default | Description |
| ------------------------------- | --------------------------- | ------------------------------------------- |
| --tpc-elements-background-color | `var(--dark-primary-color)` | Background color for header and ui elements |
| --tpc-icon-color | `var(--primary-text-color)` | Arrow color |
| --tpc-text-color | `white` | Text color |
| --tpc-accent-color | `var(--accent-color)` | AM / PM active color |
Time Picker card will automatically pick up colors from your lovelace theme, but if you want to customize some of them,
you can use the following theme variables:
| Name | Default | Description |
| --------------------------------------- | ---------------------------- | -------------------------------------- |
| --time-picker-elements-background-color | `var(--primary-color)` | Background color for header and inputs |
| --time-picker-icon-color | `var(--primary-text-color)` | Arrow color |
| --time-picker-text-color | `white` | Text color |
| --time-picker-accent-color | `var(--accent-color)` | AM / PM active color |
| --time-picker-off-color | `var(--disabled-text-color)` | AM / PM inactive color |
## Meta
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "time-picker-card",
"version": "0.0.2",
"version": "0.0.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "time-picker-card",
"version": "0.0.2",
"version": "0.0.4",
"author": "Georgi Gardev <georgi@gardev.com>",
"description": "Lovelace time-picker-card",
"keywords": [
+24 -9
View File
@@ -8,13 +8,18 @@ import {
TemplateResult,
} from 'lit-element';
import { ClassInfo, classMap } from 'lit-html/directives/class-map';
import { Period } from '../types';
import { Period, HourModeLayout } from '../types';
/**
* Renders a Time Period selector with an input for a value and two arrows for step-chaning
* the value up and down.
*/
@customElement('time-period')
export class TimePeriodComponent extends LitElement {
static readonly EVENT_TOGGLE = 'toggle';
@property() private period!: Period;
@property() private mode!: HourModeLayout;
private get amClass(): ClassInfo {
return { 'time-period': true, active: this.period === Period.AM };
@@ -26,12 +31,7 @@ export class TimePeriodComponent extends LitElement {
render(): TemplateResult {
return html`<div class="time-period-selector">
<div class=${classMap(this.amClass)} @click=${this.onTimePeriodChange}>
AM<mwc-ripple></mwc-ripple>
</div>
<div class=${classMap(this.pmClass)} @click=${this.onTimePeriodChange}>
PM<mwc-ripple></mwc-ripple>
</div>
${this.mode === 'single' ? this.renderSingle() : this.renderDouble()}
</div>`;
}
@@ -40,6 +40,21 @@ export class TimePeriodComponent extends LitElement {
this.dispatchEvent(event);
}
private renderSingle(): TemplateResult {
return html`<div class="time-period active" @click=${this.onTimePeriodChange}>
${this.period}<mwc-ripple></mwc-ripple>
</div>`;
}
private renderDouble(): TemplateResult {
return html`<div class=${classMap(this.amClass)} @click=${this.onTimePeriodChange}>
AM<mwc-ripple></mwc-ripple>
</div>
<div class=${classMap(this.pmClass)} @click=${this.onTimePeriodChange}>
PM<mwc-ripple></mwc-ripple>
</div>`;
}
static get styles(): CSSResult {
return css`
.time-period-selector {
@@ -49,8 +64,8 @@ export class TimePeriodComponent extends LitElement {
.time-period {
width: 30px;
padding: 8px;
background: var(--tpc-elements-background-color);
color: var(--tpc-text-color, #fff);
background: var(--tpc-off-color);
color: var(--tpc-text-color);
text-align: center;
font-size: 1em;
cursor: pointer;
+3
View File
@@ -10,6 +10,9 @@ import {
import { TimeUnit } from '../models/time-unit';
import { Direction } from '../types';
/**
* Renders an AM/PM picker.
*/
@customElement('time-unit')
export class TimeUnitComponent extends LitElement {
static readonly EVENT_UPDATE = 'update';
+7
View File
@@ -2,3 +2,10 @@ import * as pkg from '../package.json';
export const CARD_VERSION = pkg.version;
export const CARD_SIZE = 3;
export const ENTITY_DOMAIN = 'input_datetime';
// Config defaults
export const DEFAULT_HOUR_STEP = 1;
export const DEFAULT_MINUTE_STEP = 5;
export const DEFAULT_LAYOUT_HOUR_MODE = 'double';
+9 -6
View File
@@ -1,16 +1,19 @@
import { TimeUnit } from './time-unit';
import { DEFAULT_HOUR_STEP } from '../const';
import { HourMode } from '../types';
import { TimeUnit } from './time-unit';
/**
* Represents the hour value of a datetime.
*/
export class Hour extends TimeUnit {
private static readonly DEFAULT_STEP = 1;
private static readonly MAX = 24;
private static readonly VALUE_LIMIT = 24;
constructor(value: number, step = Hour.DEFAULT_STEP, private hourMode: HourMode) {
super(value, step, Hour.MAX);
constructor(value: number, step = DEFAULT_HOUR_STEP, private hourMode: HourMode) {
super(value, step, Hour.VALUE_LIMIT);
}
get maxValue(): number {
return this.hourMode || Hour.MAX;
return this.hourMode || Hour.VALUE_LIMIT;
}
togglePeriod(): void {
+8 -5
View File
@@ -1,13 +1,16 @@
import { DEFAULT_MINUTE_STEP } from '../const';
import { TimeUnit } from './time-unit';
/**
* * Represents the minute value of a datetime.
*/
export class Minute extends TimeUnit {
private static readonly DEFAULT_STEP = 5;
private static readonly MAX = 60;
private static readonly VALUE_LIMIT = 60;
maxValue = Minute.MAX;
maxValue = Minute.VALUE_LIMIT;
constructor(value: number, step = Minute.DEFAULT_STEP) {
super(value, step, Minute.MAX);
constructor(value: number, step = DEFAULT_MINUTE_STEP) {
super(value, step, Minute.VALUE_LIMIT);
}
protected isValidString(valueStr: string): boolean {
+18 -7
View File
@@ -1,8 +1,11 @@
import { Direction } from '../types';
/**
* Represents a single unit of a datetime oobject - e.g. hours or minutes.
*/
export abstract class TimeUnit {
/**
* Return true if the valueStr can be set as a value of this instance.
* Whether {@param valueStr} can be set as a value of this instance.
*/
protected abstract isValidString(valueStr: string): boolean;
@@ -23,28 +26,36 @@ export abstract class TimeUnit {
return this._value;
}
/**
* Sets a value from {@param stringValue}, if it can be parsed and is valid.
* @param stringValue
*/
setStringValue(stringValue: string): void {
if (this.isValidString(stringValue)) {
this.setValue(parseInt(stringValue));
}
}
/**
* Updates the value in {@param direction} by the step size specified in the constructoor.
* @param direction
*/
stepUpdate(direction: Direction): void {
direction === Direction.UP ? this.increment() : this.decrement();
}
increment(): void {
toString(): string {
return this.value < 10 ? `0${this.value}` : this.value.toString();
}
private increment(): void {
this.setValue(this.value + this._step);
}
decrement(): void {
private decrement(): void {
this.setValue(this.value - this._step);
}
toString(): string {
return this.value < 10 ? `0${this.value}` : this.value.toString();
}
protected setValue(newValue: number): void {
if (newValue >= this._limit || newValue < 0) {
newValue = (newValue + this._limit) % this._limit;
+10 -8
View File
@@ -1,4 +1,4 @@
import { HomeAssistant } from 'custom-card-helpers';
import { computeDomain, HomeAssistant } from 'custom-card-helpers';
import { HassEntity } from 'home-assistant-js-websocket';
import {
css,
@@ -11,7 +11,7 @@ import {
} from 'lit-element';
import './components/time-period.component';
import './components/time-unit.component';
import { CARD_SIZE, CARD_VERSION } from './const';
import { CARD_SIZE, CARD_VERSION, ENTITY_DOMAIN, DEFAULT_LAYOUT_HOUR_MODE } from './const';
import { Hour } from './models/hour';
import { Minute } from './models/minute';
import { Partial } from './partials';
@@ -52,13 +52,13 @@ export class TimePickerCard extends LitElement {
return Partial.error('Entity not found', this.config);
}
if (!this.entity.entity_id.startsWith('input_datetime')) {
return Partial.error('You must set an input_datetime entity', this.config);
if (computeDomain(this.entity.entity_id) !== ENTITY_DOMAIN) {
return Partial.error(`You must set an ${ENTITY_DOMAIN} entity`, this.config);
}
if (!this.entity.attributes.has_time) {
return Partial.error(
'You must set an input_datetime entity that sets has_time: true',
`You must set an ${ENTITY_DOMAIN} entity that sets has_time: true`,
this.config
);
}
@@ -79,6 +79,7 @@ export class TimePickerCard extends LitElement {
${this.shouldShowPeriod
? html`<time-period
.period=${this.period}
.mode=${this.config.layout?.hour_mode ?? DEFAULT_LAYOUT_HOUR_MODE}
@toggle=${this.onPeriodToggle}
></time-period>`
: ''}
@@ -119,7 +120,7 @@ export class TimePickerCard extends LitElement {
const time = `${this.hour.value}:${this.minute.value}:00`;
return this.hass.callService('input_datetime', 'set_datetime', {
return this.hass.callService(ENTITY_DOMAIN, 'set_datetime', {
entity_id: this.entity!.entity_id,
time,
});
@@ -130,12 +131,13 @@ export class TimePickerCard extends LitElement {
:host {
--tpc-elements-background-color: var(
--time-picker-elements-background-color,
var(--dark-primary-color)
var(--primary-color)
);
--tpc-icon-color: var(--time-picker-icon-color, var(--primary-text-color));
--tpc-text-color: var(--time-picker-text-color, #fff);
--tpc-accent-color: var(--time-picker-accent-color, var(--accent-color));
--tpc-accent-color: var(--time-picker-accent-color, var(--primary-color));
--tpc-off-color: var(--time-picker-off-color, var(--disabled-text-color));
}
.time-picker-header {
+11 -4
View File
@@ -6,9 +6,18 @@ export interface TimePickerCardConfig extends LovelaceCardConfig {
hour_mode?: HourMode;
hour_step?: number;
minute_step?: number;
layout?: TimePickerLayoutConfig;
hide?: TimePickerHideConfig;
}
export type HourMode = 12 | 24 | undefined;
export interface TimePickerLayoutConfig {
hour_mode: HourModeLayout;
}
export type HourModeLayout = 'single' | 'double';
export interface TimePickerHideConfig {
name: boolean;
}
@@ -19,8 +28,6 @@ export enum Direction {
}
export enum Period {
AM = 'am',
PM = 'pm',
AM = 'AM',
PM = 'PM',
}
export type HourMode = 12 | 24 | undefined;