mirror of
https://github.com/home-assistant/frontend.git
synced 2026-05-01 15:03:05 +00:00
Compare commits
1 Commits
missing-to
...
clock-anal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d974635ca |
@@ -2,6 +2,8 @@ import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { resolveTimeZone } from "../../../../common/datetime/resolve-time-zone";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { ClockCardConfig } from "../types";
|
||||
@@ -26,6 +28,12 @@ function romanize12HourClock(num: number) {
|
||||
return numerals[num];
|
||||
}
|
||||
|
||||
const QUARTER_TICKS = [12, 3, 6, 9];
|
||||
|
||||
const ARRAY_QUARTER_TICKS = Array.from({ length: 4 }, (_, i) => i);
|
||||
const ARRAY_HOUR_TICKS = Array.from({ length: 12 }, (_, i) => i);
|
||||
const ARRAY_MINUTE_TICKS = Array.from({ length: 60 }, (_, i) => i);
|
||||
|
||||
@customElement("hui-clock-card-analog")
|
||||
export class HuiClockCardAnalog extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
@@ -113,23 +121,35 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
this._hourOffsetSec = hour12 * 3600 + minute * 60 + secondsWithMs;
|
||||
}
|
||||
|
||||
private _computeFaceStyle = memoizeOne((config: ClockCardConfig) => {
|
||||
const faceStyleParts = config?.face_style?.split("_");
|
||||
return {
|
||||
sizeClass: config?.clock_size ? `size-${config.clock_size}` : "",
|
||||
isFaceNumbers: faceStyleParts?.includes("numbers"),
|
||||
isFaceRoman: faceStyleParts?.includes("roman"),
|
||||
isFaceUpright: faceStyleParts?.includes("upright"),
|
||||
isFaceQuarter: faceStyleParts?.includes("quarter"),
|
||||
};
|
||||
});
|
||||
|
||||
render() {
|
||||
if (!this.config) return nothing;
|
||||
|
||||
const sizeClass = this.config.clock_size
|
||||
? `size-${this.config.clock_size}`
|
||||
: "";
|
||||
|
||||
const isNumbers = this.config?.face_style?.startsWith("numbers");
|
||||
const isRoman = this.config?.face_style?.startsWith("roman");
|
||||
const isUpright = this.config?.face_style?.endsWith("upright");
|
||||
const {
|
||||
sizeClass,
|
||||
isFaceNumbers,
|
||||
isFaceRoman,
|
||||
isFaceUpright,
|
||||
isFaceQuarter,
|
||||
} = this._computeFaceStyle(this.config);
|
||||
|
||||
const indicator = (number?: number) => html`
|
||||
<div
|
||||
class=${classMap({
|
||||
line: true,
|
||||
numbers: isNumbers,
|
||||
roman: isRoman,
|
||||
numbers: isFaceNumbers,
|
||||
roman: isFaceRoman,
|
||||
quarter: isFaceQuarter,
|
||||
})}
|
||||
>
|
||||
${number && this.config?.face_style !== "markers"
|
||||
@@ -137,12 +157,12 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
class=${classMap({
|
||||
number: true,
|
||||
[this.config?.clock_size ?? ""]: true,
|
||||
upright: isUpright,
|
||||
upright: isFaceUpright,
|
||||
})}
|
||||
>
|
||||
${isRoman
|
||||
${isFaceRoman
|
||||
? romanize12HourClock(number)
|
||||
: isNumbers
|
||||
: isFaceNumbers
|
||||
? number
|
||||
: nothing}
|
||||
</div>`
|
||||
@@ -163,43 +183,52 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
})}
|
||||
>
|
||||
${this.config.ticks === "quarter"
|
||||
? Array.from({ length: 4 }, (_, i) => i).map(
|
||||
? ARRAY_QUARTER_TICKS.map(
|
||||
(i) =>
|
||||
// 4 ticks (12, 3, 6, 9) at 0°, 90°, 180°, 270°
|
||||
html`
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="tick hour"
|
||||
style=${`--tick-rotation: ${i * 90}deg;`}
|
||||
style=${styleMap({ "--tick-rotation": `${i * 90}deg` })}
|
||||
>
|
||||
${indicator([12, 3, 6, 9][i])}
|
||||
${indicator(QUARTER_TICKS[i])}
|
||||
</div>
|
||||
`
|
||||
)
|
||||
: !this.config.ticks || // Default to hour ticks
|
||||
this.config.ticks === "hour"
|
||||
? Array.from({ length: 12 }, (_, i) => i).map(
|
||||
? ARRAY_HOUR_TICKS.map(
|
||||
(i) =>
|
||||
// 12 ticks (1-12)
|
||||
html`
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="tick hour"
|
||||
style=${`--tick-rotation: ${i * 30}deg;`}
|
||||
style=${styleMap({ "--tick-rotation": `${i * 30}deg` })}
|
||||
>
|
||||
${indicator(((i + 11) % 12) + 1)}
|
||||
${isFaceQuarter
|
||||
? QUARTER_TICKS.includes(((i + 11) % 12) + 1)
|
||||
? indicator(((i + 11) % 12) + 1)
|
||||
: nothing
|
||||
: indicator(((i + 11) % 12) + 1)}
|
||||
</div>
|
||||
`
|
||||
)
|
||||
: this.config.ticks === "minute"
|
||||
? Array.from({ length: 60 }, (_, i) => i).map(
|
||||
? ARRAY_MINUTE_TICKS.map(
|
||||
(i) =>
|
||||
// 60 ticks (1-60)
|
||||
html`
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="tick ${i % 5 === 0 ? "hour" : "minute"}"
|
||||
style=${`--tick-rotation: ${i * 6}deg;`}
|
||||
class=${classMap({
|
||||
tick: true,
|
||||
[i % 5 === 0 ? "hour" : "minute"]: true,
|
||||
})}
|
||||
style=${styleMap({
|
||||
"--tick-rotation": `${i * 6}deg`,
|
||||
})}
|
||||
>
|
||||
${i % 5 === 0
|
||||
? indicator(((i / 5 + 11) % 12) + 1)
|
||||
@@ -211,11 +240,15 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
<div class="center-dot"></div>
|
||||
<div
|
||||
class="hand hour"
|
||||
style=${`animation-delay: -${this._hourOffsetSec ?? 0}s;`}
|
||||
style=${styleMap({
|
||||
"animation-delay": `-${this._hourOffsetSec ?? 0}s`,
|
||||
})}
|
||||
></div>
|
||||
<div
|
||||
class="hand minute"
|
||||
style=${`animation-delay: -${this._minuteOffsetSec ?? 0}s;`}
|
||||
style=${styleMap({
|
||||
"animation-delay": `-${this._minuteOffsetSec ?? 0}s`,
|
||||
})}
|
||||
></div>
|
||||
${this.config.show_seconds
|
||||
? html`<div
|
||||
@@ -224,11 +257,13 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
second: true,
|
||||
step: this.config.seconds_motion === "tick",
|
||||
})}
|
||||
style=${`animation-delay: -${
|
||||
(this.config.seconds_motion === "tick"
|
||||
? Math.floor(this._secondOffsetSec ?? 0)
|
||||
: (this._secondOffsetSec ?? 0)) as number
|
||||
}s;`}
|
||||
style=${styleMap({
|
||||
"animation-delay": `-${
|
||||
(this.config.seconds_motion === "tick"
|
||||
? Math.floor(this._secondOffsetSec ?? 0)
|
||||
: (this._secondOffsetSec ?? 0)) as number
|
||||
}s`,
|
||||
})}
|
||||
></div>`
|
||||
: nothing}
|
||||
</div>
|
||||
|
||||
@@ -420,7 +420,12 @@ export interface ClockCardConfig extends LovelaceCardConfig {
|
||||
// Analog clock options
|
||||
border?: boolean;
|
||||
ticks?: "none" | "quarter" | "hour" | "minute";
|
||||
face_style?: "markers" | "numbers_upright" | "roman";
|
||||
face_style?:
|
||||
| "markers"
|
||||
| "numbers_upright"
|
||||
| "numbers_upright_quarter"
|
||||
| "roman"
|
||||
| "roman_quarter";
|
||||
}
|
||||
|
||||
export interface MediaControlCardConfig extends LovelaceCardConfig {
|
||||
|
||||
@@ -63,7 +63,9 @@ const cardConfigStruct = assign(
|
||||
union([
|
||||
literal("markers"),
|
||||
literal("numbers_upright"),
|
||||
literal("numbers_upright_quarter"),
|
||||
literal("roman"),
|
||||
literal("roman_quarter"),
|
||||
]),
|
||||
literal("markers")
|
||||
)
|
||||
@@ -220,7 +222,9 @@ export class HuiClockCardEditor
|
||||
options: [
|
||||
"markers",
|
||||
"numbers_upright",
|
||||
"numbers_upright_quarter",
|
||||
"roman",
|
||||
"roman_quarter",
|
||||
].map((value) => ({
|
||||
value,
|
||||
label: localize(
|
||||
|
||||
@@ -8271,9 +8271,17 @@
|
||||
"label": "Numbers",
|
||||
"description": "Show numbers around the clock face"
|
||||
},
|
||||
"numbers_upright_quarter": {
|
||||
"label": "Numbers upright quarter",
|
||||
"description": "Show numbers around the clock with quarter marks"
|
||||
},
|
||||
"roman": {
|
||||
"label": "Roman numerals",
|
||||
"description": "Show Roman numerals (I-XII) around the clock face"
|
||||
},
|
||||
"roman_quarter": {
|
||||
"label": "Roman numerals quarter",
|
||||
"description": "Show Roman numerals (I-XII) around the clock with quarter marks"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user