mirror of
https://github.com/GeorgeSG/lovelace-time-picker-card.git
synced 2026-11-02 03:08:45 +00:00
Merge pull request #66 from bramkragten/ha-entity-names
Resolve entity names via hass.formatEntityName
This commit is contained in:
@@ -111,7 +111,7 @@ layout:
|
||||
| ----------------- | ------------ | ------------ | --------------------------------------------------------------------------------------------------------- | ------------------------ |
|
||||
| type | string | **Required** | `custom:time-picker-card` | |
|
||||
| entity | string | **Required** | [Input Datetime](https://www.home-assistant.io/integrations/input_datetime/) entity with `has_time: true` | |
|
||||
| name | string | **Optional** | Card name | Entity's `friendly_name` |
|
||||
| name | string / list | **Optional** | Card name. Accepts a [structured name](#structured-names) on Home Assistant 2026.4 and later. | Entity's name |
|
||||
| link_values | boolean | **Optional** | If enabled, will change hour when minutes overflow. E.g. will go from 11:55 to 12:00, instead of 11:00 | `false` |
|
||||
| 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` |
|
||||
@@ -156,6 +156,30 @@ you can use the following variables in your theme's config file:
|
||||
| time-picker-border-radius | `var(--ha-card-border-radius)` | Border radius of the card |
|
||||
| time-picker-control-padding | `8px` | Padding for interactive elements. Increase for larger hitboxes of the controls. Example: `10px 12px` |
|
||||
|
||||
### Structured names
|
||||
|
||||
*Requires Home Assistant 2026.4 or later. On earlier versions a structured `name` falls back to the entity's friendly name.*
|
||||
|
||||
Home Assistant composes an entity's display name out of its registry context
|
||||
(entity, device, area, floor) rather than one `friendly_name` string. `name` can
|
||||
be a list of those parts instead of a plain string, so it keeps following renames
|
||||
and matches what the built-in cards show:
|
||||
|
||||
```yaml
|
||||
type: custom:time-picker-card
|
||||
entity: input_datetime.alarm
|
||||
name:
|
||||
- type: area
|
||||
- type: entity
|
||||
```
|
||||
|
||||
Available part types are `entity`, `device`, `parent_device`, `area`, `floor`, and
|
||||
`text` (a literal, written as `{type: text, text: 'Alarm'}`). Parts that resolve to
|
||||
nothing are dropped. A plain string `name` keeps working exactly as before, and the
|
||||
visual editor offers both modes on Home Assistant 2025.11 and later.
|
||||
|
||||
See the [Home Assistant developer documentation](https://developers.home-assistant.io/docs/frontend/data#hassformatentitynamestateobj-name-options) for details.
|
||||
|
||||
## Meta
|
||||
|
||||
**Georgi Gardev**
|
||||
|
||||
+13
-6
@@ -1,4 +1,5 @@
|
||||
import { HomeAssistant, LovelaceCardEditor } from 'custom-card-helpers';
|
||||
import { supportsEntityNameSelector } from './entity-name';
|
||||
import { html, LitElement, TemplateResult } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { TimePickerCardConfig } from './types';
|
||||
@@ -17,12 +18,18 @@ const NAME_TO_LABEL_MAP = {
|
||||
seconds: 'Seconds',
|
||||
};
|
||||
|
||||
const SCHEMA = [
|
||||
type FormSchemaEntry = Record<string, unknown>;
|
||||
|
||||
// The entity_name selector, which lets users compose a name out of registry
|
||||
// parts, was added in HA 2025.11. Older versions fall back to a plain text field.
|
||||
const nameSchema = (hass: HomeAssistant): FormSchemaEntry =>
|
||||
supportsEntityNameSelector(hass)
|
||||
? { name: 'name', selector: { entity_name: {} }, context: { entity: 'entity' } }
|
||||
: { name: 'name', selector: { text: {} } };
|
||||
|
||||
const schema = (hass: HomeAssistant): FormSchemaEntry[] => [
|
||||
{ name: 'entity', selector: { entity: { domain: 'input_datetime' } } },
|
||||
{
|
||||
name: 'name',
|
||||
selector: { text: {} },
|
||||
},
|
||||
nameSchema(hass),
|
||||
{
|
||||
type: 'grid',
|
||||
schema: [
|
||||
@@ -135,7 +142,7 @@ export class TimePickerCardEditor extends LitElement implements LovelaceCardEdit
|
||||
<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this.config}
|
||||
.schema=${SCHEMA}
|
||||
.schema=${schema(this.hass)}
|
||||
.computeLabel=${this.computeLabel}
|
||||
@value-changed=${this.valueChanged}
|
||||
></ha-form>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { HomeAssistant } from 'custom-card-helpers';
|
||||
import { HassEntity } from 'home-assistant-js-websocket';
|
||||
import { EntityName } from './types';
|
||||
|
||||
// hass.formatEntityName only accepts a card's `name` option (a user string, a
|
||||
// structured name, or undefined) from HA 2026.4. Earlier versions expose the
|
||||
// same helper with an incompatible signature, so feature detection is not
|
||||
// enough - the version has to be checked.
|
||||
function atLeastVersion(hass: HomeAssistant, major: number, minor: number): boolean {
|
||||
const [haMajor, haMinor] = (hass.config?.version ?? '').split('.', 2);
|
||||
return Number(haMajor) > major || (Number(haMajor) === major && Number(haMinor) >= minor);
|
||||
}
|
||||
|
||||
function supportsEntityNames(hass: HomeAssistant): boolean {
|
||||
// A hass can report a recent version without carrying the helper (a test
|
||||
// harness, or a hass that has not finished initialising), and calling it
|
||||
// then throws - so the version gate alone is not enough.
|
||||
if (!hass || typeof (hass as { formatEntityName?: unknown }).formatEntityName !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return atLeastVersion(hass, 2026, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* The `entity_name` selector, which lets users compose a name out of registry
|
||||
* parts in the visual editor, was added in HA 2025.11.
|
||||
*/
|
||||
export function supportsEntityNameSelector(hass: HomeAssistant): boolean {
|
||||
return atLeastVersion(hass, 2025, 11);
|
||||
}
|
||||
|
||||
type HassWithEntityNames = HomeAssistant & {
|
||||
formatEntityName: (stateObj: HassEntity, name: EntityName | undefined) => string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolves a `name` option against the entity's registry context (entity,
|
||||
* device, area, floor). Falls back to the friendly name on Home Assistant
|
||||
* versions that cannot resolve a structured name.
|
||||
*/
|
||||
export function computeEntityName(
|
||||
hass: HomeAssistant,
|
||||
stateObj: HassEntity | undefined,
|
||||
name: EntityName | undefined
|
||||
): string | undefined {
|
||||
const configuredName = typeof name === 'string' ? name : undefined;
|
||||
|
||||
if (!stateObj) {
|
||||
return configuredName;
|
||||
}
|
||||
if (supportsEntityNames(hass)) {
|
||||
return (hass as HassWithEntityNames).formatEntityName(stateObj, name);
|
||||
}
|
||||
return configuredName ?? stateObj.attributes.friendly_name;
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { css, CSSResult, html, LitElement, TemplateResult } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { ClassInfo, classMap } from 'lit/directives/class-map.js';
|
||||
import { actionHandler } from './action-handler-directive';
|
||||
import { computeEntityName } from './entity-name';
|
||||
import './components/time-period.component';
|
||||
import './components/time-unit.component';
|
||||
import {
|
||||
@@ -79,7 +80,7 @@ export class TimePickerCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
private get name(): string | undefined {
|
||||
return this.config.name || this.entity?.attributes.friendly_name;
|
||||
return computeEntityName(this.hass, this.entity, this.config.name);
|
||||
}
|
||||
|
||||
private get shouldShowPeriod(): boolean {
|
||||
|
||||
+8
-1
@@ -2,7 +2,7 @@ import { ActionConfig, LovelaceCardConfig } from 'custom-card-helpers';
|
||||
|
||||
export interface TimePickerCardConfig extends LovelaceCardConfig {
|
||||
entity: string;
|
||||
name?: string;
|
||||
name?: EntityName;
|
||||
link_values?: boolean;
|
||||
hour_mode?: HourMode;
|
||||
hour_step?: number;
|
||||
@@ -16,6 +16,13 @@ export interface TimePickerCardConfig extends LovelaceCardConfig {
|
||||
hold_action?: ActionConfig;
|
||||
}
|
||||
|
||||
/** A `name` option: a plain string, or name parts resolved from the registry. */
|
||||
export type EntityName = string | EntityNameItem | EntityNameItem[];
|
||||
|
||||
export type EntityNameItem =
|
||||
| { type: 'entity' | 'device' | 'parent_device' | 'area' | 'floor' }
|
||||
| { type: 'text'; text: string };
|
||||
|
||||
export type HourMode = 12 | 24 | undefined;
|
||||
|
||||
export interface TimePickerLayoutConfig {
|
||||
|
||||
Reference in New Issue
Block a user