Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add keyboard UI #20

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ dist
# TernJS port file
.tern-port

# Build files
_static/
2 changes: 2 additions & 0 deletions v2/esp-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "./esp-entity-table";
import "./esp-log";
import "./esp-switch";
import "./esp-logo";
import "./esp-keyboard";
import cssReset from "./css/reset";
import cssButton from "./css/button";

Expand Down Expand Up @@ -102,6 +103,7 @@ export default class EspApp extends LitElement {
${this.config.title}
<span id="beat" title="${this.version}">❤</span>
</h1>
<esp-keyboard ></esp-keyboard>
<main class="flex-grid-half">
<section class="col">
<esp-entity-table></esp-entity-table>
Expand Down
22 changes: 21 additions & 1 deletion v2/esp-entity-table.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { html, css, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import { customElement, state, property } from "lit/decorators.js";
import cssReset from "./css/reset";
import cssButton from "./css/button";

Expand Down Expand Up @@ -34,6 +34,8 @@ let basePath = getBasePath();
@customElement("esp-entity-table")
export class EntityTable extends LitElement {
@state({ type: Array, reflect: true }) entities: entityConfig[] = [];
@property()
keyboard_id = ''

constructor() {
super();
Expand Down Expand Up @@ -65,6 +67,9 @@ export class EntityTable extends LitElement {
this.requestUpdate();
}
});
window.addEventListener('kbd-closed', (evt) => {
this.keyboard_id = ''
});
}
actionButton(entity: entityConfig, label: String, action?: String) {
let a = action || label.toLowerCase();
Expand Down Expand Up @@ -135,6 +140,12 @@ export class EntityTable extends LitElement {
}

control(entity: entityConfig) {
if (entity.domain === "keyboard") {
return html`<button @click=${
() => this.update_kbd_id(this.keyboard_id == entity.id ? '' : entity.id)
}>${this.keyboard_id == entity.id ? 'Hide' : 'Show'}</button>`;
}

if (entity.domain === "switch") return [this.switch(entity)];

if (entity.domain === "fan") {
Expand Down Expand Up @@ -258,6 +269,15 @@ export class EntityTable extends LitElement {
});
}

update_kbd_id(id: string) {
this.dispatchEvent(new CustomEvent('update-kbd-id', {
detail: id,
composed: true,
bubbles: true
}));
this.keyboard_id = id
}

render() {
return html`
<table>
Expand Down
176 changes: 176 additions & 0 deletions v2/esp-keyboard-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { LitElement, html, css, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";


const pressedStyle = html`
<style> :host .key {
outline: 1px solid #333333;
background-color: #8f8f8f !important;
} </style>`;

@customElement("keyboard-key")
export default class EspKey extends LitElement {
@property()
modifier = false;
@property()
pressed = false;
@property()
code = ''
@property()
'use-code'=false

constructor() {
super();
this.addEventListener("click", (evt) => {
this.togglePressedState();

// Don't send event if click removed "pressed" state
// on a modifier key.
if (!this.modifier || this.pressed) {
this.dispatchEvent(
new CustomEvent("keyclick", {
detail: {
key: this.key,
code: this.code,
isModifier: this.modifier,
},
bubbles: true,
composed: true,
})
);
} else {
this.dispatchEvent(
new CustomEvent("keyrelease", {
detail: {
key: this.key,
code: this.code,
},
bubbles: true,
composed: true,
})
);
}
});
}

get key() {
const bottomLabel = this.querySelector("[slot=bottom]")

if (bottomLabel) {
return bottomLabel.innerHTML;
}

if (this['use-code']) {
return this.code;
}

const keyLabel = this.firstChild?.textContent;
// If the key is a single A-Z character, return the lowercase
// version.
if (keyLabel && /^[A-Z]$/.test(keyLabel)) {
return keyLabel.toLowerCase();
}
return keyLabel;
}

set press(newValue : boolean) {
// Only modifier keys can be "pressed".
if (this.modifier) {
this.pressed = newValue;
}
}

togglePressedState() {
this.press = !this.pressed;
}

render() {
return html`
${this.pressed && pressedStyle || nothing }
<button type="button" class="key">
<span class="content-top">
<!-- default slot -->
<slot></slot>
</span>
<span class="content-bottom">
<slot name="bottom"></slot>
</span>
</button>`;
}

static get styles() {
return [
css`
.key {
position: relative;
display: block;
float: left;
width: 50px;
height: 50px;
font-size: 12px;
background-color: #fff;
line-height: 16px;
border-radius: 2px;
margin: 1px;
padding: 1px;
cursor: pointer;
border: 1px solid rgb(187, 187, 187);
text-align: left;
transition: background-color 0.25s;
}

.key:hover {
background-color: #e3e3e3;
}

.key:active {
background-color: #8f8f8f;
}

.key .content-top {
position: absolute;
top: 5px;
left: 5px;
}

.key .content-bottom {
position: absolute;
bottom: 5px;
left: 5px;
}

:host(.hidden) .key {
visibility: hidden;
}

:host(.accented) .key {
background-color: #dbdbdb;
}

:host(.accented) .key:hover {
background-color: #b5b5b5;
}

:host(.key-collapse-half) .key {
width: 24px;
}

:host(.key-extend-half) .key {
width: 77px;
}

:host(.key-extend-full) .key {
width: 102px;
}

:host(.key-extend-full-half) .key {
width: 128px;
}

:host(.key-space) .key {
width: 229px;
}`,
]
}

}
Loading