From 7f8d23f7f7856f1573e33a8257c9edab2003bce5 Mon Sep 17 00:00:00 2001 From: Jesse Sopel Date: Fri, 2 Oct 2020 23:41:43 -0400 Subject: [PATCH] feat: Start on the kanji clock 0.0.1 --- .devcontainer/ui-lovelace.yaml | 8 +- README.md | 119 +++--------- hacs.json | 4 +- images/12h-kanji.png | Bin 0 -> 10078 bytes images/12h.png | Bin 0 -> 11617 bytes package.json | 25 ++- rollup.config.js | 2 +- src/action-handler-directive.ts | 188 ------------------- src/boilerplate-card.ts | 118 ------------ src/const.ts | 5 +- src/editor.ts | 310 -------------------------------- src/kanji-clock-card.ts | 123 +++++++++++++ src/localize/languages/en.json | 7 - src/localize/languages/nb.json | 7 - src/localize/localize.ts | 27 --- src/types.ts | 22 +-- yarn.lock | 24 +++ 17 files changed, 207 insertions(+), 782 deletions(-) create mode 100644 images/12h-kanji.png create mode 100644 images/12h.png delete mode 100644 src/action-handler-directive.ts delete mode 100644 src/boilerplate-card.ts delete mode 100644 src/editor.ts create mode 100644 src/kanji-clock-card.ts delete mode 100644 src/localize/languages/en.json delete mode 100644 src/localize/languages/nb.json delete mode 100644 src/localize/localize.ts diff --git a/.devcontainer/ui-lovelace.yaml b/.devcontainer/ui-lovelace.yaml index 1d4526b..479bea5 100644 --- a/.devcontainer/ui-lovelace.yaml +++ b/.devcontainer/ui-lovelace.yaml @@ -3,7 +3,7 @@ resources: type: module views: - cards: - - type: custom:boilerplate-card - name: Boilerplate Card Development - entity: sun.sun - test_gui: true + - type: custom:kanji-clock-card + use_24h: false + short_weekdays: false + kanji_numbers: false diff --git a/README.md b/README.md index 81a1626..948c136 100644 --- a/README.md +++ b/README.md @@ -1,119 +1,42 @@ -# Boilerplate Card by [@iantrich](https://www.github.com/iantrich) - -A community driven boilerplate of best practices for Home Assistant Lovelace custom cards +# Kanji Clock Card by [@sopelj](https://www.github.com/sopelj) [![GitHub Release][releases-shield]][releases] [![License][license-shield]](LICENSE.md) [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg?style=for-the-badge)](https://github.com/custom-components/hacs) - ![Project Maintenance][maintenance-shield] [![GitHub Activity][commits-shield]][commits] -[![Discord][discord-shield]][discord] -[![Community Forum][forum-shield]][forum] - -## Support +A simple clock widget using Japanese Kanji for time and date -Hey dude! Help me out for a couple of :beers: or a :coffee:! +*Please ⭐️ this repo if you find it useful* -[![coffee](https://www.buymeacoffee.com/assets/img/custom_images/black_img.png)](https://www.buymeacoffee.com/zJtVxUAgH) +![12h](./images/12h.png) +![12h Kanji](./images/12h-kanji.png) ## Options -| Name | Type | Requirement | Description | Default | -| ----------------- | ------- | ------------ | ------------------------------------------- | ------------------- | -| type | string | **Required** | `custom:boilerplate-card` | -| name | string | **Optional** | Card name | `Boilerplate` | -| show_error | boolean | **Optional** | Show what an error looks like for the card | `false` | -| show_warning | boolean | **Optional** | Show what a warning looks like for the card | `false` | -| entity | string | **Optional** | Home Assistant entity ID. | `none` | -| tap_action | object | **Optional** | Action to take on tap | `action: more-info` | -| hold_action | object | **Optional** | Action to take on hold | `none` | -| double_tap_action | object | **Optional** | Action to take on hold | `none` | - -## Action Options - -| Name | Type | Requirement | Description | Default | -| --------------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| action | string | **Required** | Action to perform (more-info, toggle, call-service, navigate url, none) | `more-info` | -| navigation_path | string | **Optional** | Path to navigate to (e.g. /lovelace/0/) when action defined as navigate | `none` | -| url | string | **Optional** | URL to open on click when action is url. The URL will open in a new tab | `none` | -| service | string | **Optional** | Service to call (e.g. media_player.media_play_pause) when action defined as call-service | `none` | -| service_data | object | **Optional** | Service data to include (e.g. entity_id: media_player.bedroom) when action defined as call-service | `none` | -| haptic | string | **Optional** | Haptic feedback for the [Beta IOS App](http://home-assistant.io/ios/beta) _success, warning, failure, light, medium, heavy, selection_ | `none` | -| repeat | number | **Optional** | How often to repeat the `hold_action` in milliseconds. | `non` | - -## Starting a new card from boilerplate-card - -### Step 1 - -Clone this repository - -### Step 2 - -Install necessary modules (verified to work in node 8.x) -`yarn install` or `npm install` - - -### Step 3 +| Name | Type | Requirement | Description | Default | +| ----------------- | ------- | ------------ | ------------------------------------------- | ------------- | +| type | string | **Required** | `custom:kanji-clock-card` | | +| use_24h | boolean | **Optional** | Use 24 hour clock | `false` | +| short_weekdays | boolean | **Optional** | Abbreviate weekdays to single kanji | `false` | +| kanji_numbers | boolean | **Optional** | Convert numbers to kanji | `false` | -Do a test lint & build on the project. You can see available scripts in the package.json -`npm run build` - -### Step 4 - -Search the repository for all instances of "TODO" and handle the changes/suggestions - -### Step 5 - -Customize to suit your needs and contribute it back to the community - - -## Starting a new card from boilerplate-card with [devcontainer][devcontainer] - -Note: this is available only in vscode ensure you have the [Remote Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension installed. - -1. Fork and clone the repository. -2. Open a [devcontainer][devcontainer] terminal and run `npm start` when it's ready. -3. The compiled `.js` file will be accessible on - `http://127.0.0.1:5000/boilerplate-card.js`. -4. On a running Home Assistant installation add this to your Lovelace - `resources:` +## Installation with Hacs ```yaml -- url: "http://127.0.0.1:5000/boilerplate-card.js" +- url: "lovelace-kanji-clock-card/kanji-clock-card.js" type: module ``` -_Change "127.0.0.1" to the IP of your development machine._ - -### Bonus +## Credits -If you need a fresh test instance you can install a fresh Home Assistant instance inside the devcontainer as well. - -1. Run the command `dc start`. -2. Home Assistant will install and will eventually be running on port `9123` - -## [Troubleshooting](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins) -NB This will not work with node 9.x if you see the following errors try installing node 8.10.0 -```yarn install -yarn install v1.3.2 -[1/4] πŸ” Resolving packages... -warning rollup-plugin-commonjs@10.1.0: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-commonjs. -[2/4] 🚚 Fetching packages... -error @typescript-eslint/eslint-plugin@2.6.0: The engine "node" is incompatible with this module. Expected version "^8.10.0 || ^10.13.0 || >=11.10.1". -error Found incompatible module -info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command. -``` +This was created using the [Boilerplate Card](https://github.com/custom-cards/boilerplate-card) by [@iantrich](https://www.github.com/iantrich) -[commits-shield]: https://img.shields.io/github/commit-activity/y/custom-cards/boilerplate-card.svg?style=for-the-badge -[commits]: https://github.com/custom-cards/boilerplate-card/commits/master -[devcontainer]: https://code.visualstudio.com/docs/remote/containers -[discord]: https://discord.gg/5e9yvq -[discord-shield]: https://img.shields.io/discord/330944238910963714.svg?style=for-the-badge -[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg?style=for-the-badge +[commits-shield]: https://img.shields.io/github/commit-activity/y/sopelj/lovelace-kanji-clock-card.svg?style=for-the-badge +[commits]: https://github.com/sopelj/lovelace-kanji-clock-card/commits/master [forum]: https://community.home-assistant.io/c/projects/frontend -[license-shield]: https://img.shields.io/github/license/custom-cards/boilerplate-card.svg?style=for-the-badge -[maintenance-shield]: https://img.shields.io/maintenance/yes/2019.svg?style=for-the-badge -[releases-shield]: https://img.shields.io/github/release/custom-cards/boilerplate-card.svg?style=for-the-badge -[releases]: https://github.com/custom-cards/boilerplate-card/releases +[license-shield]: https://img.shields.io/github/license/sopelj/lovelace-kanji-clock-card.svg?style=for-the-badge +[maintenance-shield]: https://img.shields.io/maintenance/yes/2020.svg?style=for-the-badge +[releases-shield]: https://img.shields.io/github/release/sopelj/lovelace-kanji-clock-card.svg?style=for-the-badge +[releases]: https://github.com/sopelj/lovelace-kanji-clock-card/releases diff --git a/hacs.json b/hacs.json index 6f4c662..d0c7f6c 100644 --- a/hacs.json +++ b/hacs.json @@ -1,5 +1,5 @@ { - "name": "Boilerplate Card", + "name": "Kanji Clock Card", "render_readme": true, - "filename": "boilerplate-card.js" + "filename": "kanji-clock-card.js" } diff --git a/images/12h-kanji.png b/images/12h-kanji.png new file mode 100644 index 0000000000000000000000000000000000000000..218e92166857e944f57d052bff0b620ebc0eb53d GIT binary patch literal 10078 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 AVE_OC literal 0 HcmV?d00001 diff --git a/images/12h.png b/images/12h.png new file mode 100644 index 0000000000000000000000000000000000000000..fa24c42c56ca12df4f15a12ee7b48c89c29872ac GIT binary patch literal 11617 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 E4?F{lX#fBK literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 46bafe5..9e9247a 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,29 @@ { - "name": "boilerplate-card", - "version": "1.1.9", - "description": "Lovelace boilerplate-card", + "name": "kanji-clock-card", + "version": "0.0.1", + "description": "Lovelace kanji-clock-card", "keywords": [ "home-assistant", "homeassistant", "hass", - "automation", "lovelace", + "kanji", + "clock", "custom-cards" ], - "module": "boilerplate-card.js", - "repository": "git@github.com:custom_cards/boilerplate-card.git", - "author": "Ian Richardson ", + "module": "kanji-clock-card.js", + "repository": { + "type": "git", + "url": "git+https://github.com/sopelj/lovelace-kanji-clock-card.git" + }, + "bugs": { + "url": "https://github.com/sopelj/lovelace-kanji-clock-card/issues" + }, + "homepage": "https://github.com/sopelj/lovelace-kanji-clock-card#readme", + "author": "Jesse Sopel ", "license": "MIT", "dependencies": { "custom-card-helpers": "^1.6.3", - "home-assistant-js-websocket": "^4.4.0", "lit-element": "^2.2.1", "lit-html": "^1.1.2" }, @@ -34,6 +41,8 @@ "eslint-plugin-prettier": "^3.1.1", "prettier": "^1.19.1", "rollup": "^1.26.0", + "minimist": "^1.2.3", + "serialize-javascript": "^3.1.0", "rollup-plugin-babel": "^4.3.3", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", diff --git a/rollup.config.js b/rollup.config.js index 5586c3c..472b0d4 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -32,7 +32,7 @@ const plugins = [ export default [ { - input: 'src/boilerplate-card.ts', + input: 'src/kanji-clock-card.ts', output: { dir: 'dist', format: 'es', diff --git a/src/action-handler-directive.ts b/src/action-handler-directive.ts deleted file mode 100644 index c6926c5..0000000 --- a/src/action-handler-directive.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { directive, PropertyPart } from 'lit-html'; - -import { ActionHandlerDetail, ActionHandlerOptions } from 'custom-card-helpers/dist/types'; -import { fireEvent } from 'custom-card-helpers'; - -const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; - -interface ActionHandler extends HTMLElement { - holdTime: number; - bind(element: Element, options): void; -} -interface ActionHandlerElement extends HTMLElement { - actionHandler?: boolean; -} - -declare global { - interface HASSDomEvents { - action: ActionHandlerDetail; - } -} - -class ActionHandler extends HTMLElement implements ActionHandler { - public holdTime = 500; - - public ripple: any; - - protected timer?: number; - - protected held = false; - - private dblClickTimeout?: number; - - constructor() { - super(); - this.ripple = document.createElement('mwc-ripple'); - } - - public connectedCallback(): void { - Object.assign(this.style, { - position: 'absolute', - width: isTouch ? '100px' : '50px', - height: isTouch ? '100px' : '50px', - transform: 'translate(-50%, -50%)', - pointerEvents: 'none', - zIndex: '999', - }); - - this.appendChild(this.ripple); - this.ripple.primary = true; - - ['touchcancel', 'mouseout', 'mouseup', 'touchmove', 'mousewheel', 'wheel', 'scroll'].forEach(ev => { - document.addEventListener( - ev, - () => { - clearTimeout(this.timer); - this.stopAnimation(); - this.timer = undefined; - }, - { passive: true }, - ); - }); - } - - public bind(element: ActionHandlerElement, options): void { - if (element.actionHandler) { - return; - } - element.actionHandler = true; - - element.addEventListener('contextmenu', (ev: Event) => { - const e = ev || window.event; - if (e.preventDefault) { - e.preventDefault(); - } - if (e.stopPropagation) { - e.stopPropagation(); - } - e.cancelBubble = true; - e.returnValue = false; - return false; - }); - - const start = (ev: Event): void => { - this.held = false; - let x; - let y; - if ((ev as TouchEvent).touches) { - x = (ev as TouchEvent).touches[0].pageX; - y = (ev as TouchEvent).touches[0].pageY; - } else { - x = (ev as MouseEvent).pageX; - y = (ev as MouseEvent).pageY; - } - - this.timer = window.setTimeout(() => { - this.startAnimation(x, y); - this.held = true; - }, this.holdTime); - }; - - const end = (ev: Event): void => { - // Prevent mouse event if touch event - ev.preventDefault(); - if (['touchend', 'touchcancel'].includes(ev.type) && this.timer === undefined) { - return; - } - clearTimeout(this.timer); - this.stopAnimation(); - this.timer = undefined; - if (this.held) { - fireEvent(element, 'action', { action: 'hold' }); - } else if (options.hasDoubleClick) { - if ((ev.type === 'click' && (ev as MouseEvent).detail < 2) || !this.dblClickTimeout) { - this.dblClickTimeout = window.setTimeout(() => { - this.dblClickTimeout = undefined; - fireEvent(element, 'action', { action: 'tap' }); - }, 250); - } else { - clearTimeout(this.dblClickTimeout); - this.dblClickTimeout = undefined; - fireEvent(element, 'action', { action: 'double_tap' }); - } - } else { - fireEvent(element, 'action', { action: 'tap' }); - } - }; - - const handleEnter = (ev: KeyboardEvent): void => { - if (ev.keyCode !== 13) { - return; - } - end(ev); - }; - - element.addEventListener('touchstart', start, { passive: true }); - element.addEventListener('touchend', end); - element.addEventListener('touchcancel', end); - - element.addEventListener('mousedown', start, { passive: true }); - element.addEventListener('click', end); - - element.addEventListener('keyup', handleEnter); - } - - private startAnimation(x: number, y: number): void { - Object.assign(this.style, { - left: `${x}px`, - top: `${y}px`, - display: null, - }); - this.ripple.disabled = false; - this.ripple.active = true; - this.ripple.unbounded = true; - } - - private stopAnimation(): void { - this.ripple.active = false; - this.ripple.disabled = true; - this.style.display = 'none'; - } -} - -// TODO You need to replace all instances of "action-handler-boilerplate" with "action-handler-" -customElements.define('action-handler-boilerplate', ActionHandler); - -const getActionHandler = (): ActionHandler => { - const body = document.body; - if (body.querySelector('action-handler-boilerplate')) { - return body.querySelector('action-handler-boilerplate') as ActionHandler; - } - - const actionhandler = document.createElement('action-handler-boilerplate'); - body.appendChild(actionhandler); - - return actionhandler as ActionHandler; -}; - -export const actionHandlerBind = (element: ActionHandlerElement, options: ActionHandlerOptions): void => { - const actionhandler: ActionHandler = getActionHandler(); - if (!actionhandler) { - return; - } - actionhandler.bind(element, options); -}; - -export const actionHandler = directive((options: ActionHandlerOptions = {}) => (part: PropertyPart): void => { - actionHandlerBind(part.committer.element as ActionHandlerElement, options); -}); diff --git a/src/boilerplate-card.ts b/src/boilerplate-card.ts deleted file mode 100644 index a7869de..0000000 --- a/src/boilerplate-card.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { LitElement, html, customElement, property, CSSResult, TemplateResult, css, PropertyValues } from 'lit-element'; -import { - HomeAssistant, - hasConfigOrEntityChanged, - hasAction, - ActionHandlerEvent, - handleAction, - LovelaceCardEditor, - getLovelace, - LovelaceCard, -} from 'custom-card-helpers'; - -import './editor'; - -import { BoilerplateCardConfig } from './types'; -import { actionHandler } from './action-handler-directive'; -import { CARD_VERSION } from './const'; - -import { localize } from './localize/localize'; - -/* eslint no-console: 0 */ -console.info( - `%c BOILERPLATE-CARD \n%c ${localize('common.version')} ${CARD_VERSION} `, - 'color: orange; font-weight: bold; background: black', - 'color: white; font-weight: bold; background: dimgray', -); - -(window as any).customCards = (window as any).customCards || []; -(window as any).customCards.push({ - type: 'boilerplate-card', - name: 'Boilerplate Card', - description: 'A template custom card for you to create something awesome', -}); - -// TODO Name your custom element -@customElement('boilerplate-card') -export class BoilerplateCard extends LitElement { - public static async getConfigElement(): Promise { - return document.createElement('boilerplate-card-editor') as LovelaceCardEditor; - } - - public static getStubConfig(): object { - return {}; - } - - // TODO Add any properities that should cause your element to re-render here - @property() public hass!: HomeAssistant; - @property() private _config!: BoilerplateCardConfig; - - public setConfig(config: BoilerplateCardConfig): void { - // TODO Check for required fields and that they are of the proper format - if (!config || config.show_error) { - throw new Error(localize('common.invalid_configuration')); - } - - if (config.test_gui) { - getLovelace().setEditMode(true); - } - - this._config = { - name: 'Boilerplate', - ...config, - }; - } - - protected shouldUpdate(changedProps: PropertyValues): boolean { - return hasConfigOrEntityChanged(this, changedProps, false); - } - - protected render(): TemplateResult | void { - // TODO Check for stateObj or other necessary things and render a warning if missing - if (this._config.show_warning) { - return this.showWarning(localize('common.show_warning')); - } - - return html` - - `; - } - - private _handleAction(ev: ActionHandlerEvent): void { - if (this.hass && this._config && ev.detail.action) { - handleAction(this, this.hass, this._config, ev.detail.action); - } - } - - private showWarning(warning: string): TemplateResult { - return html` - ${warning} - `; - } - - private showError(error: string): TemplateResult { - const errorCard = document.createElement('hui-error-card') as LovelaceCard; - errorCard.setConfig({ - type: 'error', - error, - origConfig: this._config, - }); - - return html` - ${errorCard} - `; - } - - static get styles(): CSSResult { - return css``; - } -} diff --git a/src/const.ts b/src/const.ts index 4c9062b..99d6752 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1 +1,4 @@ -export const CARD_VERSION = '1.1.7'; +export const CARD_VERSION = '0.0.1'; +export const KANJI_NUMBERS = 'ιœŠδΈ€δΊŒδΈ‰ε››δΊ”ε…­δΈƒε…«δΉ'; +export const KANJI_WEEKDAYS = 'ζ—₯ζœˆη«ζ°΄ζœ¨ι‡‘εœŸ'; +export const TENS = ['', '十', 'η™Ύ', '千']; diff --git a/src/editor.ts b/src/editor.ts deleted file mode 100644 index e5f568b..0000000 --- a/src/editor.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { LitElement, html, customElement, property, TemplateResult, CSSResult, css } from 'lit-element'; -import { HomeAssistant, fireEvent, LovelaceCardEditor, ActionConfig } from 'custom-card-helpers'; - -import { BoilerplateCardConfig } from './types'; - -const options = { - required: { - icon: 'tune', - name: 'Required', - secondary: 'Required options for this card to function', - show: true, - }, - actions: { - icon: 'gesture-tap-hold', - name: 'Actions', - secondary: 'Perform actions based on tapping/clicking', - show: false, - options: { - tap: { - icon: 'gesture-tap', - name: 'Tap', - secondary: 'Set the action to perform on tap', - show: false, - }, - hold: { - icon: 'gesture-tap-hold', - name: 'Hold', - secondary: 'Set the action to perform on hold', - show: false, - }, - double_tap: { - icon: 'gesture-double-tap', - name: 'Double Tap', - secondary: 'Set the action to perform on double tap', - show: false, - }, - }, - }, - appearance: { - icon: 'palette', - name: 'Appearance', - secondary: 'Customize the name, icon, etc', - show: false, - }, -}; - -@customElement('boilerplate-card-editor') -export class BoilerplateCardEditor extends LitElement implements LovelaceCardEditor { - @property() public hass?: HomeAssistant; - @property() private _config?: BoilerplateCardConfig; - @property() private _toggle?: boolean; - - public setConfig(config: BoilerplateCardConfig): void { - this._config = config; - } - - get _name(): string { - if (this._config) { - return this._config.name || ''; - } - - return ''; - } - - get _entity(): string { - if (this._config) { - return this._config.entity || ''; - } - - return ''; - } - - get _show_warning(): boolean { - if (this._config) { - return this._config.show_warning || false; - } - - return false; - } - - get _show_error(): boolean { - if (this._config) { - return this._config.show_error || false; - } - - return false; - } - - get _tap_action(): ActionConfig { - if (this._config) { - return this._config.tap_action || { action: 'more-info' }; - } - - return { action: 'more-info' }; - } - - get _hold_action(): ActionConfig { - if (this._config) { - return this._config.hold_action || { action: 'none' }; - } - - return { action: 'none' }; - } - - get _double_tap_action(): ActionConfig { - if (this._config) { - return this._config.double_tap_action || { action: 'none' }; - } - - return { action: 'none' }; - } - - protected render(): TemplateResult | void { - if (!this.hass) { - return html``; - } - - // You can restrict on domain type - const entities = Object.keys(this.hass.states).filter(eid => eid.substr(0, eid.indexOf('.')) === 'sun'); - - return html` -
-
-
- -
${options.required.name}
-
-
${options.required.secondary}
-
- ${options.required.show - ? html` -
- - - ${entities.map(entity => { - return html` - ${entity} - `; - })} - - -
- ` - : ''} -
-
- -
${options.actions.name}
-
-
${options.actions.secondary}
-
- ${options.actions.show - ? html` -
-
-
- -
${options.actions.options.tap.name}
-
-
${options.actions.options.tap.secondary}
-
- ${options.actions.options.tap.show - ? html` -
- Action Editors Coming Soon -
- ` - : ''} -
-
- -
${options.actions.options.hold.name}
-
-
${options.actions.options.hold.secondary}
-
- ${options.actions.options.hold.show - ? html` -
- Action Editors Coming Soon -
- ` - : ''} -
-
- -
${options.actions.options.double_tap.name}
-
-
${options.actions.options.double_tap.secondary}
-
- ${options.actions.options.double_tap.show - ? html` -
- Action Editors Coming Soon -
- ` - : ''} -
- ` - : ''} -
-
- -
${options.appearance.name}
-
-
${options.appearance.secondary}
-
- ${options.appearance.show - ? html` -
- -
- Show Warning? - Show Error? -
- ` - : ''} -
- `; - } - - private _toggleAction(ev): void { - this._toggleThing(ev, options.actions.options); - } - - private _toggleOption(ev): void { - this._toggleThing(ev, options); - } - - private _toggleThing(ev, optionList): void { - const show = !optionList[ev.target.option].show; - for (const [key] of Object.entries(optionList)) { - optionList[key].show = false; - } - optionList[ev.target.option].show = show; - this._toggle = !this._toggle; - } - - private _valueChanged(ev): void { - if (!this._config || !this.hass) { - return; - } - const target = ev.target; - if (this[`_${target.configValue}`] === target.value) { - return; - } - if (target.configValue) { - if (target.value === '') { - delete this._config[target.configValue]; - } else { - this._config = { - ...this._config, - [target.configValue]: target.checked !== undefined ? target.checked : target.value, - }; - } - } - fireEvent(this, 'config-changed', { config: this._config }); - } - - static get styles(): CSSResult { - return css` - .option { - padding: 4px 0px; - cursor: pointer; - } - .row { - display: flex; - margin-bottom: -14px; - pointer-events: none; - } - .title { - padding-left: 16px; - margin-top: -6px; - pointer-events: none; - } - .secondary { - padding-left: 40px; - color: var(--secondary-text-color); - pointer-events: none; - } - .values { - padding-left: 16px; - background: var(--secondary-background-color); - } - ha-switch { - padding-bottom: 8px; - } - `; - } -} diff --git a/src/kanji-clock-card.ts b/src/kanji-clock-card.ts new file mode 100644 index 0000000..ccfbca1 --- /dev/null +++ b/src/kanji-clock-card.ts @@ -0,0 +1,123 @@ +import { LitElement, html, customElement, property, CSSResult, TemplateResult, css } from 'lit-element'; +import { HomeAssistant } from 'custom-card-helpers'; + +import { KanjiClockCardConfig } from './types'; +import { KANJI_NUMBERS, KANJI_WEEKDAYS, TENS } from './const'; + +(window as Window).customCards = (window as Window).customCards || []; +(window as Window).customCards.push({ + type: 'kanji-clock-card', + name: 'Kanji Clock Card', + description: 'A simple clock widget using Japanese Kanji for time and date', +}); + +@customElement('kanji-clock-card') +export class KanjiClockCard extends LitElement { + private _handle = 0; + + @property() public hass!: HomeAssistant; + @property() private _config!: KanjiClockCardConfig; + + public connectedCallback(): void { + super.connectedCallback(); + this._handle = window.setInterval(this.requestUpdate.bind(this), 500); + } + + public disconnectedCallback(): void { + clearInterval(this._handle); + } + + public setConfig(config: KanjiClockCardConfig): void { + this._config = { + name: 'Kanji Clock', + ...config, + }; + } + + protected numberToKanji(number: number): string { + if (this._config.kanji_numbers !== true) { + return number.toString(); + } + + let output = ''; + const length = number.toString().length; + for (let i = length - 1; i >= 0; i--) { + const divisor = Math.pow(10, i); + const num = number % divisor; + const prefix = Math.floor(number / divisor); + if (prefix > 1 && prefix < 10) { + output += KANJI_NUMBERS[prefix]; + } + if (prefix > 0) { + output += TENS[i]; + } + if (num > 0 && num < 10) { + output += KANJI_NUMBERS[num]; + } + } + return output; + } + + protected render(): TemplateResult | void { + const date = new Date(); + let hours = date.getHours(); + const minutes = date.getMinutes(); + const day = this.numberToKanji(date.getDate()); + const year = this.numberToKanji(date.getFullYear()); + const month = this.numberToKanji(date.getMonth() + 1); + let pm = ''; + const weeksuffix = this._config.short_weekdays ? 'ζ›œζ—₯' : ''; + + if (this._config.use_24h !== true) { + if (hours > 12) { + hours -= 12; + } + pm = hours >= 12 ? 'εˆε‰' : '午後'; + } + + let minutesText; + if (this._config.use_24h !== true && minutes === 0) { + minutesText = ''; + } else if (minutes === 30) { + minutesText = '半'; + } else { + minutesText = `${this.numberToKanji(minutes)}εˆ†`; + } + + return html` + +
+
${pm}${this.numberToKanji(hours)}ζ™‚${minutesText}
+
+ ${day}ζ—₯${month}月${year}εΉ΄ (${KANJI_WEEKDAYS[date.getDay()]}${weeksuffix}) +
+
+
+ `; + } + + static get cardSize(): number { + return 3; + } + + static get styles(): CSSResult { + return css` + .content { + padding: 1rem; + text-align: center; + } + .time { + font-size: 3.2rem; + line-height: 1em; + font-weight: light; + } + .time span { + font-weight: lighter; + } + .date { + color: var(--primary-color); + font-size: var(--paper-font-headline_-_font-size); + } + `; + } +} diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json deleted file mode 100644 index d5440f5..0000000 --- a/src/localize/languages/en.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "common": { - "version": "Version", - "invalid_configuration": "Invalid configuration", - "show_warning": "Show Warning" - } -} diff --git a/src/localize/languages/nb.json b/src/localize/languages/nb.json deleted file mode 100644 index d8b7264..0000000 --- a/src/localize/languages/nb.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "common": { - "version": "Versjon", - "invalid_configuration": "Ikke gyldig konfiguration", - "show_warning": "Vis advarsel" - } -} diff --git a/src/localize/localize.ts b/src/localize/localize.ts deleted file mode 100644 index d1e4970..0000000 --- a/src/localize/localize.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as en from './languages/en.json'; -import * as nb from './languages/nb.json'; - -var languages: any = { - en: en, - nb: nb, -}; - -export function localize(string: string, search: string = '', replace: string = '') { - - const lang = (localStorage.getItem('selectedLanguage') || 'en').replace(/['"]+/g, '').replace('-', '_'); - - var translated: string; - - try { - translated = string.split('.').reduce((o, i) => o[i], languages[lang]); - } catch (e) { - translated = string.split('.').reduce((o, i) => o[i], languages['en']); - } - - if (translated === undefined) translated = string.split('.').reduce((o, i) => o[i], languages['en']); - - if (search !== '' && replace !== '') { - translated = translated.replace(search, replace); - } - return translated; -} diff --git a/src/types.ts b/src/types.ts index f6b9e30..d309c82 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,14 +1,14 @@ -import { ActionConfig, LovelaceCardConfig } from 'custom-card-helpers'; +import { LovelaceCardConfig } from 'custom-card-helpers'; -// TODO Add your configuration elements here for type-checking -export interface BoilerplateCardConfig extends LovelaceCardConfig { +export interface KanjiClockCardConfig extends LovelaceCardConfig { type: string; - name?: string; - show_warning?: boolean; - show_error?: boolean; - test_gui?: boolean; - entity?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; - double_tap_action?: ActionConfig; + use_24h?: boolean; + short_weekdays?: boolean; + kanji_numbers?: boolean; +} + +declare global { + interface Window { + customCards: Array; + } } diff --git a/yarn.lock b/yarn.lock index 96364f9..6e12c08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1359,6 +1359,11 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -1612,6 +1617,13 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" @@ -1768,6 +1780,11 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -1798,6 +1815,13 @@ serialize-javascript@^1.9.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== +serialize-javascript@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" + integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== + dependencies: + randombytes "^2.1.0" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"