(() => { var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res, err) => function __init() { if (err) throw err[0]; try { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; } catch (e) { throw err = [e], e; } }; var __commonJS = (cb, mod) => function __require() { try { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; } catch (e) { throw mod = 0, e; } }; // src/config/normalize.js function normalizeResolvableValue(value, entityValue, percentValue = null) { const normalized = { fixed: value != null ? value : null, entity: entityValue != null ? entityValue : null }; if (Number.isFinite(percentValue)) { normalized.percent = percentValue; } return normalized; } function looksLikeEntityId(value) { return typeof value === "string" && /^[a-z0-9_]+\.[a-z0-9_]+$/i.test(value.trim()); } function parsePercentLiteral(value) { if (typeof value !== "string") return null; const match = value.match(/^\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*%\s*$/); if (!match) return null; const percent = parseFloat(match[1]); return Number.isFinite(percent) ? percent : null; } function getFiniteNumber(value) { if (typeof value === "number") { return Number.isFinite(value) ? value : null; } if (typeof value === "string") { const trimmed = value.trim(); if (!trimmed) return null; const num = Number(trimmed); return Number.isFinite(num) ? num : null; } return null; } function normalizeStructuredResolvableValue(input, inheritedResolvable = null, defaultValue = null, options = {}) { var _a, _b, _c, _d, _e, _f; const { allowPercent = false } = options; const inherited = inheritedResolvable != null ? inheritedResolvable : normalizeResolvableValue(defaultValue, null); if (input === void 0) { return { ...inherited }; } if (input === null) { return normalizeResolvableValue(null, null); } if (typeof input === "object" && !Array.isArray(input)) { const value = (_b = (_a = input.fixed) != null ? _a : input.value) != null ? _b : null; const entity = (_c = input.entity) != null ? _c : null; const percent = allowPercent ? getFiniteNumber(input.percent) : null; return normalizeResolvableValue(value, entity, percent); } if (looksLikeEntityId(input)) { return normalizeResolvableValue( (_e = (_d = inherited.fixed) != null ? _d : defaultValue) != null ? _e : null, input, (_f = inherited.percent) != null ? _f : null ); } if (allowPercent) { const percent = parsePercentLiteral(input); if (Number.isFinite(percent)) { return normalizeResolvableValue(null, null, percent); } } return normalizeResolvableValue(input, null); } function normalizeBaselineDirectionConfig(input, inheritedDirection = null) { var _a; const inherited = inheritedDirection != null ? inheritedDirection : { color: null }; if (input === void 0) { return { ...inherited }; } if (input === null) { return { color: null }; } if (typeof input === "object" && !Array.isArray(input)) { return { color: (_a = input.color) != null ? _a : null }; } return { color: input }; } function normalizeOptionalEnabled(value) { return value === true ? true : value === false ? false : null; } function normalizeBaselineConfig(entityConfig, cardConfig) { var _a; const cardBaseline = cardConfig == null ? void 0 : cardConfig.baseline; const rawBaseline = entityConfig == null ? void 0 : entityConfig.baseline; const inherited = { enabled: normalizeOptionalEnabled(cardBaseline == null ? void 0 : cardBaseline.enabled), at: (cardBaseline == null ? void 0 : cardBaseline.at) ? { ...cardBaseline.at } : normalizeResolvableValue(null, null), above: normalizeBaselineDirectionConfig(void 0, cardBaseline == null ? void 0 : cardBaseline.above), below: normalizeBaselineDirectionConfig(void 0, cardBaseline == null ? void 0 : cardBaseline.below) }; if (rawBaseline === void 0) { return inherited; } if (rawBaseline === null) { return { enabled: null, at: normalizeResolvableValue(null, null), above: { color: null }, below: { color: null } }; } if (typeof rawBaseline !== "object" || Array.isArray(rawBaseline)) { return { enabled: inherited.enabled, at: normalizeStructuredResolvableValue(rawBaseline, inherited.at, null), above: inherited.above, below: inherited.below }; } return { enabled: (_a = normalizeOptionalEnabled(rawBaseline.enabled)) != null ? _a : inherited.enabled, at: normalizeStructuredResolvableValue(rawBaseline.at, inherited.at, null, { allowPercent: true }), above: normalizeBaselineDirectionConfig(rawBaseline.above, inherited.above), below: normalizeBaselineDirectionConfig(rawBaseline.below, inherited.below) }; } function inferSegmentEndValues(segments, fallbackEnd = null) { const sorted = [...segments].sort((a, b) => a.from - b.from); return sorted.map((segment, index) => { var _a; let to = Number.isFinite(segment.to) ? segment.to : null; if (!Number.isFinite(to) && index < sorted.length - 1) { to = sorted[index + 1].from; } if (!Number.isFinite(to) && Number.isFinite(fallbackEnd)) { to = fallbackEnd; } return { from: segment.from, to, color: segment.color, label: (_a = segment.label) != null ? _a : null }; }); } function normalizeSeverityToSegments(input) { if (!Array.isArray(input)) return null; const segments = input.filter((segment) => Number.isFinite(segment == null ? void 0 : segment.from) && (segment == null ? void 0 : segment.color)).map((segment) => { var _a; return { from: segment.from, to: Number.isFinite(segment == null ? void 0 : segment.to) ? segment.to : null, color: segment.color, label: (_a = segment.label) != null ? _a : null }; }); return inferSegmentEndValues(segments, 100); } function hasResolvableMagnitude(resolvable) { return !!resolvable && (Number.isFinite(getFiniteNumber(resolvable.fixed)) || Number.isFinite(resolvable.percent)); } function normalizeGaugeSegments(input) { if (!Array.isArray(input)) return null; const segments = input.map((segment) => { var _a; const from = normalizeStructuredResolvableValue(segment == null ? void 0 : segment.from, null, null, { allowPercent: true }); const to = (segment == null ? void 0 : segment.to) === void 0 ? null : normalizeStructuredResolvableValue(segment.to, null, null, { allowPercent: true }); if (!hasResolvableMagnitude(from) || !(segment == null ? void 0 : segment.color)) { return null; } return { from, to, color: segment.color, label: (_a = segment.label) != null ? _a : null }; }).filter(Boolean); return segments.map((segment, index) => { var _a; return { from: { ...segment.from }, to: segment.to ? { ...segment.to } : index < segments.length - 1 ? { ...segments[index + 1].from } : null, color: segment.color, label: (_a = segment.label) != null ? _a : null }; }); } function normalizeScaleBound(entityConfig, cardConfig, key, defaultValue) { var _a, _b, _c, _d, _e, _f, _g, _h; const cardScale = cardConfig == null ? void 0 : cardConfig.scale; const entityScale = entityConfig == null ? void 0 : entityConfig.scale; const entityKey = `${key}_entity`; const cardBound = cardScale == null ? void 0 : cardScale[key]; const inherited = cardBound ? normalizeResolvableValue( (_b = (_a = cardBound.fixed) != null ? _a : cardBound.value) != null ? _b : null, (_c = cardBound.entity) != null ? _c : null ) : normalizeResolvableValue( (_d = cardConfig == null ? void 0 : cardConfig[key]) != null ? _d : defaultValue, (_e = cardConfig == null ? void 0 : cardConfig[entityKey]) != null ? _e : null ); if ((entityScale == null ? void 0 : entityScale[key]) !== void 0) { return normalizeStructuredResolvableValue( entityScale[key], inherited, defaultValue ); } const entityOverride = entityConfig[entityKey]; const hasEntityOverride = entityOverride !== void 0 && entityOverride !== null; const value = (_g = (_f = entityConfig[key]) != null ? _f : hasEntityOverride ? null : inherited.fixed) != null ? _g : inherited.entity ? null : defaultValue; const entity = (_h = entityOverride != null ? entityOverride : inherited.entity) != null ? _h : null; return normalizeResolvableValue(value, entity); } function normalizeScaleConfig(entityConfig, cardConfig) { return { min: normalizeScaleBound(entityConfig, cardConfig, "min", 0), max: normalizeScaleBound(entityConfig, cardConfig, "max", 100) }; } function fillStyleToColorMode(fillStyle) { switch (fillStyle) { case "solid": return "single"; case "gradient": return "gradient"; case "bands": return "severity"; case "soft_bands": return "severity"; case "band_gradient": return "severity_gradient"; default: return null; } } function colorModeToFillStyle(colorMode) { switch (colorMode) { case "single": return "solid"; case "gradient": return "gradient"; case "severity": return "bands"; case "severity_gradient": return "band_gradient"; default: return null; } } function normalizeBarModeConfig(barConfig = null, flatColorMode = null) { var _a, _b, _c, _d, _e, _f; const fillStyle = (_a = barConfig == null ? void 0 : barConfig.fill_style) != null ? _a : null; const colorMode = (_c = (_b = barConfig == null ? void 0 : barConfig.color_mode) != null ? _b : flatColorMode) != null ? _c : null; const normalizedColorMode = (_e = (_d = fillStyleToColorMode(fillStyle)) != null ? _d : colorMode) != null ? _e : "severity"; return { fill_style: (_f = fillStyle != null ? fillStyle : colorModeToFillStyle(normalizedColorMode)) != null ? _f : "bands", color_mode: normalizedColorMode }; } function resolveNormalizedBarMode(entityBar, entityConfig, cardBar, cardConfig) { if ((entityBar == null ? void 0 : entityBar.fill_style) !== void 0 || (entityBar == null ? void 0 : entityBar.color_mode) !== void 0 || entityConfig.color_mode !== void 0) { return normalizeBarModeConfig(entityBar, entityConfig.color_mode); } if ((cardBar == null ? void 0 : cardBar.fill_style) !== void 0 || (cardBar == null ? void 0 : cardBar.color_mode) !== void 0 || (cardConfig == null ? void 0 : cardConfig.color_mode) !== void 0) { return normalizeBarModeConfig(cardBar, cardConfig == null ? void 0 : cardConfig.color_mode); } return normalizeBarModeConfig(null, null); } function normalizeGradientStops(input) { if (!Array.isArray(input)) return input != null ? input : null; return input.map((stop) => { if (!stop || typeof stop !== "object" || Array.isArray(stop)) { return stop; } const percentPos = parsePercentLiteral(stop.pos); const numericPos = Number.isFinite(percentPos) ? percentPos : getFiniteNumber(stop.pos); return { ...stop, pos: Number.isFinite(numericPos) ? numericPos : stop.pos }; }); } function normalizeNeedleConfig(input, inheritedNeedle = null) { var _a, _b, _c, _d; const base = inheritedNeedle ? { show: (_a = inheritedNeedle.show) != null ? _a : false, color: (_b = inheritedNeedle.color) != null ? _b : "#ffffff" } : { show: false, color: "#ffffff" }; if (input === void 0) { return { ...base }; } if (typeof input === "boolean") { return { show: input, color: "#ffffff" }; } if (input && typeof input === "object" && !Array.isArray(input)) { return { show: (_c = input.show) != null ? _c : base.show, color: (_d = input.color) != null ? _d : base.color }; } return { ...base }; } function normalizeBarConfig(entityConfig, cardConfig) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y; const cardBar = cardConfig == null ? void 0 : cardConfig.bar; const entityBar = entityConfig == null ? void 0 : entityConfig.bar; const entityStructuredSegments = entityBar == null ? void 0 : entityBar.segments; const entityTopLevelSegments = entityConfig.segments; const entityLegacySeverity = entityConfig.severity; const cardStructuredSegments = (_a = cardBar == null ? void 0 : cardBar.segments) != null ? _a : null; const cardTopLevelSegments = (_b = cardConfig == null ? void 0 : cardConfig.segments) != null ? _b : null; const cardLegacySeverity = (_c = cardConfig == null ? void 0 : cardConfig.severity) != null ? _c : null; let segments = null; let segment_space = (_d = cardBar == null ? void 0 : cardBar.segment_space) != null ? _d : "percent"; if (entityStructuredSegments !== void 0 && entityStructuredSegments !== null) { segments = normalizeGaugeSegments(entityStructuredSegments); segment_space = "scale"; } else if (entityTopLevelSegments !== void 0 && entityTopLevelSegments !== null) { segments = normalizeGaugeSegments(entityTopLevelSegments); segment_space = "scale"; } else if (entityLegacySeverity !== void 0 && entityLegacySeverity !== null) { segments = normalizeSeverityToSegments(entityLegacySeverity); segment_space = "percent"; } else if (cardStructuredSegments !== null && cardStructuredSegments !== void 0) { segments = cardStructuredSegments.map((segment) => ({ ...segment })); segment_space = (_e = cardBar == null ? void 0 : cardBar.segment_space) != null ? _e : "percent"; } else if (cardTopLevelSegments !== null && cardTopLevelSegments !== void 0) { segments = normalizeGaugeSegments(cardTopLevelSegments); segment_space = "scale"; } else if (cardLegacySeverity !== null && cardLegacySeverity !== void 0) { segments = normalizeSeverityToSegments(cardLegacySeverity); segment_space = "percent"; } const structuredAboveTargetColor = (entityConfig == null ? void 0 : entityConfig.target) && typeof entityConfig.target === "object" && !Array.isArray(entityConfig.target) ? (_f = entityConfig.target.when_exceeded) == null ? void 0 : _f.fill_color : void 0; const inheritedStructuredAboveTargetColor = (cardConfig == null ? void 0 : cardConfig.target) && typeof cardConfig.target === "object" && !Array.isArray(cardConfig.target) ? (_g = cardConfig.target.when_exceeded) == null ? void 0 : _g.fill_color : void 0; const normalizedMode = resolveNormalizedBarMode(entityBar, entityConfig, cardBar, cardConfig); return { fill_style: normalizedMode.fill_style, color_mode: normalizedMode.color_mode, needle: normalizeNeedleConfig(entityBar == null ? void 0 : entityBar.needle, cardBar == null ? void 0 : cardBar.needle), solid_fill: (_i = (_h = entityBar == null ? void 0 : entityBar.solid_fill) != null ? _h : cardBar == null ? void 0 : cardBar.solid_fill) != null ? _i : false, color: (_m = (_l = (_k = (_j = entityBar == null ? void 0 : entityBar.color) != null ? _j : entityConfig.color) != null ? _k : cardBar == null ? void 0 : cardBar.color) != null ? _l : cardConfig == null ? void 0 : cardConfig.color) != null ? _m : "#4a9eff", gradient_stops: normalizeGradientStops( (_q = (_p = (_o = (_n = entityBar == null ? void 0 : entityBar.gradient_stops) != null ? _n : entityConfig.gradient_stops) != null ? _o : cardBar == null ? void 0 : cardBar.gradient_stops) != null ? _p : cardConfig == null ? void 0 : cardConfig.gradient_stops) != null ? _q : null ), severity: segments, segments, segment_space, animated: (_u = (_t = (_s = (_r = entityBar == null ? void 0 : entityBar.animated) != null ? _r : entityConfig.animated) != null ? _s : cardBar == null ? void 0 : cardBar.animated) != null ? _t : cardConfig == null ? void 0 : cardConfig.animated) != null ? _u : true, above_target_color: (_y = (_x = (_w = (_v = structuredAboveTargetColor != null ? structuredAboveTargetColor : entityConfig.above_target_color) != null ? _v : cardBar == null ? void 0 : cardBar.above_target_color) != null ? _w : inheritedStructuredAboveTargetColor) != null ? _x : cardConfig == null ? void 0 : cardConfig.above_target_color) != null ? _y : null }; } function clampSupportedRowHeight(height) { return Math.max(24, height); } function normalizeLabelPosition(position, fallback = "left") { const normalized = typeof position === "string" ? position.trim().toLowerCase() : ""; return ["left", "above", "inside", "off", "hero"].includes(normalized) ? normalized : fallback; } function normalizeHeroSize(size, fallback = "medium") { const normalized = typeof size === "string" ? size.trim().toLowerCase() : ""; return ["small", "medium", "large"].includes(normalized) ? normalized : fallback; } function normalizeHeroFontSize(value) { if (!Number.isFinite(value)) return null; return Math.min(112, Math.max(12, value)); } function normalizeLayoutConfig(entityConfig, cardConfig) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y; const cardLayout = cardConfig == null ? void 0 : cardConfig.layout; const entityLayout = entityConfig == null ? void 0 : entityConfig.layout; const entityLabel = entityLayout == null ? void 0 : entityLayout.label; const entityHero = entityLayout == null ? void 0 : entityLayout.hero; const cardLabel = cardLayout == null ? void 0 : cardLayout.label; const cardHero = cardLayout == null ? void 0 : cardLayout.hero; const isCardLevelNormalization = !cardConfig; const rawHeight = (_d = (_c = (_b = (_a = entityLayout == null ? void 0 : entityLayout.height) != null ? _a : entityConfig.height) != null ? _b : cardLayout == null ? void 0 : cardLayout.height) != null ? _c : cardConfig == null ? void 0 : cardConfig.height) != null ? _d : 38; const heightExplicit = (entityLayout == null ? void 0 : entityLayout.height) !== void 0 || entityConfig._height_explicit === true || !isCardLevelNormalization && entityConfig.height !== void 0 || (cardLayout == null ? void 0 : cardLayout.height_explicit) === true || (cardConfig == null ? void 0 : cardConfig._height_explicit) === true; const labelPosition = normalizeLabelPosition( (_h = (_g = (_f = (_e = entityLabel == null ? void 0 : entityLabel.position) != null ? _e : entityConfig.label_position) != null ? _f : cardLabel == null ? void 0 : cardLabel.position) != null ? _g : cardLayout == null ? void 0 : cardLayout.label_position) != null ? _h : cardConfig == null ? void 0 : cardConfig.label_position, "left" ); const heroFontSize = labelPosition === "hero" ? normalizeHeroFontSize((_i = entityHero == null ? void 0 : entityHero.value_size) != null ? _i : cardHero == null ? void 0 : cardHero.value_size) : null; return { label: { position: labelPosition, width: (_n = (_m = (_l = (_k = (_j = entityLabel == null ? void 0 : entityLabel.width) != null ? _j : entityConfig.label_width) != null ? _k : cardLabel == null ? void 0 : cardLabel.width) != null ? _l : cardLayout == null ? void 0 : cardLayout.label_width) != null ? _m : cardConfig == null ? void 0 : cardConfig.label_width) != null ? _n : 100 }, hero: { size: normalizeHeroSize( (_y = (_x = (_w = (_v = (_u = (_t = (_s = (_r = (_q = (_p = (_o = entityHero == null ? void 0 : entityHero.size) != null ? _o : entityLabel == null ? void 0 : entityLabel.hero_size) != null ? _p : entityLabel == null ? void 0 : entityLabel.heroSize) != null ? _q : entityConfig.hero_size) != null ? _r : entityConfig.heroSize) != null ? _s : cardHero == null ? void 0 : cardHero.size) != null ? _t : cardLabel == null ? void 0 : cardLabel.hero_size) != null ? _u : cardLabel == null ? void 0 : cardLabel.heroSize) != null ? _v : cardLayout == null ? void 0 : cardLayout.hero_size) != null ? _w : cardLayout == null ? void 0 : cardLayout.heroSize) != null ? _x : cardConfig == null ? void 0 : cardConfig.hero_size) != null ? _y : cardConfig == null ? void 0 : cardConfig.heroSize, "medium" ), value_size: heroFontSize }, height: clampSupportedRowHeight(rawHeight), height_explicit: heightExplicit }; } function normalizeFormattingConfig(entityConfig, cardConfig) { var _a, _b, _c, _d, _e, _f, _g, _h; const cardFormatting = cardConfig == null ? void 0 : cardConfig.formatting; const entityFormatting = entityConfig == null ? void 0 : entityConfig.formatting; return { decimal: (_d = (_c = (_b = (_a = entityFormatting == null ? void 0 : entityFormatting.decimal) != null ? _a : entityConfig.decimal) != null ? _b : cardFormatting == null ? void 0 : cardFormatting.decimal) != null ? _c : cardConfig == null ? void 0 : cardConfig.decimal) != null ? _d : null, unit: (_h = (_g = (_f = (_e = entityFormatting == null ? void 0 : entityFormatting.unit) != null ? _e : entityConfig.unit) != null ? _f : cardFormatting == null ? void 0 : cardFormatting.unit) != null ? _g : cardConfig == null ? void 0 : cardConfig.unit) != null ? _h : null }; } function normalizeTargetMarkerConfig(entityConfig, cardConfig) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B; const cardTarget = cardConfig == null ? void 0 : cardConfig.target_marker; const rawTarget = entityConfig == null ? void 0 : entityConfig.target; const legacyCardTarget = (cardConfig == null ? void 0 : cardConfig.target) && typeof cardConfig.target === "object" && !Array.isArray(cardConfig.target) ? null : (_a = cardConfig == null ? void 0 : cardConfig.target) != null ? _a : null; const inheritedTarget = cardTarget != null ? cardTarget : { enabled: null, source: normalizeResolvableValue(null, null), color: (_b = cardConfig == null ? void 0 : cardConfig.target_color) != null ? _b : "#888", show_label: (_c = cardConfig == null ? void 0 : cardConfig.show_target_label) != null ? _c : false }; if (rawTarget && typeof rawTarget === "object" && !Array.isArray(rawTarget)) { return { enabled: (_e = (_d = normalizeOptionalEnabled(rawTarget.enabled)) != null ? _d : inheritedTarget.enabled) != null ? _e : null, source: normalizeStructuredResolvableValue(rawTarget.at, inheritedTarget.source, null, { allowPercent: true }), color: (_g = (_f = rawTarget.color) != null ? _f : entityConfig.target_color) != null ? _g : inheritedTarget.color, show_label: (_j = (_i = (_h = rawTarget.label) == null ? void 0 : _h.show) != null ? _i : entityConfig.show_target_label) != null ? _j : inheritedTarget.show_label }; } const value = (_o = (_n = (_l = entityConfig.target) != null ? _l : (_k = inheritedTarget.source) == null ? void 0 : _k.fixed) != null ? _n : (_m = inheritedTarget.source) == null ? void 0 : _m.value) != null ? _o : legacyCardTarget; const entity = (_s = (_r = (_q = entityConfig.target_entity) != null ? _q : (_p = inheritedTarget.source) == null ? void 0 : _p.entity) != null ? _r : cardConfig == null ? void 0 : cardConfig.target_entity) != null ? _s : null; const percent = entityConfig.target === void 0 && entityConfig.target_entity === void 0 ? (_u = (_t = inheritedTarget.source) == null ? void 0 : _t.percent) != null ? _u : null : null; return { enabled: (_v = inheritedTarget.enabled) != null ? _v : null, source: normalizeResolvableValue(value, entity, percent), color: (_y = (_x = (_w = entityConfig.target_color) != null ? _w : inheritedTarget.color) != null ? _x : cardConfig == null ? void 0 : cardConfig.target_color) != null ? _y : "#888", show_label: (_B = (_A = (_z = entityConfig.show_target_label) != null ? _z : inheritedTarget.show_label) != null ? _A : cardConfig == null ? void 0 : cardConfig.show_target_label) != null ? _B : false }; } function normalizePeakMarkerConfig(entityConfig, cardConfig) { var _a, _b, _c, _d, _e, _f, _g, _h; const cardPeak = cardConfig == null ? void 0 : cardConfig.peak_marker; const entityPeak = entityConfig == null ? void 0 : entityConfig.peak; return { show: (_d = (_c = (_b = (_a = entityPeak == null ? void 0 : entityPeak.enabled) != null ? _a : entityConfig.show_peak) != null ? _b : cardPeak == null ? void 0 : cardPeak.show) != null ? _c : cardConfig == null ? void 0 : cardConfig.show_peak) != null ? _d : false, color: (_h = (_g = (_f = (_e = entityPeak == null ? void 0 : entityPeak.color) != null ? _e : entityConfig.peak_color) != null ? _f : cardPeak == null ? void 0 : cardPeak.color) != null ? _g : cardConfig == null ? void 0 : cardConfig.peak_color) != null ? _h : "#888" }; } function normalizeEntityConfig(entityConfig, cardConfig) { var _a; const normalizedEntity = { ...entityConfig, _normalized: true, entity: entityConfig.entity, name: (_a = entityConfig.name) != null ? _a : null, icon: entityConfig.icon }; normalizedEntity.layout = normalizeLayoutConfig(entityConfig, cardConfig); normalizedEntity.scale = normalizeScaleConfig(entityConfig, cardConfig); normalizedEntity.bar = normalizeBarConfig(entityConfig, cardConfig); normalizedEntity.baseline = normalizeBaselineConfig(entityConfig, cardConfig); normalizedEntity.formatting = normalizeFormattingConfig(entityConfig, cardConfig); normalizedEntity.target_marker = normalizeTargetMarkerConfig(entityConfig, cardConfig); normalizedEntity.peak_marker = normalizePeakMarkerConfig(entityConfig, cardConfig); normalizedEntity.min = normalizedEntity.scale.min.fixed; normalizedEntity.min_entity = normalizedEntity.scale.min.entity; normalizedEntity.max = normalizedEntity.scale.max.fixed; normalizedEntity.max_entity = normalizedEntity.scale.max.entity; normalizedEntity.height = normalizedEntity.layout.height; normalizedEntity.label_position = normalizedEntity.layout.label.position; normalizedEntity.label_width = normalizedEntity.layout.label.width; normalizedEntity.color_mode = normalizedEntity.bar.color_mode; normalizedEntity.fill_style = normalizedEntity.bar.fill_style; normalizedEntity.solid_fill = normalizedEntity.bar.solid_fill; normalizedEntity.color = normalizedEntity.bar.color; normalizedEntity.gradient_stops = normalizedEntity.bar.gradient_stops; normalizedEntity.severity = normalizedEntity.bar.severity; normalizedEntity.animated = normalizedEntity.bar.animated; normalizedEntity.above_target_color = normalizedEntity.bar.above_target_color; normalizedEntity.decimal = normalizedEntity.formatting.decimal; normalizedEntity.unit = normalizedEntity.formatting.unit; normalizedEntity.target = normalizedEntity.target_marker.source.fixed; normalizedEntity.target_entity = normalizedEntity.target_marker.source.entity; normalizedEntity.target_color = normalizedEntity.target_marker.color; normalizedEntity.show_target_label = normalizedEntity.target_marker.show_label; normalizedEntity.show_peak = normalizedEntity.peak_marker.show; normalizedEntity.peak_color = normalizedEntity.peak_marker.color; return normalizedEntity; } function normalizeCardConfig(rawConfig) { var _a; const baseConfig = { title: "", label_position: "left", color_mode: "severity", color: "#4a9eff", animated: true, show_peak: false, peak_color: "#888", target: null, target_entity: null, target_color: "#888", show_target_label: false, above_target_color: null, baseline: null, decimal: null, gradient_stops: null, min: 0, min_entity: null, max: 100, max_entity: null, height: 38, label_width: 100, severity: [ { from: 0, to: 33, color: "#4CAF50" }, { from: 33, to: 75, color: "#FF9800" }, { from: 75, to: 100, color: "#F44336" } ], ...rawConfig }; baseConfig._height_explicit = ((_a = rawConfig == null ? void 0 : rawConfig.layout) == null ? void 0 : _a.height) !== void 0 || (rawConfig == null ? void 0 : rawConfig.height) !== void 0; if (baseConfig.entity && !baseConfig.entities) { baseConfig.entities = [{ entity: baseConfig.entity, ...baseConfig.name !== void 0 ? { name: baseConfig.name } : {} }]; } baseConfig.entities = baseConfig.entities.map( (e) => typeof e === "string" ? { entity: e } : e ); const normalizedCard = { ...baseConfig, _normalized: true }; normalizedCard.layout = normalizeLayoutConfig(baseConfig, null); normalizedCard.scale = normalizeScaleConfig(baseConfig, null); normalizedCard.bar = normalizeBarConfig(baseConfig, null); normalizedCard.baseline = normalizeBaselineConfig(baseConfig, null); normalizedCard.formatting = normalizeFormattingConfig(baseConfig, null); normalizedCard.target_marker = normalizeTargetMarkerConfig(baseConfig, null); normalizedCard.peak_marker = normalizePeakMarkerConfig(baseConfig, null); normalizedCard.entities = baseConfig.entities.map( (entityCfg) => normalizeEntityConfig(entityCfg, normalizedCard) ); return normalizedCard; } var init_normalize = __esm({ "src/config/normalize.js"() { } }); // src/config/resolve.js function getEntityNumericValue(hass, entityId) { var _a; if (!entityId || !((_a = hass == null ? void 0 : hass.states) == null ? void 0 : _a[entityId])) return null; const raw = hass.states[entityId].state; const num = parseFloat(raw); return Number.isFinite(num) ? num : null; } function getNumericValue(hass, value, entityId = null) { const entityValue = getEntityNumericValue(hass, entityId); if (entityValue !== null) return entityValue; if (value === null || value === void 0 || value === "") return null; const num = parseFloat(value); return Number.isFinite(num) ? num : null; } function resolvePercentValue(percent, minValue, maxValue) { if (!Number.isFinite(percent)) return null; const safeMin = Number.isFinite(minValue) ? minValue : 0; const safeMax = Number.isFinite(maxValue) ? maxValue : 100; return safeMin + percent / 100 * (safeMax - safeMin); } function getNormalizedResolvableNumericValue(hass, resolvable, minValue = null, maxValue = null) { var _a; if (!resolvable) return null; const entityValue = getEntityNumericValue(hass, resolvable.entity); if (entityValue !== null) return entityValue; const fixedValue = getNumericValue(hass, (_a = resolvable.fixed) != null ? _a : resolvable.value, null); if (fixedValue !== null) return fixedValue; if (Number.isFinite(resolvable.percent)) { return resolvePercentValue(resolvable.percent, minValue, maxValue); } return null; } var init_resolve = __esm({ "src/config/resolve.js"() { init_normalize(); } }); // src/config/validate.js function createDiagnostic(code, message, path, entity = null) { return { code, message, path, entity }; } function getStaticFixedValue(resolvable) { var _a; if (!resolvable || resolvable.entity || Number.isFinite(resolvable.percent)) { return null; } return getFiniteNumber((_a = resolvable.fixed) != null ? _a : resolvable.value); } function addWarning(diagnostics, code, message, path, entity = null) { diagnostics.warnings.push(createDiagnostic(code, message, path, entity)); } function validateScaleBounds(diagnostics, scale, path, entity = null) { const min = getStaticFixedValue(scale == null ? void 0 : scale.min); const max = getStaticFixedValue(scale == null ? void 0 : scale.max); if (Number.isFinite(min) && Number.isFinite(max) && min > max) { addWarning(diagnostics, "scale.min_gt_max", "Scale minimum is greater than maximum.", path, entity); } return { min, max }; } function validateTargetRange(diagnostics, config, scaleBounds, path, entity = null) { var _a; const target = getStaticFixedValue((_a = config == null ? void 0 : config.target_marker) == null ? void 0 : _a.source); if (!Number.isFinite(target)) return; const { min, max } = scaleBounds; if (Number.isFinite(min) && Number.isFinite(max) && (target < min || target > max)) { addWarning(diagnostics, "target.outside_scale", "Fixed target value is outside the fixed scale range.", path, entity); } } function validateBaselineRange(diagnostics, config, scaleBounds, path, entity = null) { var _a; const baseline = getStaticFixedValue((_a = config == null ? void 0 : config.baseline) == null ? void 0 : _a.at); if (!Number.isFinite(baseline)) return; const { min, max } = scaleBounds; if (Number.isFinite(min) && Number.isFinite(max) && (baseline < min || baseline > max)) { addWarning(diagnostics, "baseline.outside_scale", "Fixed baseline value is outside the fixed scale range.", path, entity); } } function hasConfiguredResolvableValue(resolvable) { var _a; return !!resolvable && (Number.isFinite(getFiniteNumber((_a = resolvable.fixed) != null ? _a : resolvable.value)) || Number.isFinite(resolvable.percent) || !!resolvable.entity); } function validateBaselineSuppressesNeedle(diagnostics, config, path, entity = null) { var _a, _b, _c, _d; const needleEnabled = ((_b = (_a = config == null ? void 0 : config.bar) == null ? void 0 : _a.needle) == null ? void 0 : _b.show) === true; const baselineConfigured = ((_c = config == null ? void 0 : config.baseline) == null ? void 0 : _c.enabled) !== false && hasConfiguredResolvableValue((_d = config == null ? void 0 : config.baseline) == null ? void 0 : _d.at); if (needleEnabled && baselineConfigured) { addWarning( diagnostics, "baseline-suppresses-needle", "Baseline rendering suppresses the needle marker.", path, entity ); } } function getStaticSegmentBound(boundary) { var _a; if (!boundary || boundary.entity || Number.isFinite(boundary.percent)) return null; return getFiniteNumber((_a = boundary.fixed) != null ? _a : boundary.value); } function validateSegments(diagnostics, segments, scaleBounds, path, entity = null) { if (!Array.isArray(segments) || !segments.length) return; const staticSegments = []; const { min, max } = scaleBounds; for (let index = 0; index < segments.length; index += 1) { const segment = segments[index]; const from = getStaticSegmentBound(segment == null ? void 0 : segment.from); const to = getStaticSegmentBound(segment == null ? void 0 : segment.to); const segmentPath = `${path}.segments[${index}]`; if (Number.isFinite(from) && Number.isFinite(to) && from > to) { addWarning(diagnostics, "segments.from_gt_to", "Segment start is greater than segment end.", segmentPath, entity); } if (Number.isFinite(min) && Number.isFinite(max)) { if (Number.isFinite(from) && (from < min || from > max)) { addWarning(diagnostics, "segments.outside_scale", "Segment boundary is outside the fixed scale range.", segmentPath, entity); } if (Number.isFinite(to) && (to < min || to > max)) { addWarning(diagnostics, "segments.outside_scale", "Segment boundary is outside the fixed scale range.", segmentPath, entity); } } if (Number.isFinite(from) && Number.isFinite(to)) { staticSegments.push({ from, to, path: segmentPath }); } } const sorted = [...staticSegments].sort((a, b) => a.from - b.from); for (let index = 1; index < sorted.length; index += 1) { const previous = sorted[index - 1]; const current = sorted[index]; if (current.from < previous.to) { addWarning(diagnostics, "segments.overlap", "Fixed segments overlap.", current.path, entity); } } } function validateGradientStops(diagnostics, stops, path, entity = null) { var _a; if (!Array.isArray(stops)) return; const seenPositions = /* @__PURE__ */ new Set(); for (let index = 0; index < stops.length; index += 1) { const pos = getFiniteNumber((_a = stops[index]) == null ? void 0 : _a.pos); const stopPath = `${path}.gradient_stops[${index}]`; if (Number.isFinite(pos) && (pos < 0 || pos > 100)) { addWarning( diagnostics, "gradient_stops.outside_range", "Gradient stop position is outside 0..100.", stopPath, entity ); } if (Number.isFinite(pos)) { if (seenPositions.has(pos)) { addWarning( diagnostics, "duplicate-gradient-stop-position", "Multiple gradient stops use the same position value.", stopPath, entity ); } else { seenPositions.add(pos); } } } } function validateConfigScope(diagnostics, config, path, entity = null) { var _a, _b; const scaleBounds = validateScaleBounds(diagnostics, config == null ? void 0 : config.scale, path, entity); validateTargetRange(diagnostics, config, scaleBounds, path, entity); validateBaselineRange(diagnostics, config, scaleBounds, path, entity); validateBaselineSuppressesNeedle(diagnostics, config, path, entity); validateSegments(diagnostics, (_a = config == null ? void 0 : config.bar) == null ? void 0 : _a.segments, scaleBounds, `${path}.bar`, entity); validateGradientStops(diagnostics, (_b = config == null ? void 0 : config.bar) == null ? void 0 : _b.gradient_stops, `${path}.bar`, entity); } function validateNormalizedConfig(config) { var _a; const diagnostics = { warnings: [], errors: [] }; if (!config || typeof config !== "object") { return diagnostics; } validateConfigScope(diagnostics, config, "card"); const seenEntities = /* @__PURE__ */ new Set(); const entities = Array.isArray(config.entities) ? config.entities : []; for (let index = 0; index < entities.length; index += 1) { const entityConfig = entities[index]; const entityId = (_a = entityConfig == null ? void 0 : entityConfig.entity) != null ? _a : null; const path = `entities[${index}]`; if (!entityId) { addWarning(diagnostics, "entities.missing_entity", "Entity row is missing an entity id.", path, null); continue; } if (seenEntities.has(entityId)) { addWarning(diagnostics, "entities.duplicate_entity", "Duplicate entity id in the same card config.", path, entityId); } else { seenEntities.add(entityId); } validateConfigScope(diagnostics, entityConfig, path, entityId); } return diagnostics; } var init_validate = __esm({ "src/config/validate.js"() { init_normalize(); } }); // src/view-model/row-view-model.js function getDefaultEntityIcon(stateObj, entityId = "") { var _a, _b, _c; const deviceClass = String((_b = (_a = stateObj == null ? void 0 : stateObj.attributes) == null ? void 0 : _a.device_class) != null ? _b : "").trim(); if (deviceClass) { const deviceClassIcons = { apparent_power: "mdi:flash", battery: "mdi:battery", carbon_dioxide: "mdi:molecule-co2", current: "mdi:current-ac", energy: "mdi:lightning-bolt", gas: "mdi:meter-gas", humidity: "mdi:water-percent", monetary: "mdi:cash", power: "mdi:flash", pressure: "mdi:gauge", temperature: "mdi:thermometer", voltage: "mdi:sine-wave", water: "mdi:water", weight: "mdi:weight", wind_speed: "mdi:weather-windy" }; if (deviceClassIcons[deviceClass]) { return deviceClassIcons[deviceClass]; } } const domain = String(entityId || "").split(".")[0]; const domainIcons = { sensor: "mdi:eye", binary_sensor: "mdi:radiobox-marked", switch: "mdi:toggle-switch-variant", light: "mdi:lightbulb" }; return (_c = domainIcons[domain]) != null ? _c : null; } function toScalePct(value, minValue, maxValue) { if (!Number.isFinite(value)) return null; const safeMin = Number.isFinite(minValue) ? minValue : 0; const safeMax = Number.isFinite(maxValue) ? maxValue : 100; const range = safeMax - safeMin || 1; return Math.min(100, Math.max(0, (value - safeMin) / range * 100)); } function formatNumericDisplay(rawVal, decimal = null) { if (!Number.isFinite(rawVal)) return String(rawVal); if (decimal !== null) { return parseFloat(rawVal.toFixed(decimal)).toLocaleString(); } return rawVal.toLocaleString(); } function isTightUnit(unit) { return ["h", "m", "s"].includes(String(unit || "").trim()); } function formatDisplayWithUnit(display, unit) { if (!unit) return String(display); const cleanUnit = String(unit); return `${display}${isTightUnit(cleanUnit) ? "" : " "}${cleanUnit}`; } function parseColorToRgb(color) { const value = String(color || "").trim(); if (!value) return null; const hexMatch = value.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i); if (hexMatch) { const hex = hexMatch[1]; const full = hex.length === 3 ? hex.split("").map((char) => char + char).join("") : hex; return { r: parseInt(full.slice(0, 2), 16), g: parseInt(full.slice(2, 4), 16), b: parseInt(full.slice(4, 6), 16) }; } const rgbMatch = value.match(/^rgba?\(([^)]+)\)$/i); if (rgbMatch) { const parts = rgbMatch[1].split(",").map((part) => part.trim()); if (parts.length >= 3) { return { r: Math.max(0, Math.min(255, parseFloat(parts[0]))), g: Math.max(0, Math.min(255, parseFloat(parts[1]))), b: Math.max(0, Math.min(255, parseFloat(parts[2]))) }; } } return null; } function getNeedleBorderColor(color) { const rgb = parseColorToRgb(color); if (!rgb) return "#000000"; const toLinear = (channel) => { const srgb = channel / 255; return srgb <= 0.04045 ? srgb / 12.92 : ((srgb + 0.055) / 1.055) ** 2.4; }; const luminance = 0.2126 * toLinear(rgb.r) + 0.7152 * toLinear(rgb.g) + 0.0722 * toLinear(rgb.b); return luminance < 0.22 ? "#ffffff" : "#000000"; } function getNeedleState(entityConfig, numericValue, minValue, maxValue, baselinePercent) { var _a, _b, _c; const needle = (_a = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _a.needle; if (!(needle == null ? void 0 : needle.show) || Number.isFinite(baselinePercent) || !Number.isFinite(numericValue)) { const color2 = (_b = needle == null ? void 0 : needle.color) != null ? _b : "#ffffff"; return { show: false, percent: null, pct: null, color: color2, borderColor: getNeedleBorderColor(color2), edge: "middle" }; } const color = (_c = needle.color) != null ? _c : "#ffffff"; const percent = Math.min(100, Math.max(0, toScalePct(numericValue, minValue, maxValue))); return { show: true, percent, pct: percent, color, borderColor: getNeedleBorderColor(color), edge: percent <= 0 ? "left" : percent >= 100 ? "right" : "middle" }; } function getPeakState(entityId, numericValue, minValue, maxValue, peaks, peakEnabled) { if (!peakEnabled || !Number.isFinite(numericValue)) { return { value: null, percent: null, display: null, visible: false }; } const existingPeak = getFiniteNumber(peaks == null ? void 0 : peaks[entityId]); const peakValue = Number.isFinite(existingPeak) ? Math.max(existingPeak, numericValue) : numericValue; return { value: peakValue, percent: toScalePct(peakValue, minValue, maxValue), visible: true }; } function buildRowViewModel(options) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S; const { hass, cardConfig, entityConfig, entityState, peaks } = options; void cardConfig; const entityId = (_a = entityConfig == null ? void 0 : entityConfig.entity) != null ? _a : null; const rawState = (_b = entityState == null ? void 0 : entityState.state) != null ? _b : ""; const numericValue = getFiniteNumber(rawState); const rawUnit = (_d = (_c = entityState == null ? void 0 : entityState.attributes) == null ? void 0 : _c.unit_of_measurement) != null ? _d : ""; const displayUnit = numericValue !== null ? (_g = (_f = (_e = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _e.unit) != null ? _f : rawUnit) != null ? _g : "" : ""; const min = getNormalizedResolvableNumericValue(hass, (_h = entityConfig == null ? void 0 : entityConfig.scale) == null ? void 0 : _h.min); const max = getNormalizedResolvableNumericValue(hass, (_i = entityConfig == null ? void 0 : entityConfig.scale) == null ? void 0 : _i.max); const safeMin = Number.isFinite(min) ? min : 0; const safeMax = Number.isFinite(max) ? max : 100; const percent = numericValue !== null ? toScalePct(numericValue, safeMin, safeMax) : 0; const displayValue = numericValue === null ? rawState : formatNumericDisplay(numericValue, (_k = (_j = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _j.decimal) != null ? _k : null); const targetValue = ((_l = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _l.enabled) === false ? null : getNormalizedResolvableNumericValue(hass, (_m = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _m.source, safeMin, safeMax); const targetPercent = targetValue !== null ? toScalePct(targetValue, safeMin, safeMax) : null; const targetVisible = targetValue !== null; const targetDisplay = targetValue !== null ? formatDisplayWithUnit( formatNumericDisplay(targetValue, (_o = (_n = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _n.decimal) != null ? _o : null), (_r = (_q = (_p = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _p.unit) != null ? _q : rawUnit) != null ? _r : "" ) : null; const baselineValue = ((_s = entityConfig == null ? void 0 : entityConfig.baseline) == null ? void 0 : _s.enabled) === false ? null : getNormalizedResolvableNumericValue(hass, (_t = entityConfig == null ? void 0 : entityConfig.baseline) == null ? void 0 : _t.at, safeMin, safeMax); const baselinePercent = Number.isFinite(baselineValue) ? toScalePct(baselineValue, safeMin, safeMax) : null; const baselineVisible = Number.isFinite(baselineValue); const peakState = getPeakState( entityId, numericValue, safeMin, safeMax, peaks, ((_u = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _u.show) === true ); const peakDisplay = peakState.visible ? formatNumericDisplay(peakState.value, (_w = (_v = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _v.decimal) != null ? _w : null) : null; return { entityId, name: (_z = (_y = entityConfig == null ? void 0 : entityConfig.name) != null ? _y : (_x = entityState == null ? void 0 : entityState.attributes) == null ? void 0 : _x.friendly_name) != null ? _z : entityId, icon: (entityConfig == null ? void 0 : entityConfig.icon) === false ? false : (_C = (_B = entityConfig == null ? void 0 : entityConfig.icon) != null ? _B : (_A = entityState == null ? void 0 : entityState.attributes) == null ? void 0 : _A.icon) != null ? _C : getDefaultEntityIcon(entityState, entityId), state: rawState, numericValue, rawUnit, displayUnit, min: safeMin, max: safeMax, percent, displayValue, unit: displayUnit, barColor: (_E = (_D = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _D.color) != null ? _E : null, fillStyle: (_G = (_F = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _F.fill_style) != null ? _G : null, target: targetValue, targetPercent, targetDisplay, targetVisible, baseline: baselineValue, baselinePercent, baselineVisible, peak: peakState.value, peakPercent: peakState.percent, peakDisplay, peakVisible: peakState.visible, segments: (_I = (_H = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _H.segments) != null ? _I : null, gradientStops: (_K = (_J = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _J.gradient_stops) != null ? _K : null, needle: getNeedleState(entityConfig, numericValue, safeMin, safeMax, baselinePercent), classes: { labelPosition: (_N = (_M = (_L = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _L.label) == null ? void 0 : _M.position) != null ? _N : "left", animated: ((_O = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _O.animated) !== false }, attributes: { entity: entityId, baseHeight: (_Q = (_P = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _P.height) != null ? _Q : 38, heightExplicit: ((_R = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _R.height_explicit) === true, barAnimated: ((_S = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _S.animated) !== false } }; } var init_row_view_model = __esm({ "src/view-model/row-view-model.js"() { init_resolve(); init_normalize(); } }); // src/utils/dom.js function escapeHtml(value) { if (value == null) return ""; return String(value).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); } var init_dom = __esm({ "src/utils/dom.js"() { } }); // src/card/SensorBarCard.js var SensorBarCard; var init_SensorBarCard = __esm({ "src/card/SensorBarCard.js"() { init_normalize(); init_resolve(); init_validate(); init_row_view_model(); init_dom(); SensorBarCard = class extends HTMLElement { static getConfigElement() { return document.createElement("sensor-bar-card-plus-editor"); } constructor() { super(); this.attachShadow({ mode: "open" }); this._baseDomReady = false; this._config = {}; this._diagnostics = { warnings: [], errors: [] }; this._lastDiagnosticsSignature = null; this._hass = null; this._peaks = {}; this._rendered = false; this._resizeObserver = null; this._densityPassScheduled = false; this._densityPassDirty = false; this._densityPassFrame = null; this._densityPassRetries = 0; this._boundWindowResize = () => this._schedulePostLayoutDensityPass(); this._ensureBaseDom(); } connectedCallback() { window.addEventListener("resize", this._boundWindowResize, { passive: true }); this._schedulePostLayoutDensityPass(); } disconnectedCallback() { window.removeEventListener("resize", this._boundWindowResize); this._disconnectResizeObserver(); if (this._densityPassFrame) { cancelAnimationFrame(this._densityPassFrame); this._densityPassFrame = null; } this._densityPassScheduled = false; this._densityPassDirty = false; } setConfig(config) { if (!config.entities && !config.entity) { throw new Error("You must define entities or entity"); } this._rendered = false; this._config = this.normalizeCardConfig(config); const activeEntityIds = new Set( (this._config.entities || []).map((entityConfig) => entityConfig.entity) ); for (const entityId of Object.keys(this._peaks)) { if (!activeEntityIds.has(entityId)) { delete this._peaks[entityId]; } } this._diagnostics = validateNormalizedConfig(this._config); this._logDiagnostics(); this._render(); } _logDiagnostics() { var _a; const diagnostics = (_a = this._diagnostics) != null ? _a : { warnings: [], errors: [] }; const signature = JSON.stringify(diagnostics); if (signature === this._lastDiagnosticsSignature) return; this._lastDiagnosticsSignature = signature; diagnostics.warnings.forEach((diagnostic) => { console.warn(`[sensor-bar-card-plus] ${diagnostic.message}`, diagnostic); }); diagnostics.errors.forEach((diagnostic) => { console.warn(`[sensor-bar-card-plus] ${diagnostic.message}`, diagnostic); }); } // The normalized model is internal only. It preserves today's flat YAML // while giving future work one structured compatibility layer to build on. normalizeCardConfig(rawConfig) { return normalizeCardConfig(rawConfig); } normalizeEntityConfig(entityConfig, cardConfig) { return normalizeEntityConfig(entityConfig, cardConfig); } // Internal resolvable shape preserves today's flat `value + *_entity` // behavior while canonicalizing the normalized form to `fixed + entity`. normalizeResolvableValue(value, entityValue, percentValue = null) { return normalizeResolvableValue(value, entityValue, percentValue); } _looksLikeEntityId(value) { return looksLikeEntityId(value); } _parsePercentLiteral(value) { return parsePercentLiteral(value); } _getFiniteNumber(value) { return getFiniteNumber(value); } normalizeStructuredResolvableValue(input, inheritedResolvable = null, defaultValue = null, options = {}) { return normalizeStructuredResolvableValue(input, inheritedResolvable, defaultValue, options); } normalizeBaselineDirectionConfig(input, inheritedDirection = null) { return normalizeBaselineDirectionConfig(input, inheritedDirection); } normalizeBaselineConfig(entityConfig, cardConfig) { return normalizeBaselineConfig(entityConfig, cardConfig); } inferSegmentEndValues(segments, fallbackEnd = null) { const sorted = [...segments].sort((a, b) => a.from - b.from); return sorted.map((segment, index) => { var _a; let to = Number.isFinite(segment.to) ? segment.to : null; if (!Number.isFinite(to) && index < sorted.length - 1) { to = sorted[index + 1].from; } if (!Number.isFinite(to) && Number.isFinite(fallbackEnd)) { to = fallbackEnd; } return { from: segment.from, to, color: segment.color, label: (_a = segment.label) != null ? _a : null }; }); } normalizeSeverityToSegments(input) { return normalizeSeverityToSegments(input); } _hasResolvableMagnitude(resolvable) { return !!resolvable && (Number.isFinite(this._getFiniteNumber(resolvable.fixed)) || Number.isFinite(resolvable.percent)); } normalizeGaugeSegments(input) { return normalizeGaugeSegments(input); } normalizeScaleBound(entityConfig, cardConfig, key, defaultValue) { return normalizeScaleBound(entityConfig, cardConfig, key, defaultValue); } normalizeScaleConfig(entityConfig, cardConfig) { return normalizeScaleConfig(entityConfig, cardConfig); } _fillStyleToColorMode(fillStyle) { return fillStyleToColorMode(fillStyle); } _colorModeToFillStyle(colorMode) { return colorModeToFillStyle(colorMode); } _normalizeBarModeConfig(barConfig = null, flatColorMode = null) { return normalizeBarModeConfig(barConfig, flatColorMode); } _resolveNormalizedBarMode(entityBar, entityConfig, cardBar, cardConfig) { return resolveNormalizedBarMode(entityBar, entityConfig, cardBar, cardConfig); } _normalizeGradientStops(input) { return normalizeGradientStops(input); } normalizeNeedleConfig(input, inheritedNeedle = null) { return normalizeNeedleConfig(input, inheritedNeedle); } normalizeBarConfig(entityConfig, cardConfig) { return normalizeBarConfig(entityConfig, cardConfig); } normalizeLayoutConfig(entityConfig, cardConfig) { return normalizeLayoutConfig(entityConfig, cardConfig); } _clampSupportedRowHeight(height) { return clampSupportedRowHeight(height); } normalizeFormattingConfig(entityConfig, cardConfig) { return normalizeFormattingConfig(entityConfig, cardConfig); } normalizeTargetMarkerConfig(entityConfig, cardConfig) { return normalizeTargetMarkerConfig(entityConfig, cardConfig); } normalizePeakMarkerConfig(entityConfig, cardConfig) { return normalizePeakMarkerConfig(entityConfig, cardConfig); } _normalizeOptionalEnabled(value) { return normalizeOptionalEnabled(value); } set hass(hass) { const oldHass = this._hass; this._hass = hass; if (!oldHass) { this._update(); return; } if (this._shouldUpdate(oldHass, hass)) { this._update(); } } // Merge global config with per-entity overrides _resolve(entityCfg) { var _a, _b, _c, _d, _e, _f, _g; const ecfg = (entityCfg == null ? void 0 : entityCfg._normalized) ? entityCfg : this.normalizeEntityConfig(entityCfg, this._config); const stateObj = (_c = (_b = (_a = this._hass) == null ? void 0 : _a.states) == null ? void 0 : _b[ecfg.entity]) != null ? _c : null; return { ...ecfg, icon: ecfg.icon === false ? false : (_f = (_e = ecfg.icon) != null ? _e : (_d = stateObj == null ? void 0 : stateObj.attributes) == null ? void 0 : _d.icon) != null ? _f : this._getDefaultEntityIcon(stateObj, ecfg.entity), name: (_g = ecfg.name) != null ? _g : null }; } _getDefaultEntityIcon(stateObj, entityId = "") { var _a, _b, _c; const deviceClass = String((_b = (_a = stateObj == null ? void 0 : stateObj.attributes) == null ? void 0 : _a.device_class) != null ? _b : "").trim(); if (deviceClass) { const deviceClassIcons = { apparent_power: "mdi:flash", battery: "mdi:battery", carbon_dioxide: "mdi:molecule-co2", current: "mdi:current-ac", energy: "mdi:lightning-bolt", gas: "mdi:meter-gas", humidity: "mdi:water-percent", monetary: "mdi:cash", power: "mdi:flash", pressure: "mdi:gauge", temperature: "mdi:thermometer", voltage: "mdi:sine-wave", water: "mdi:water", weight: "mdi:weight", wind_speed: "mdi:weather-windy" }; if (deviceClassIcons[deviceClass]) { return deviceClassIcons[deviceClass]; } } const domain = String(entityId || "").split(".")[0]; const domainIcons = { sensor: "mdi:eye", binary_sensor: "mdi:radiobox-marked", switch: "mdi:toggle-switch-variant", light: "mdi:lightbulb" }; return (_c = domainIcons[domain]) != null ? _c : null; } _shouldUpdate(oldHass, newHass) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; if (!this._config || !this._config.entities) return true; for (const entityCfg of this._config.entities) { const ecfg = this._resolve(entityCfg); const entitiesToWatch = [ entityCfg.entity, (_b = (_a = ecfg.scale) == null ? void 0 : _a.min) == null ? void 0 : _b.entity, (_d = (_c = ecfg.scale) == null ? void 0 : _c.max) == null ? void 0 : _d.entity, (_f = (_e = ecfg.baseline) == null ? void 0 : _e.at) == null ? void 0 : _f.entity, (_h = (_g = ecfg.target_marker) == null ? void 0 : _g.source) == null ? void 0 : _h.entity ].filter(Boolean); for (const ent of entitiesToWatch) { const oldState = (_i = oldHass.states[ent]) != null ? _i : null; const newState = (_j = newHass.states[ent]) != null ? _j : null; if (oldState !== newState) { return true; } } } return false; } _setStyleIfChanged(el, prop, value) { var _a, _b; if (!(el == null ? void 0 : el.style)) return false; const nextValue = value == null ? "" : String(value); if (prop.startsWith("--")) { const currentValue2 = typeof el.style.getPropertyValue === "function" ? el.style.getPropertyValue(prop) : (_a = el.style[prop]) != null ? _a : ""; if (currentValue2 === nextValue) return false; if (typeof el.style.setProperty === "function") { el.style.setProperty(prop, nextValue); } else { el.style[prop] = nextValue; } return true; } const currentValue = (_b = el.style[prop]) != null ? _b : ""; if (currentValue === nextValue) return false; el.style[prop] = nextValue; return true; } _setStyleTextIfChanged(el, value) { var _a; if (!(el == null ? void 0 : el.style)) return false; const nextValue = value == null ? "" : String(value); const currentValue = (_a = el.style.cssText) != null ? _a : ""; if (currentValue === nextValue) return false; el.style.cssText = nextValue; return true; } _setTextIfChanged(el, value) { var _a; if (!el) return false; const nextValue = value == null ? "" : String(value); if (((_a = el.textContent) != null ? _a : "") === nextValue) return false; el.textContent = nextValue; return true; } _setDatasetIfChanged(el, key, value) { var _a; if (!(el == null ? void 0 : el.dataset)) return false; const nextValue = value == null ? "" : String(value); const currentValue = (_a = el.dataset[key]) != null ? _a : ""; if (currentValue === nextValue) return false; el.dataset[key] = nextValue; return true; } _setClassNameIfChanged(el, value) { var _a; if (!el) return false; const nextValue = value == null ? "" : String(value); if (((_a = el.className) != null ? _a : "") === nextValue) return false; el.className = nextValue; return true; } _repositionAllTargetLabels() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".row[data-entity]").forEach((row) => { this._positionTargetLabel(row); }); } _positionTargetLabel(row) { const track = row.querySelector(".bar-track"); const label = row.querySelector(".target-value-label"); const marker = row.querySelector(".target-marker"); if (!track || !label || !marker) return; if (marker.style.display === "none" || !label.textContent.trim()) { this._setStyleIfChanged(label, "visibility", "hidden"); return; } const trackRect = track.getBoundingClientRect(); const maxLabelWidth = Math.max(0, Math.floor(trackRect.width - 4)); this._setStyleIfChanged(label, "maxWidth", `${maxLabelWidth}px`); const labelRect = label.getBoundingClientRect(); const markerPercent = parseFloat(marker.style.left); if (!Number.isFinite(markerPercent) || trackRect.width <= 0 || labelRect.width <= 0 || maxLabelWidth <= 10) { this._setStyleIfChanged(label, "visibility", "hidden"); return; } const markerX = markerPercent / 100 * trackRect.width; const halfLabel = labelRect.width / 2; const clampedX = Math.max(halfLabel, Math.min(trackRect.width - halfLabel, markerX)); this._setStyleIfChanged(label, "left", `${clampedX}px`); this._setStyleIfChanged(label, "transform", "translateX(-50%)"); this._setStyleIfChanged(label, "visibility", "visible"); } _getEntityNumericValue(entityId) { return getEntityNumericValue(this._hass, entityId); } _getNumericValue(value, entityId = null) { return getNumericValue(this._hass, value, entityId); } _resolvePercentValue(percent, minValue, maxValue) { return resolvePercentValue(percent, minValue, maxValue); } _getNormalizedResolvableNumericValue(resolvable, minValue = null, maxValue = null) { return getNormalizedResolvableNumericValue(this._hass, resolvable, minValue, maxValue); } _hexToRgb(color) { if (!color || typeof color !== "string") return null; const hex = color.replace("#", "").trim(); const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex; if (!/^[0-9a-fA-F]{6}$/.test(full)) return null; return { r: parseInt(full.slice(0, 2), 16), g: parseInt(full.slice(2, 4), 16), b: parseInt(full.slice(4, 6), 16) }; } _getSeverityInterpolationStops(ecfg, minValue = 0, maxValue = 100) { const bands = this._getSegmentsForRendering(ecfg, minValue, maxValue); const sorted = bands.filter((s) => Number.isFinite(s == null ? void 0 : s.from) && Number.isFinite(s == null ? void 0 : s.to) && (s == null ? void 0 : s.color)).sort((a, b) => a.from - b.from); if (!sorted.length) return []; const stops = []; for (let i = 0; i < sorted.length; i++) { const band = sorted[i]; const rgb = this._hexToRgb(band.color); if (!rgb) continue; let anchor; if (i === 0) { anchor = band.from; } else if (i === sorted.length - 1) { anchor = band.to; } else { anchor = band.from + (band.to - band.from) / 2; } if (!stops.length || stops[stops.length - 1].p !== anchor) { stops.push({ p: anchor, ...rgb }); } } return stops; } _getSeverityBandGradientCss(ecfg, minValue = 0, maxValue = 100) { const bands = this._getSegmentsForRendering(ecfg, minValue, maxValue); const sorted = bands.filter((s) => Number.isFinite(s == null ? void 0 : s.from) && Number.isFinite(s == null ? void 0 : s.to) && (s == null ? void 0 : s.color)).sort((a, b) => a.from - b.from); if (!sorted.length) return null; const stops = []; for (const band of sorted) { stops.push(`${band.color} ${band.from}%`, `${band.color} ${band.to}%`); } return `linear-gradient(to right, ${stops.join(", ")})`; } _getSoftBandBlendWidthPct() { return 1.5; } _pushGradientColorStop(stops, pos, color) { if (!Array.isArray(stops) || !color) return; const clampedPos = Math.min(100, Math.max(0, pos)); const last = stops[stops.length - 1]; if (last && last.color === color && Math.abs(last.p - clampedPos) < 1e-4) return; stops.push({ p: clampedPos, color }); } _getSoftBandGradientStops(ecfg, minValue = 0, maxValue = 100) { const bands = this._getSegmentsForRendering(ecfg, minValue, maxValue); const sorted = bands.filter((s) => Number.isFinite(s == null ? void 0 : s.from) && Number.isFinite(s == null ? void 0 : s.to) && (s == null ? void 0 : s.color)).sort((a, b) => a.from - b.from); if (!sorted.length) return []; const blendWidth = this._getSoftBandBlendWidthPct(); const blendHalf = blendWidth / 2; const stops = []; this._pushGradientColorStop(stops, sorted[0].from, sorted[0].color); for (let i = 0; i < sorted.length - 1; i++) { const current = sorted[i]; const next = sorted[i + 1]; const boundary = current.to; const currentWidth = current.to - current.from; const nextWidth = next.to - next.from; const soften = currentWidth >= blendWidth && nextWidth >= blendWidth; if (soften) { this._pushGradientColorStop(stops, Math.max(current.from, boundary - blendHalf), current.color); this._pushGradientColorStop(stops, Math.min(next.to, boundary + blendHalf), next.color); } else { this._pushGradientColorStop(stops, boundary, current.color); this._pushGradientColorStop(stops, boundary, next.color); } } this._pushGradientColorStop(stops, sorted[sorted.length - 1].to, sorted[sorted.length - 1].color); return stops; } _getSoftBandGradientCss(ecfg, minValue = 0, maxValue = 100) { const stops = this._getSoftBandGradientStops(ecfg, minValue, maxValue); if (!stops.length) return null; return `linear-gradient(to right, ${stops.map((stop) => `${stop.color} ${stop.p}%`).join(", ")})`; } _resolveSegmentBoundaryPct(boundary, minValue, maxValue) { if (boundary === null || boundary === void 0) return null; if (typeof boundary === "object" && !Array.isArray(boundary)) { const fixed2 = this._getFiniteNumber(boundary.fixed); if (Number.isFinite(fixed2)) { return this._toScalePct(fixed2, minValue, maxValue); } if (Number.isFinite(boundary.percent)) { return boundary.percent; } return null; } const percent = this._parsePercentLiteral(boundary); if (Number.isFinite(percent)) { return percent; } const fixed = this._getFiniteNumber(boundary); return Number.isFinite(fixed) ? this._toScalePct(fixed, minValue, maxValue) : null; } _getEffectiveFillStyle(ecfg) { var _a, _b, _c, _d; return (_d = (_c = (_a = ecfg == null ? void 0 : ecfg.bar) == null ? void 0 : _a.fill_style) != null ? _c : this._colorModeToFillStyle((_b = ecfg == null ? void 0 : ecfg.bar) == null ? void 0 : _b.color_mode)) != null ? _d : "bands"; } _segmentsNeedBoundaryResolution(segments) { return Array.isArray(segments) && segments.some((segment) => (segment == null ? void 0 : segment.from) && typeof segment.from === "object" && !Array.isArray(segment.from) || (segment == null ? void 0 : segment.to) && typeof segment.to === "object" && !Array.isArray(segment.to)); } _getSegmentsForRendering(ecfg, minValue = 0, maxValue = 100) { var _a, _b; const safeMin = Number.isFinite(minValue) ? minValue : 0; const safeMax = Number.isFinite(maxValue) ? maxValue : 100; const rawSegments = Array.isArray((_a = ecfg.bar) == null ? void 0 : _a.segments) ? ecfg.bar.segments : []; if (((_b = ecfg.bar) == null ? void 0 : _b.segment_space) === "scale" || this._segmentsNeedBoundaryResolution(rawSegments)) { const resolvedSegments = rawSegments.map((segment) => { var _a2; return { from: this._resolveSegmentBoundaryPct(segment.from, safeMin, safeMax), to: this._resolveSegmentBoundaryPct(segment.to, safeMin, safeMax), color: segment.color, label: (_a2 = segment.label) != null ? _a2 : null }; }).filter((segment) => Number.isFinite(segment.from) && segment.color); return this.inferSegmentEndValues(resolvedSegments, 100).filter((segment) => Number.isFinite(segment.from) && Number.isFinite(segment.to) && segment.color); } return this.inferSegmentEndValues(rawSegments, 100).filter((segment) => Number.isFinite(segment.from) && Number.isFinite(segment.to) && segment.color); } _getColor(pct, ecfg, minValue = 0, maxValue = 100) { const fillStyle = this._getEffectiveFillStyle(ecfg); if (fillStyle === "solid") return ecfg.bar.color; if (fillStyle === "gradient" || fillStyle === "band_gradient" || fillStyle === "soft_bands") { let stops; if (fillStyle === "band_gradient") { stops = this._getSeverityInterpolationStops(ecfg, minValue, maxValue); } else if (fillStyle === "soft_bands") { stops = this._getSoftBandGradientStops(ecfg, minValue, maxValue).map((stop) => { const rgb = this._hexToRgb(stop.color); return rgb ? { p: stop.p, ...rgb } : null; }).filter(Boolean); } else if (ecfg.bar.gradient_stops && ecfg.bar.gradient_stops.length >= 2) { stops = ecfg.bar.gradient_stops.map((s) => { const hex = s.color.replace("#", ""); const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex; return { p: s.pos, r: parseInt(full.slice(0, 2), 16), g: parseInt(full.slice(2, 4), 16), b: parseInt(full.slice(4, 6), 16) }; }); stops.sort((a, b) => a.p - b.p); } else { stops = [ { p: 0, r: 76, g: 175, b: 80 }, { p: 50, r: 255, g: 152, b: 0 }, { p: 100, r: 244, g: 67, b: 54 } ]; } if (!stops || !stops.length) return ecfg.bar.color; let lo = stops[0], hi = stops[stops.length - 1]; for (let i = 0; i < stops.length - 1; i++) { if (pct >= stops[i].p && pct <= stops[i + 1].p) { lo = stops[i]; hi = stops[i + 1]; break; } } const t = lo.p === hi.p ? 0 : (pct - lo.p) / (hi.p - lo.p); return `rgb(${Math.round(lo.r + t * (hi.r - lo.r))},${Math.round(lo.g + t * (hi.g - lo.g))},${Math.round(lo.b + t * (hi.b - lo.b))})`; } for (const s of this._getSegmentsForRendering(ecfg, minValue, maxValue)) { if (pct >= s.from && pct <= s.to) return s.color; } return ecfg.bar.color; } _buildFullScaleGradientStyle(stops) { if (!Array.isArray(stops) || !stops.length) return null; const cssStops = stops.map((stop) => { var _a; const cssColor = (_a = stop.color) != null ? _a : this._rgbToCss(stop); return cssColor ? `${cssColor} ${stop.p}%` : null; }).filter(Boolean); if (!cssStops.length) return null; return `background:linear-gradient(to right,${cssStops.join(",")});background-repeat:no-repeat;`; } _getGradientInterpolationStops(ecfg, minValue = 0, maxValue = 100) { const fillStyle = this._getEffectiveFillStyle(ecfg); if (fillStyle === "band_gradient") { return this._getSeverityInterpolationStops(ecfg, minValue, maxValue); } if (fillStyle === "soft_bands") { return this._getSoftBandGradientStops(ecfg, minValue, maxValue).map((stop) => { const rgb = this._hexToRgb(stop.color); return rgb ? { p: stop.p, ...rgb } : null; }).filter(Boolean).sort((a, b) => a.p - b.p); } if (ecfg.bar.gradient_stops && ecfg.bar.gradient_stops.length >= 2) { return ecfg.bar.gradient_stops.map((s) => { const rgb = this._hexToRgb(s.color); return rgb ? { p: s.pos, ...rgb } : null; }).filter(Boolean).sort((a, b) => a.p - b.p); } return [ { p: 0, r: 76, g: 175, b: 80 }, { p: 50, r: 255, g: 152, b: 0 }, { p: 100, r: 244, g: 67, b: 54 } ]; } _rgbToCss(rgb) { if (!rgb) return null; return `rgb(${rgb.r},${rgb.g},${rgb.b})`; } _buildSolidGradientStyle(color) { return `linear-gradient(to right,${color} 0%,${color} 100%)`; } _getBasePaintGradient(color, ecfg, minValue = 0, maxValue = 100) { var _a; const fillStyle = this._getEffectiveFillStyle(ecfg); if (ecfg.bar.solid_fill) { return this._buildSolidGradientStyle(color); } if (fillStyle === "bands") { return this._getSeverityBandGradientCss(ecfg, minValue, maxValue); } if (fillStyle === "soft_bands") { return this._getSoftBandGradientCss(ecfg, minValue, maxValue); } if (fillStyle === "gradient" || fillStyle === "band_gradient") { const stops = this._getGradientInterpolationStops(ecfg, minValue, maxValue); return (_a = this._buildFullScaleGradientStyle(stops)) == null ? void 0 : _a.replace(/^background:/, "").replace(/;background-repeat:no-repeat;$/, ""); } return this._buildSolidGradientStyle(color); } _getOverlayGradient(startPct, endPct, color) { if (!color) return null; const start = Math.min(100, Math.max(0, startPct)); const end = Math.min(100, Math.max(0, endPct)); if (end <= start) return null; return `linear-gradient(to right,transparent 0%,transparent ${start}%,${color} ${start}%,${color} ${end}%,transparent ${end}%,transparent 100%)`; } _toScalePct(value, minValue, maxValue) { if (!Number.isFinite(value)) return null; const safeMin = Number.isFinite(minValue) ? minValue : 0; const safeMax = Number.isFinite(maxValue) ? maxValue : 100; const range = safeMax - safeMin || 1; return Math.min(100, Math.max(0, (value - safeMin) / range * 100)); } _resolveBaselinePct(ecfg, safeMin, safeMax) { var _a, _b; if (((_a = ecfg.baseline) == null ? void 0 : _a.enabled) === false) return null; const baselineValue = this._getNormalizedResolvableNumericValue((_b = ecfg.baseline) == null ? void 0 : _b.at, safeMin, safeMax); if (!Number.isFinite(baselineValue)) return null; return this._toScalePct(baselineValue, safeMin, safeMax); } _formatNumericDisplay(rawVal, decimal = null) { if (!Number.isFinite(rawVal)) return String(rawVal); if (decimal !== null) { return parseFloat(rawVal.toFixed(decimal)).toLocaleString(); } return rawVal.toLocaleString(); } _getNormalizedPercent(valuePct, baselinePct = null) { const clampedValue = Math.min(100, Math.max(0, valuePct)); if (!Number.isFinite(baselinePct)) { return { usesBaseline: false, start: 0, end: clampedValue, positive: true, baseline: null, hidden: clampedValue <= 0 }; } const clampedBaseline = Math.min(100, Math.max(0, baselinePct)); return { usesBaseline: true, start: Math.min(clampedValue, clampedBaseline), end: Math.max(clampedValue, clampedBaseline), positive: clampedValue >= clampedBaseline, baseline: clampedBaseline, hidden: clampedValue === clampedBaseline }; } _getEndpointSemantics(geometry) { if (geometry == null ? void 0 : geometry.endpointSemantics) { return geometry.endpointSemantics; } if (!(geometry == null ? void 0 : geometry.usesBaseline)) { return { left: "scale", right: "value" }; } return geometry.positive ? { left: "baseline", right: "value" } : { left: "value", right: "baseline" }; } _getRevealCornerRadii(geometry) { const endpoints = this._getEndpointSemantics(geometry); const isRounded = (endpointType) => endpointType === "value" || endpointType === "range" || endpointType === "scale"; const leftRadius = isRounded(endpoints.left) ? "6px" : "0"; const rightRadius = isRounded(endpoints.right) ? "6px" : "0"; return `${leftRadius} ${rightRadius} ${rightRadius} ${leftRadius}`; } _getAboveTargetOverlayInterval(targetPct = null) { if (!Number.isFinite(targetPct)) return null; const start = Math.min(100, Math.max(0, targetPct)); if (start >= 100) return null; return { start, end: 100 }; } _getAboveTargetLayerGeometry(targetPct = null) { const interval = this._getAboveTargetOverlayInterval(targetPct); if (!interval) return null; return { start: interval.start, end: interval.end, hidden: false }; } _getFullScalePaintStyle(ecfg, color, targetPct = null, baselinePct = null, minValue = 0, maxValue = 100) { var _a, _b, _c, _d, _e, _f; const layers = []; const basePaint = this._getBasePaintGradient(color, ecfg, minValue, maxValue); const clampedBaseline = Number.isFinite(baselinePct) ? Math.min(100, Math.max(0, baselinePct)) : null; if (Number.isFinite(clampedBaseline)) { const belowColor = (_c = (_b = (_a = ecfg.baseline) == null ? void 0 : _a.below) == null ? void 0 : _b.color) != null ? _c : null; const aboveColor = (_f = (_e = (_d = ecfg.baseline) == null ? void 0 : _d.above) == null ? void 0 : _e.color) != null ? _f : null; const belowOverlay = this._getOverlayGradient(0, clampedBaseline, belowColor); const aboveOverlay = this._getOverlayGradient(clampedBaseline, 100, aboveColor); if (belowOverlay) layers.push(belowOverlay); if (aboveOverlay) layers.push(aboveOverlay); } if (basePaint) layers.push(basePaint); if (!layers.length) return "display:none;"; return `display:block;inset:0;background-image:${layers.join(",")};background-repeat:no-repeat;background-size:100% 100%;`; } _getRevealShapeStyle(geometry, h) { var _a, _b; const heightValue = typeof h === "number" ? `${h}px` : h; const start = Math.min(100, Math.max(0, (_a = geometry == null ? void 0 : geometry.start) != null ? _a : 0)); const end = Math.min(100, Math.max(0, (_b = geometry == null ? void 0 : geometry.end) != null ? _b : 0)); if (geometry == null ? void 0 : geometry.hidden) { return `display:none;height:${heightValue};clip-path:inset(0 100% 0 0 round 0);`; } const topInset = "0"; const rightInset = `${Math.max(0, 100 - end)}%`; const bottomInset = "0"; const leftInset = `${start}%`; const radii = this._getRevealCornerRadii(geometry); return `display:block;height:${heightValue};clip-path:inset(${topInset} ${rightInset} ${bottomInset} ${leftInset} round ${radii});`; } _getStaticLayerRevealStyle(geometry) { if (!(geometry == null ? void 0 : geometry.hidden) && Number.isFinite(geometry == null ? void 0 : geometry.start) && Number.isFinite(geometry == null ? void 0 : geometry.end) && geometry.end > geometry.start) { const start = Math.min(100, Math.max(0, geometry.start)); const end = Math.min(100, Math.max(0, geometry.end)); return `display:block;clip-path:inset(0 ${Math.max(0, 100 - end)}% 0 ${start}% round 0);`; } return "display:none;clip-path:inset(0 100% 0 0 round 0);"; } _getFillPaintLayers(geometry, h, ecfg, color, targetPct = null, baselinePct = null, minValue = 0, maxValue = 100) { var _a, _b; const basePaintStyle = this._getFullScalePaintStyle(ecfg, color, targetPct, baselinePct, minValue, maxValue); const baseLayer = { id: "base", zIndex: 1, visible: true, paintStyle: basePaintStyle, revealStyle: "display:block;" }; const aboveTargetGeometry = this._getAboveTargetLayerGeometry(targetPct); const aboveTargetLayer = { id: "above-target", zIndex: 2, visible: !!(((_a = ecfg == null ? void 0 : ecfg.bar) == null ? void 0 : _a.above_target_color) && aboveTargetGeometry), paintStyle: ((_b = ecfg == null ? void 0 : ecfg.bar) == null ? void 0 : _b.above_target_color) ? `display:block;inset:0;background:${ecfg.bar.above_target_color};` : "display:none;", revealStyle: aboveTargetGeometry ? this._getStaticLayerRevealStyle(aboveTargetGeometry) : this._getStaticLayerRevealStyle({ start: 0, end: 0, hidden: true }) }; return [baseLayer, aboveTargetLayer]; } _getFillRenderState(pct, h, ecfg, color, targetPct = null, baselinePct = null, minValue = 0, maxValue = 100, needleActive = false) { var _a, _b; const geometry = needleActive ? this._getNormalizedPercent(100, null) : this._getNormalizedPercent(pct, baselinePct); const paintLayers = this._getFillPaintLayers(geometry, h, ecfg, color, targetPct, baselinePct, minValue, maxValue); return { geometry, paintLayers, paintStyle: (_b = (_a = paintLayers[0]) == null ? void 0 : _a.paintStyle) != null ? _b : "display:none;", revealStyle: this._getRevealShapeStyle(geometry, h) }; } _getNeedleRenderState(rawValue, ecfg, minValue = 0, maxValue = 100, baselinePct = null) { var _a, _b, _c, _d, _e, _f, _g, _h, _i; const needle = (_a = ecfg == null ? void 0 : ecfg.bar) == null ? void 0 : _a.needle; if (!(needle == null ? void 0 : needle.show)) { return { show: false, pct: null, color: (_b = needle == null ? void 0 : needle.color) != null ? _b : "#ffffff", borderColor: this._getNeedleBorderColor((_c = needle == null ? void 0 : needle.color) != null ? _c : "#ffffff"), edge: "middle" }; } if (Number.isFinite(baselinePct)) { return { show: false, pct: null, color: (_d = needle.color) != null ? _d : "#ffffff", borderColor: this._getNeedleBorderColor((_e = needle.color) != null ? _e : "#ffffff"), edge: "middle" }; } if (!Number.isFinite(rawValue)) { return { show: false, pct: null, color: (_f = needle.color) != null ? _f : "#ffffff", borderColor: this._getNeedleBorderColor((_g = needle.color) != null ? _g : "#ffffff"), edge: "middle" }; } const pct = Math.min(100, Math.max(0, this._toScalePct(rawValue, minValue, maxValue))); return { show: true, pct, color: (_h = needle.color) != null ? _h : "#ffffff", borderColor: this._getNeedleBorderColor((_i = needle.color) != null ? _i : "#ffffff"), edge: pct <= 0 ? "left" : pct >= 100 ? "right" : "middle" }; } _ensureBaseDom() { if (this._baseDomReady) return; if (this.shadowRoot.querySelector("ha-card")) { this._baseDomReady = true; return; } this.shadowRoot.innerHTML = `
`; this._baseDomReady = true; } _render() { const cfg = this._config; this._ensureBaseDom(); const titleEl = this.shadowRoot.querySelector(".card-title"); if (titleEl) { if (cfg.title) { titleEl.textContent = cfg.title; titleEl.style.display = ""; } else { titleEl.textContent = ""; titleEl.style.display = "none"; } } this._disconnectResizeObserver(); this._resizeObserver = new ResizeObserver(() => { this._applyCompactTier(); this._schedulePostLayoutDensityPass(); }); const surface = this.shadowRoot.querySelector("ha-card"); const card = this.shadowRoot.querySelector(".card"); if (surface && card) { this._applyCompactTier(); this._resizeObserver.observe(surface); this._resizeObserver.observe(this); } this._update(); this._schedulePostLayoutDensityPass(); } _disconnectResizeObserver() { if (!this._resizeObserver) return; this._resizeObserver.disconnect(); this._resizeObserver = null; } _isReliableWidth(width, minWidth = 16) { return Number.isFinite(width) && width >= minWidth; } _getHeroLabelReservedWidth(headerEl, labelEl, labelHidden) { var _a, _b, _c; if (labelHidden || !headerEl || !labelEl) return 0; const headerWidth = Math.floor((_b = (_a = headerEl.getBoundingClientRect) == null ? void 0 : _a.call(headerEl).width) != null ? _b : 0); const naturalLabelWidth = Math.ceil(labelEl.scrollWidth || ((_c = labelEl.getBoundingClientRect) == null ? void 0 : _c.call(labelEl).width) || 0); if (!this._isReliableWidth(headerWidth, 8) || !Number.isFinite(naturalLabelWidth) || naturalLabelWidth <= 0) { return 0; } return Math.min(naturalLabelWidth, headerWidth * 0.45); } _classifyCompactTier(width, currentTier = "normal") { if (!this._isReliableWidth(width)) return currentTier || "normal"; if (width < 180) return "compressed"; if (width < 220) return "dense"; if (width < 280) return "tight"; if (width < 360) return "compact"; return "normal"; } _classifyLeftDensity(width, currentDensity = "normal") { if (!this._isReliableWidth(width)) return currentDensity || "normal"; if (width < 170) return "compressed"; if (width < 210) return "dense"; if (width < 255) return "tight"; if (width < 320) return "compact"; return "normal"; } _classifyRowDensity(width, currentDensity = "normal") { if (!this._isReliableWidth(width)) return currentDensity || "normal"; if (width < 150) return "compressed"; if (width < 190) return "dense"; if (width < 245) return "tight"; if (width < 300) return "compact"; return "normal"; } _schedulePostLayoutDensityPass() { if (!this.isConnected) return; if (this._densityPassScheduled) { this._densityPassDirty = true; return; } this._densityPassScheduled = true; this._densityPassFrame = requestAnimationFrame(() => { var _a, _b; this._densityPassScheduled = false; this._densityPassFrame = null; const runAgain = this._densityPassDirty; this._densityPassDirty = false; if (!this.isConnected) return; const surface = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector("ha-card"); const width = (_b = surface == null ? void 0 : surface.getBoundingClientRect().width) != null ? _b : 0; if (!this._isReliableWidth(width)) { if (this._densityPassRetries < 4) { this._densityPassRetries += 1; this._schedulePostLayoutDensityPass(); } return; } this._densityPassRetries = 0; this._applyCompactTier(); this._runPostLayoutPasses(); if (runAgain) { this._schedulePostLayoutDensityPass(); } }); } _applyCompactTier() { if (!this.shadowRoot) return; const surface = this.shadowRoot.querySelector("ha-card"); const card = this.shadowRoot.querySelector(".card"); if (!surface || !card) return; const width = surface.getBoundingClientRect().width; if (!this._isReliableWidth(width)) { this._schedulePostLayoutDensityPass(); if (!card.dataset.compact) card.dataset.compact = "normal"; return; } card.dataset.compact = this._classifyCompactTier(width, card.dataset.compact); } _applyLeftModeDensity() { if (!this.shadowRoot) return; const densities = ["normal", "compact", "tight", "dense", "compressed"]; this.shadowRoot.querySelectorAll(".main-line.left-mode").forEach((mainLine) => { const width = mainLine.getBoundingClientRect().width; if (!this._isReliableWidth(width)) { this._schedulePostLayoutDensityPass(); if (!mainLine.dataset.leftDensity) mainLine.dataset.leftDensity = "normal"; return; } let density = this._classifyLeftDensity(width, mainLine.dataset.leftDensity); const labelText = mainLine.querySelector(".label-left-text"); const fullLabelWidth = labelText ? labelText.scrollWidth : Number.POSITIVE_INFINITY; const visibleLabelWidth = labelText ? labelText.clientWidth : Number.POSITIVE_INFINITY; const labelIsTruncated = labelText ? fullLabelWidth > visibleLabelWidth + 1 : false; const effectiveLabelWidth = labelIsTruncated ? visibleLabelWidth : fullLabelWidth; let relaxBy = 0; if (Number.isFinite(effectiveLabelWidth)) { if (effectiveLabelWidth <= 72 && width >= 185) relaxBy = 1; if (effectiveLabelWidth <= 44 && width >= 205) relaxBy = 2; } const currentIndex = densities.indexOf(density); if (currentIndex !== -1 && relaxBy > 0) { density = densities[Math.max(0, currentIndex - relaxBy)]; } mainLine.dataset.leftDensity = density; }); } _applyInsideLabelDensity() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".bar-inner-label").forEach((innerLabel) => { var _a, _b, _c, _d, _e, _f; const track = innerLabel.closest(".bar-track"); const mainLine = innerLabel.closest(".main-line"); const nameEl = innerLabel.querySelector(".inside-name"); const valueEl = innerLabel.querySelector(".inside-value"); if (!track || !nameEl || !valueEl) return; const trackWidth = track.getBoundingClientRect().width; const valueDisplay = this._decodeDataAttr(valueEl.dataset.display || valueEl.textContent || ""); const valueUnit = this._decodeDataAttr(valueEl.dataset.unit || ((_a = valueEl.querySelector(".inside-unit")) == null ? void 0 : _a.textContent) || ""); const valueWidth = this._measureInsideValueMarkupWidth(valueEl, valueDisplay, valueUnit, false); const valueOnlyWidth = this._measureInsideValueMarkupWidth(valueEl, valueDisplay, valueUnit, true); let density = this._classifyInsideDensity(trackWidth, valueWidth); const rowWidth = typeof (mainLine == null ? void 0 : mainLine.getBoundingClientRect) === "function" ? mainLine.getBoundingClientRect().width : 0; const rowDensity = this._isReliableWidth(rowWidth) ? this._classifyRowDensity(rowWidth, ((_b = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _b.rowDensity) || "normal") : ((_c = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _c.rowDensity) || "normal"; const iconWrap = (_e = (_d = mainLine == null ? void 0 : mainLine.querySelector) == null ? void 0 : _d.call(mainLine, ".icon-wrap")) != null ? _e : null; let hideIcon = rowDensity === "dense" || rowDensity === "compressed"; const reclaimedWidth = iconWrap ? this._getLeftModeIconWidth(iconWrap, mainLine) + this._getLeftModeGap(mainLine) : 0; if (!hideIcon && valueWidth > this._getInsideValueVisibleCap(trackWidth, density)) { hideIcon = true; } if (iconWrap && hideIcon) { density = this._classifyInsideDensity(trackWidth + reclaimedWidth, valueWidth); } const effectiveTrackWidth = trackWidth + (hideIcon ? reclaimedWidth : 0); let hideName = false; if (rowDensity === "compressed") { density = "compressed"; hideIcon = true; } const rawValueCap = this._getInsideValueVisibleCap(trackWidth, density); const innerPadding = this._getNumericStyleValue(innerLabel, "padding-left", 0) + this._getNumericStyleValue(innerLabel, "padding-right", 0); const valueCap = Math.max(0, rawValueCap - innerPadding); const hideUnit = !!valueUnit && valueWidth > valueCap; const hideValue = valueOnlyWidth > valueCap; const reservedValueWidth = hideValue ? 0 : Math.ceil(hideUnit ? valueOnlyWidth : valueWidth); const labelGap = !hideValue ? this._getNumericStyleValue(innerLabel, "gap", 0) : 0; if (!hideValue) { const nameText = (nameEl.textContent || "").trim(); const nameFullWidth = nameEl.scrollWidth || ((_f = nameEl.getBoundingClientRect) == null ? void 0 : _f.call(nameEl).width) || this._measureTextWidthWithStyles(nameEl, nameText); if (!nameText || !Number.isFinite(nameFullWidth) || nameFullWidth <= 0) { hideName = density === "dense" || density === "compressed"; } else { const usefulNameWidth = this._getInsideUsefulNameWidth(nameEl, nameText, nameFullWidth); const availableNameWidth = Math.max( 0, trackWidth - innerPadding - reservedValueWidth - labelGap ); const visibleChars = this._measureVisibleLabelCharacters(nameEl, nameText, availableNameWidth); const minUsefulChars = Math.min(4, nameText.length); const nameNeedsTruncation = nameFullWidth > availableNameWidth + 1; const hasUsefulRoom = availableNameWidth >= usefulNameWidth && (!nameNeedsTruncation || visibleChars >= minUsefulChars); hideName = !hasUsefulRoom; } } if (hideName && density === "normal") density = "dense"; innerLabel.dataset.insideDensity = density; innerLabel.dataset.hideName = hideName ? "true" : "false"; valueEl.dataset.hideUnit = hideUnit ? "true" : "false"; valueEl.dataset.hideValue = hideValue ? "true" : "false"; if (mainLine) { mainLine.dataset.hideInsideIcon = hideIcon ? "true" : "false"; } }); } _getInsideValueVisibleCap(trackWidth, density) { if (density === "dense" || density === "compressed") { return trackWidth; } return trackWidth * 0.56; } _classifyInsideDensity(trackWidth, valueWidth) { if (trackWidth < Math.max(72, valueWidth + 12)) return "compressed"; if (trackWidth < valueWidth + 56) return "dense"; if (trackWidth < valueWidth + 92) return "tight"; if (trackWidth < valueWidth + 128) return "compact"; return "normal"; } _applyRowDensity() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".main-line").forEach((mainLine) => { const width = mainLine.getBoundingClientRect().width; if (!this._isReliableWidth(width)) { this._schedulePostLayoutDensityPass(); if (!mainLine.dataset.rowDensity) mainLine.dataset.rowDensity = "normal"; return; } mainLine.dataset.rowDensity = this._classifyRowDensity(width, mainLine.dataset.rowDensity); }); } _applyAboveLabelDensity() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".above-line, .hero-line").forEach((aboveLine) => { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t; const label = aboveLine.querySelector(".above-bar-label, .hero-header"); if (!label) return; const isHeroLine = aboveLine.classList.contains("hero-line"); const width = isHeroLine ? this._getHeroDensityWidth(aboveLine) : label.getBoundingClientRect().width; let density = "normal"; if (width < 90) density = "xs"; else if (width < 110) density = "compressed"; else if (width < 150) density = "dense"; else if (width < 210) density = "tight"; else if (width < 280) density = "compact"; if (isHeroLine) { aboveLine.dataset.heroDensity = density; label.dataset.hideName = density === "dense" || density === "compressed" || density === "xs" ? "true" : "false"; aboveLine.dataset.hideHeroIcon = density === "compressed" || density === "xs" ? "true" : "false"; return; } aboveLine.dataset.aboveDensity = density; const labelText = typeof label.querySelector === "function" ? label.querySelector(".above-bar-label-name") : null; const valueEl = typeof label.querySelector === "function" ? label.querySelector(".above-bar-label-value") : null; const display = this._decodeDataAttr(((_a = valueEl == null ? void 0 : valueEl.dataset) == null ? void 0 : _a.display) || ""); const unit = this._decodeDataAttr(((_b = valueEl == null ? void 0 : valueEl.dataset) == null ? void 0 : _b.unit) || ""); const row = (_c = aboveLine.closest) == null ? void 0 : _c.call(aboveLine, ".row"); const mainLine = (_d = row == null ? void 0 : row.querySelector) == null ? void 0 : _d.call(row, ".main-line.above-mode"); const rowDensity = ((_e = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _e.rowDensity) || "normal"; const iconWrap = (_g = (_f = mainLine == null ? void 0 : mainLine.querySelector) == null ? void 0 : _f.call(mainLine, ".icon-wrap")) != null ? _g : null; const iconRect = (_h = iconWrap == null ? void 0 : iconWrap.getBoundingClientRect) == null ? void 0 : _h.call(iconWrap); const iconStyle = iconWrap && typeof getComputedStyle === "function" ? getComputedStyle(iconWrap) : null; const mainIconVisible = !!iconWrap && rowDensity !== "compressed" && (iconStyle == null ? void 0 : iconStyle.display) !== "none" && ((_i = iconRect == null ? void 0 : iconRect.width) != null ? _i : 0) > 0 && ((_j = iconRect == null ? void 0 : iconRect.height) != null ? _j : 0) > 0; let hideName = density === "dense" || density === "compressed"; let hideSpacer = !mainIconVisible; if (labelText && valueEl && display) { const rowStack = (_k = aboveLine.closest) == null ? void 0 : _k.call(aboveLine, ".row-stack"); const lineWidth = (_o = (_n = (_l = rowStack == null ? void 0 : rowStack.getBoundingClientRect) == null ? void 0 : _l.call(rowStack).width) != null ? _n : (_m = aboveLine.getBoundingClientRect) == null ? void 0 : _m.call(aboveLine).width) != null ? _o : width; const spacerEl = typeof aboveLine.querySelector === "function" ? aboveLine.querySelector(".above-icon-spacer") : null; const spacerWidth = (_q = (_p = spacerEl == null ? void 0 : spacerEl.getBoundingClientRect) == null ? void 0 : _p.call(spacerEl).width) != null ? _q : 0; const lineGap = spacerEl ? this._getNumericStyleValue(aboveLine, "gap", 0) : 0; const nameWidth = (_t = (_s = (_r = labelText.getBoundingClientRect) == null ? void 0 : _r.call(labelText).width) != null ? _s : labelText.clientWidth) != null ? _t : 0; const labelGap = this._getNumericStyleValue(label, "gap", this._getLeftModeGap(aboveLine)); const fullValueWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, false) + 2); const valueOnlyWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, true) + 2); const text = (labelText.textContent || "").trim(); const visibleWidth = labelText.clientWidth; const fullWidth = labelText.scrollWidth; const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); const labelIsUnhelpful = this._shouldHideLeftLabel(text, fullWidth, visibleWidth, visibleChars); const spacerReserve = mainIconVisible && spacerWidth > 0 ? spacerWidth + lineGap : 0; const availableWithName = Math.max(0, lineWidth - spacerReserve - nameWidth - labelGap); const availableValueOnly = Math.max(0, lineWidth); hideName = labelIsUnhelpful; if (!hideName && fullValueWidth <= availableWithName) { hideSpacer = !mainIconVisible; } else if (!hideName && valueOnlyWidth <= availableWithName) { hideSpacer = !mainIconVisible; } else { hideName = true; hideSpacer = true; } const availableWidth = hideName ? availableValueOnly : availableWithName; const hideUnit = !!unit && fullValueWidth > availableWidth; valueEl.dataset.hideUnit = hideUnit ? "true" : "false"; } else if (valueEl) { valueEl.dataset.hideUnit = "false"; } label.dataset.hideName = hideName ? "true" : "false"; aboveLine.dataset.hideAboveIcon = hideSpacer ? "true" : "false"; }); } _getHeroDensityWidth(heroLine) { var _a, _b, _c, _d, _e, _f, _g, _h, _i; const row = (_a = heroLine == null ? void 0 : heroLine.closest) == null ? void 0 : _a.call(heroLine, ".row"); const rowStack = (_b = heroLine == null ? void 0 : heroLine.closest) == null ? void 0 : _b.call(heroLine, ".row-stack"); const mainLine = (_c = rowStack == null ? void 0 : rowStack.querySelector) == null ? void 0 : _c.call(rowStack, ".main-line.hero-mode"); const barWrap = (_d = mainLine == null ? void 0 : mainLine.querySelector) == null ? void 0 : _d.call(mainLine, ".bar-wrap"); const candidates = [ (_e = row == null ? void 0 : row.getBoundingClientRect) == null ? void 0 : _e.call(row).width, (_f = rowStack == null ? void 0 : rowStack.getBoundingClientRect) == null ? void 0 : _f.call(rowStack).width, (_g = mainLine == null ? void 0 : mainLine.getBoundingClientRect) == null ? void 0 : _g.call(mainLine).width, (_h = barWrap == null ? void 0 : barWrap.getBoundingClientRect) == null ? void 0 : _h.call(barWrap).width, (_i = heroLine == null ? void 0 : heroLine.getBoundingClientRect) == null ? void 0 : _i.call(heroLine).width ]; for (const width of candidates) { if (this._isReliableWidth(width, 8)) return width; } return 0; } _measureHeroValueWidth(heroLine, valueEl, valueFit = "normal", hideUnit = false) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; const layer = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".measure-layer"); if (!layer || !heroLine || !valueEl) return 0; const display = this._decodeDataAttr(valueEl.dataset.display || valueEl.textContent || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); if (!display) return 0; const wrapper = document.createElement("div"); wrapper.className = "hero-line"; wrapper.dataset.heroSize = heroLine.dataset.heroSize || "medium"; wrapper.dataset.heroDensity = heroLine.dataset.heroDensity || "normal"; wrapper.dataset.heroValueFit = valueFit; wrapper.dataset.hideHeroUnit = hideUnit ? "true" : "false"; wrapper.style.display = "inline-block"; this._setStyleIfChanged( wrapper, "--sbcp-hero-base-size", ((_c = (_b = heroLine.style) == null ? void 0 : _b.getPropertyValue) == null ? void 0 : _c.call(_b, "--sbcp-hero-base-size")) || null ); const measureValue = document.createElement("span"); measureValue.className = "hero-value"; measureValue.dataset.display = valueEl.dataset.display || ""; measureValue.dataset.unit = valueEl.dataset.unit || ""; measureValue.innerHTML = this._formatRightValueMarkup(display, unit, hideUnit); measureValue.style.display = "inline-flex"; measureValue.style.flex = "0 0 auto"; measureValue.style.width = "auto"; measureValue.style.minWidth = "0"; measureValue.style.maxWidth = "none"; measureValue.style.justifyContent = "flex-start"; measureValue.style.justifySelf = "start"; measureValue.style.overflow = "visible"; const text = measureValue.querySelector(".value-right-text"); if (text) { text.style.display = "inline-flex"; text.style.flex = "0 0 auto"; text.style.width = "auto"; text.style.minWidth = "0"; text.style.maxWidth = "none"; text.style.justifyContent = "flex-start"; text.style.overflow = "visible"; } const number = measureValue.querySelector(".value-right-number"); if (number) { number.style.flex = "0 0 auto"; number.style.minWidth = "0"; number.style.overflow = "visible"; number.style.textOverflow = "clip"; } const unitGroup = measureValue.querySelector(".unit-group"); if (unitGroup) { unitGroup.style.flex = "0 0 auto"; unitGroup.style.minWidth = "0"; unitGroup.style.overflow = "visible"; } wrapper.appendChild(measureValue); layer.replaceChildren(wrapper); return Math.max( Math.ceil((_e = (_d = measureValue.getBoundingClientRect) == null ? void 0 : _d.call(measureValue).width) != null ? _e : 0), Math.ceil(measureValue.scrollWidth || 0), Math.ceil((_h = (_g = (_f = text == null ? void 0 : text.getBoundingClientRect) == null ? void 0 : _f.call(text).width) != null ? _g : text == null ? void 0 : text.scrollWidth) != null ? _h : 0), Math.ceil((_k = (_j = (_i = number == null ? void 0 : number.getBoundingClientRect) == null ? void 0 : _i.call(number).width) != null ? _j : number == null ? void 0 : number.scrollWidth) != null ? _k : 0), Math.ceil((_n = (_m = (_l = unitGroup == null ? void 0 : unitGroup.getBoundingClientRect) == null ? void 0 : _l.call(unitGroup).width) != null ? _m : unitGroup == null ? void 0 : unitGroup.scrollWidth) != null ? _n : 0) ); } _applyHeroValueFit() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".hero-line").forEach((heroLine) => { var _a, _b; const headerEl = heroLine.querySelector(".hero-header"); const labelEl = heroLine.querySelector(".hero-label"); const valueEl = heroLine.querySelector(".hero-value"); const unitGroup = heroLine.querySelector(".unit-group"); if (!headerEl || !valueEl) return; heroLine.dataset.hideHeroUnit = "false"; heroLine.dataset.heroValueFit = "normal"; delete headerEl.dataset.priorityHideName; const headerWidth = Math.floor((_b = (_a = headerEl.getBoundingClientRect) == null ? void 0 : _a.call(headerEl).width) != null ? _b : 0); if (!this._isReliableWidth(headerWidth, 8)) { this._schedulePostLayoutDensityPass(); return; } const hasUnit = !!unitGroup && unitGroup.textContent.trim().length > 0; const labelHiddenByDensity = headerEl.dataset.hideName === "true"; const visibleLabelGap = !labelHiddenByDensity && labelEl ? this._getNumericStyleValue(headerEl, "column-gap", 0) : 0; const valueWidth = (valueFit = "normal", hideUnit = false) => this._measureHeroValueWidth(heroLine, valueEl, valueFit, hideUnit); const availableWithLabel = Math.max(0, headerWidth - visibleLabelGap - 4); const availableWithoutLabel = Math.max(0, headerWidth - 4); if (!this._isReliableWidth(availableWithoutLabel, 8)) { heroLine.dataset.hideHeroUnit = hasUnit ? "true" : "false"; heroLine.dataset.heroValueFit = "minimum"; this._schedulePostLayoutDensityPass(); return; } if (valueWidth("normal", false) <= availableWithLabel) return; if (!labelHiddenByDensity && labelEl) { headerEl.dataset.priorityHideName = "true"; if (valueWidth("normal", false) <= availableWithoutLabel) return; } if (hasUnit) { heroLine.dataset.hideHeroUnit = "true"; if (valueWidth("normal", true) <= availableWithoutLabel) return; } heroLine.dataset.heroValueFit = "tight"; if (valueWidth("tight", hasUnit) <= availableWithoutLabel) return; heroLine.dataset.heroValueFit = "minimum"; if (valueWidth("minimum", hasUnit) <= availableWithoutLabel) return; heroLine.dataset.heroValueFit = "hidden"; }); } _measureValueMarkupWidth(valueEl, display, unit, hideUnit) { var _a; const layer = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".measure-layer"); if (!layer || !valueEl) return 0; const clone = valueEl.cloneNode(false); clone.removeAttribute("data-hide-unit"); clone.style.removeProperty("--sbcp-value-extra-width"); clone.style.width = "auto"; clone.style.minWidth = "0"; clone.style.maxWidth = "none"; clone.style.flex = "0 0 auto"; clone.innerHTML = this._formatRightValueMarkup(display, unit, hideUnit); layer.replaceChildren(clone); return clone.scrollWidth; } _measureInsideValueMarkupWidth(valueEl, display, unit, hideUnit = false) { var _a; const layer = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".measure-layer"); if (!layer || !valueEl) return (valueEl == null ? void 0 : valueEl.scrollWidth) || 0; const clone = valueEl.cloneNode(false); clone.style.width = "auto"; clone.style.minWidth = "0"; clone.style.maxWidth = "none"; clone.style.flex = "0 0 auto"; clone.style.overflow = "visible"; clone.style.textOverflow = "clip"; clone.style.whiteSpace = "nowrap"; clone.innerHTML = this._formatInsideValueMarkup(display, unit, hideUnit); layer.replaceChildren(clone); let extraWidth = 0; try { const style = getComputedStyle(valueEl); extraWidth += parseFloat(style.paddingLeft || "0") || 0; extraWidth += parseFloat(style.paddingRight || "0") || 0; extraWidth += parseFloat(style.borderLeftWidth || "0") || 0; extraWidth += parseFloat(style.borderRightWidth || "0") || 0; } catch (_err) { } return clone.getBoundingClientRect().width + extraWidth; } _measureTextWidthWithStyles(sourceEl, text) { var _a; const layer = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".measure-layer"); if (!layer || !sourceEl) return 0; const clone = sourceEl.cloneNode(false); clone.textContent = text; clone.style.width = "auto"; clone.style.minWidth = "0"; clone.style.maxWidth = "none"; clone.style.flex = "0 0 auto"; clone.style.overflow = "visible"; clone.style.textOverflow = "clip"; clone.style.whiteSpace = "nowrap"; layer.replaceChildren(clone); return clone.scrollWidth; } _measureVisibleLabelCharacters(labelTextEl, text, visibleWidth) { if (!labelTextEl || !text || !Number.isFinite(visibleWidth) || visibleWidth <= 0) return 0; const ellipsisWidth = this._measureTextWidthWithStyles(labelTextEl, "..."); const availableTextWidth = Math.max(0, visibleWidth - ellipsisWidth); if (availableTextWidth <= 0) return 0; let low = 0; let high = text.length; while (low < high) { const mid = Math.ceil((low + high) / 2); const width = this._measureTextWidthWithStyles(labelTextEl, text.slice(0, mid)); if (width <= availableTextWidth) { low = mid; } else { high = mid - 1; } } return low; } _shouldHideLeftLabel(text, fullWidth, visibleWidth, visibleChars) { if (!text) return false; if (!Number.isFinite(fullWidth) || !Number.isFinite(visibleWidth)) return false; const truncated = fullWidth > visibleWidth + 1; return truncated && visibleChars < 5; } _getInsideUsefulNameWidth(labelTextEl, text, fullWidth = NaN) { if (!text) return 0; const naturalWidth = Number.isFinite(fullWidth) && fullWidth > 0 ? fullWidth : this._measureTextWidthWithStyles(labelTextEl, text); const usefulChars = text.slice(0, Math.min(5, text.length)); const usefulWidth = this._measureTextWidthWithStyles(labelTextEl, usefulChars) + this._measureTextWidthWithStyles(labelTextEl, "..."); const minUsefulWidth = Math.max(36, Math.min(44, usefulWidth || 0)); return Math.min(naturalWidth || minUsefulWidth, minUsefulWidth); } _applyValueWidthReservation() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".value-right").forEach((valueEl) => { var _a, _b, _c; const display = this._decodeDataAttr(valueEl.dataset.display || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); if (!display) { valueEl.style.setProperty("--sbcp-value-extra-width", "0px"); return; } const getStyle = typeof globalThis.getComputedStyle === "function" && globalThis.getComputedStyle.bind(globalThis) || typeof window !== "undefined" && typeof window.getComputedStyle === "function" && window.getComputedStyle.bind(window) || ((_c = (_b = (_a = valueEl == null ? void 0 : valueEl.ownerDocument) == null ? void 0 : _a.defaultView) == null ? void 0 : _b.getComputedStyle) == null ? void 0 : _c.bind(valueEl.ownerDocument.defaultView)); if (!getStyle) return; const style = getStyle(valueEl); const baseWidth = parseFloat(style.getPropertyValue("--sbcp-value-width")) || valueEl.clientWidth || 0; const desiredWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, false) + 2); const extraWidth = Math.max(0, desiredWidth - baseWidth); valueEl.style.setProperty("--sbcp-value-extra-width", `${extraWidth}px`); }); } _applyValueVisibility() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".value-right, .top-right-value, .above-bar-label-value").forEach((valueEl) => { var _a, _b, _c, _d; const display = this._decodeDataAttr(valueEl.dataset.display || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); let hideUnit = valueEl.dataset.hideUnit === "true"; const isAboveValue = (_a = valueEl.classList) == null ? void 0 : _a.contains("above-bar-label-value"); if (!isAboveValue && display) { const availableWidth = (_d = (_c = (_b = valueEl.getBoundingClientRect) == null ? void 0 : _b.call(valueEl).width) != null ? _c : valueEl.clientWidth) != null ? _d : 0; const fullValueWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, false) + 2); hideUnit = !!unit && availableWidth > 0 ? fullValueWidth > availableWidth : false; valueEl.dataset.hideUnit = hideUnit ? "true" : "false"; } if (valueEl.innerHTML !== this._formatRightValueMarkup(display, unit, hideUnit)) { valueEl.innerHTML = this._formatRightValueMarkup(display, unit, hideUnit); } }); this.shadowRoot.querySelectorAll(".inside-value").forEach((valueEl) => { const display = this._decodeDataAttr(valueEl.dataset.display || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); const hideUnit = valueEl.dataset.hideUnit === "true"; const hideValue = valueEl.dataset.hideValue === "true"; if (!hideValue && !display) return; if (!valueEl.dataset.hideUnit) valueEl.dataset.hideUnit = "false"; if (!valueEl.dataset.hideValue) valueEl.dataset.hideValue = "false"; const nextMarkup = this._formatInsideValueMarkup(display, unit, hideUnit); if (valueEl.innerHTML !== nextMarkup) { valueEl.innerHTML = nextMarkup; } }); } _getMinimumBarShare() { return 0.5; } _getMinimumBarShareHysteresis() { return 0.02; } _getTopValueEnableShare() { return this._getMinimumBarShare() - this._getMinimumBarShareHysteresis(); } _getTopValueDisableShare() { return this._getMinimumBarShare() + this._getMinimumBarShareHysteresis(); } _getNumericStyleValue(el, propertyName, fallback = 0) { if (!el) return fallback; try { const value = parseFloat(getComputedStyle(el).getPropertyValue(propertyName)); return Number.isFinite(value) ? value : fallback; } catch (_err) { return fallback; } } _getLeftModeGap(mainLine) { var _a; const computedGap = this._getNumericStyleValue(mainLine, "gap", NaN); if (Number.isFinite(computedGap)) return computedGap; const density = ((_a = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _a.rowDensity) || "normal"; if (density === "tight") return 7; if (density === "dense" || density === "compressed") return 6; return 8; } _getLeftModeBarMinWidth(mainLine) { var _a; const computedMin = this._getNumericStyleValue(mainLine, "--sbcp-bar-min-width", NaN); if (Number.isFinite(computedMin)) return computedMin; const density = ((_a = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _a.leftDensity) || "normal"; if (density === "compact") return 52; if (density === "tight") return 48; if (density === "dense") return 44; if (density === "compressed") return 40; return 56; } _getLeftModeIconWidth(iconWrap, mainLine) { var _a, _b; const measured = (_a = iconWrap == null ? void 0 : iconWrap.getBoundingClientRect) == null ? void 0 : _a.call(iconWrap).width; if (this._isReliableWidth(measured, 1)) return measured; const computed = this._getNumericStyleValue(iconWrap || mainLine, "--sbcp-icon-width", NaN); if (Number.isFinite(computed)) return computed; const density = ((_b = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _b.leftDensity) || "normal"; if (density === "compact") return 26; if (density === "tight") return 24; if (density === "dense") return 23; if (density === "compressed") return 22; return 28; } _getReservedInlineValueWidth(valueEl) { var _a, _b, _c; if (!valueEl) return 0; const display = this._decodeDataAttr(valueEl.dataset.display || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); const baseWidth = this._getNumericStyleValue(valueEl, "--sbcp-value-width", valueEl.clientWidth || 0); const inlineExtra = parseFloat(((_b = (_a = valueEl.style) == null ? void 0 : _a.getPropertyValue) == null ? void 0 : _b.call(_a, "--sbcp-value-extra-width")) || ((_c = valueEl.style) == null ? void 0 : _c["--sbcp-value-extra-width"]) || "0"); const extraWidth = Number.isFinite(inlineExtra) ? inlineExtra : this._getNumericStyleValue(valueEl, "--sbcp-value-extra-width", 0); const reservedWidth = Math.max(0, baseWidth + extraWidth); if (!display) return reservedWidth; const fullMarkupWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, false) + 2); return Math.max(reservedWidth, fullMarkupWidth); } _estimateLeftModeWidthBudget(row) { var _a, _b, _c, _d, _e, _f; const mainLine = row == null ? void 0 : row.querySelector(".main-line"); if (!mainLine) return null; const rowWidth = (_b = (_a = mainLine.getBoundingClientRect) == null ? void 0 : _a.call(mainLine).width) != null ? _b : 0; if (!this._isReliableWidth(rowWidth)) return null; const labelWrap = row.querySelector(".label-left"); const iconWrap = row.querySelector(".icon-wrap"); const valueEl = row.querySelector(".value-right"); const labelMetrics = this._getLabelSacrificeMetrics(row, "left", { rowWidth }); const labelWidth = ((_c = labelWrap == null ? void 0 : labelWrap.dataset) == null ? void 0 : _c.hidden) === "true" ? 0 : (_f = (_e = (_d = labelWrap == null ? void 0 : labelWrap.getBoundingClientRect) == null ? void 0 : _d.call(labelWrap).width) != null ? _e : labelMetrics == null ? void 0 : labelMetrics.labelWidth) != null ? _f : 0; const iconWidth = iconWrap ? this._getLeftModeIconWidth(iconWrap, mainLine) : 0; const valueWidth = this._getReservedInlineValueWidth(valueEl); const gap = this._getLeftModeGap(mainLine); const barMinWidth = this._getLeftModeBarMinWidth(mainLine); const baseLabelVisible = !!labelWrap && labelWrap.dataset.hidden !== "true"; const labelSacrificial = baseLabelVisible ? this._isLabelWorthSacrificing(row, "left", { rowWidth }) : true; const hasIcon = !!iconWrap; return { rowWidth, gap, barMinWidth, labelWidth: this._isReliableWidth(labelWidth, 0) ? labelWidth : 0, iconWidth: this._isReliableWidth(iconWidth, 0) ? iconWidth : 0, valueWidth: this._isReliableWidth(valueWidth, 0) ? valueWidth : 0, baseLabelVisible, labelSacrificial, hasIcon, mainLine, labelWrap, iconWrap, valueEl, rowStack: row.querySelector(".row-stack") }; } _predictLeftModeBarShareForState(row, state, budget = null) { const effectiveBudget = budget || this._estimateLeftModeWidthBudget(row); if (!effectiveBudget) return null; const showLabel = effectiveBudget.baseLabelVisible && !state.hideLabel; const showIcon = effectiveBudget.hasIcon && !state.hideIcon; const showInlineValue = !state.topValue; const visibleItems = 1 + (showIcon ? 1 : 0) + (showLabel ? 1 : 0) + (showInlineValue ? 1 : 0); const gapCount = Math.max(0, visibleItems - 1); const reservedWidth = (showIcon ? effectiveBudget.iconWidth : 0) + (showLabel ? effectiveBudget.labelWidth : 0) + (showInlineValue ? effectiveBudget.valueWidth : 0) + gapCount * effectiveBudget.gap; const predictedBarWidth = Math.max(0, effectiveBudget.rowWidth - reservedWidth); return { rowWidth: effectiveBudget.rowWidth, barWidth: predictedBarWidth, share: predictedBarWidth / effectiveBudget.rowWidth, showLabel, showIcon, showInlineValue, reservedWidth, gapCount }; } _getLeftModeCandidateStates(budget) { const states = [ { hideLabel: false, topValue: false, hideIcon: false } ]; if (budget == null ? void 0 : budget.labelSacrificial) { states.push({ hideLabel: true, topValue: false, hideIcon: false }); } states.push( { hideLabel: false, topValue: true, hideIcon: false }, { hideLabel: true, topValue: true, hideIcon: false }, { hideLabel: true, topValue: true, hideIcon: true } ); return states; } _chooseFirstPredictedLeftModeState(row, states, threshold, budget) { for (const state of states) { const predicted = this._predictLeftModeBarShareForState(row, state, budget); if (!predicted) continue; if (predicted.share >= threshold) return { ...state, predicted }; } return null; } _chooseFallbackPredictedLeftModeState(row, states, budget) { let fallback = null; for (const state of states) { const predicted = this._predictLeftModeBarShareForState(row, state, budget); if (!predicted) continue; fallback = { ...state, predicted }; } return fallback; } _chooseLeftModeResponsiveState(row) { var _a, _b; const budget = this._estimateLeftModeWidthBudget(row); if (!budget) return null; const minimumBarShare = this._getMinimumBarShare(); const states = this._getLeftModeCandidateStates(budget); const previousTopValue = ((_b = (_a = budget.rowStack) == null ? void 0 : _a.dataset) == null ? void 0 : _b.forceTopValue) === "true"; const inlineStates = states.filter((state) => !state.topValue); const topStates = states.filter((state) => state.topValue); const enableShare = this._getTopValueEnableShare(); const disableShare = this._getTopValueDisableShare(); const inlineChoice = previousTopValue ? this._chooseFirstPredictedLeftModeState(row, inlineStates, disableShare, budget) : this._chooseFirstPredictedLeftModeState(row, inlineStates, enableShare, budget); if (inlineChoice) return inlineChoice; const topChoice = this._chooseFirstPredictedLeftModeState(row, topStates, minimumBarShare, budget) || this._chooseFallbackPredictedLeftModeState(row, topStates, budget); return topChoice; } _applyLeftModeResponsiveState(row, state) { const mainLine = row == null ? void 0 : row.querySelector(".main-line"); const rowStack = row == null ? void 0 : row.querySelector(".row-stack"); const leftLabel = row == null ? void 0 : row.querySelector(".label-left"); if (!mainLine || !rowStack) return; delete rowStack.dataset.forceTopValue; delete mainLine.dataset.hideLeftIcon; if (leftLabel) delete leftLabel.dataset.priorityHidden; if ((state == null ? void 0 : state.hideLabel) && leftLabel) { leftLabel.dataset.priorityHidden = "true"; } if (state == null ? void 0 : state.topValue) { rowStack.dataset.forceTopValue = "true"; } if (state == null ? void 0 : state.hideIcon) { mainLine.dataset.hideLeftIcon = "true"; } } _getMeasuredBarShare(row) { const mainLine = row == null ? void 0 : row.querySelector(".main-line"); const track = row == null ? void 0 : row.querySelector(".bar-track"); if (!mainLine || !track) return null; const rowWidth = mainLine.getBoundingClientRect().width; const barWidth = track.getBoundingClientRect().width; if (!this._isReliableWidth(rowWidth) || !this._isReliableWidth(barWidth, 1)) return null; return { rowWidth, barWidth, share: barWidth / rowWidth, mainLine, track }; } _clearMinimumBarShareOverrides(row) { const mainLine = row == null ? void 0 : row.querySelector(".main-line"); const rowStack = row == null ? void 0 : row.querySelector(".row-stack"); const leftLabel = row == null ? void 0 : row.querySelector(".label-left"); const aboveLabel = row == null ? void 0 : row.querySelector(".above-bar-label"); const innerLabel = row == null ? void 0 : row.querySelector(".bar-inner-label"); const aboveLine = row == null ? void 0 : row.querySelector(".above-line"); if (rowStack) delete rowStack.dataset.forceTopValue; if (leftLabel) delete leftLabel.dataset.priorityHidden; if (aboveLabel) delete aboveLabel.dataset.priorityHideName; if (innerLabel) delete innerLabel.dataset.priorityHideName; if (!mainLine) return; delete mainLine.dataset.hideLeftIcon; delete mainLine.dataset.hideAboveIcon; delete mainLine.dataset.priorityHideInsideIcon; } _hideMinimumBarShareLabel(row, mode) { if (mode === "left") { const leftLabel = row.querySelector(".label-left"); if (leftLabel) leftLabel.dataset.priorityHidden = "true"; return; } if (mode === "above") { const aboveLabel = row.querySelector(".above-bar-label"); if (aboveLabel) aboveLabel.dataset.priorityHideName = "true"; return; } if (mode === "inside") { const innerLabel = row.querySelector(".bar-inner-label"); if (innerLabel) innerLabel.dataset.priorityHideName = "true"; } } _forceMinimumBarShareTopValue(row, mode) { if (mode !== "left") return; const rowStack = row.querySelector(".row-stack"); if (rowStack) rowStack.dataset.forceTopValue = "true"; } _hideMinimumBarShareIcon(row, mode) { const mainLine = row.querySelector(".main-line"); if (!mainLine) return; if (mode === "left") { mainLine.dataset.hideLeftIcon = "true"; return; } if (mode === "above") { mainLine.dataset.hideAboveIcon = "true"; const aboveLine = row.querySelector(".above-line"); if (aboveLine) aboveLine.dataset.hideAboveIcon = "true"; return; } if (mode === "inside") { mainLine.dataset.priorityHideInsideIcon = "true"; } } _getLabelSacrificeMetrics(row, mode, measurement) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; const rowWidth = (_d = (_c = measurement == null ? void 0 : measurement.rowWidth) != null ? _c : (_b = (_a = row == null ? void 0 : row.querySelector(".main-line")) == null ? void 0 : _a.getBoundingClientRect) == null ? void 0 : _b.call(_a).width) != null ? _d : 0; if (!this._isReliableWidth(rowWidth)) return null; if (mode === "left") { const labelWrap = row.querySelector(".label-left"); const labelText = row.querySelector(".label-left-text"); if (!labelWrap || !labelText) return null; const text = (labelText.textContent || "").trim(); const visibleWidth = labelText.clientWidth; const fullWidth = labelText.scrollWidth; const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); const labelWidth = (_f = (_e = labelWrap.getBoundingClientRect) == null ? void 0 : _e.call(labelWrap).width) != null ? _f : visibleWidth; return { text, visibleWidth, fullWidth, visibleChars, labelWidth, rowWidth }; } if (mode === "above") { const labelText = row.querySelector(".above-bar-label-name"); if (!labelText) return null; const text = (labelText.textContent || "").trim(); const visibleWidth = labelText.clientWidth; const fullWidth = labelText.scrollWidth; const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); const labelWidth = (_h = (_g = labelText.getBoundingClientRect) == null ? void 0 : _g.call(labelText).width) != null ? _h : visibleWidth; return { text, visibleWidth, fullWidth, visibleChars, labelWidth, rowWidth }; } if (mode === "inside") { const labelText = row.querySelector(".inside-name"); if (!labelText) return null; const text = (labelText.textContent || "").trim(); const visibleWidth = labelText.clientWidth; const fullWidth = labelText.scrollWidth; const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); const labelWidth = (_j = (_i = labelText.getBoundingClientRect) == null ? void 0 : _i.call(labelText).width) != null ? _j : visibleWidth; return { text, visibleWidth, fullWidth, visibleChars, labelWidth, rowWidth }; } return null; } _isLabelWorthSacrificing(row, mode, measurement) { const metrics = this._getLabelSacrificeMetrics(row, mode, measurement); if (!metrics || !metrics.text) return false; return this._shouldHideLeftLabel(metrics.text, metrics.fullWidth, metrics.visibleWidth, metrics.visibleChars); } _ensureMinimumBarShare(rows = null) { if (!this.shadowRoot) return; const targetRows = rows || this.shadowRoot.querySelectorAll(".row[data-entity]"); const minimumBarShare = this._getMinimumBarShare(); targetRows.forEach((row) => { const mainLine = row.querySelector(".main-line"); if (!mainLine) return; const mode = mainLine.classList.contains("left-mode") ? "left" : mainLine.classList.contains("above-mode") ? "above" : mainLine.classList.contains("inside-mode") ? "inside" : "other"; if (mode === "other") return; if (mode === "left") { const state = this._chooseLeftModeResponsiveState(row); if (state) this._applyLeftModeResponsiveState(row, state); return; } this._clearMinimumBarShareOverrides(row); let measurement = this._getMeasuredBarShare(row); if (!measurement || measurement.share >= minimumBarShare) return; if (this._isLabelWorthSacrificing(row, mode, measurement)) { this._hideMinimumBarShareLabel(row, mode); measurement = this._getMeasuredBarShare(row); if (!measurement || measurement.share >= minimumBarShare) return; } this._forceMinimumBarShareTopValue(row, mode); this._applyTopRightValueLayout(); measurement = this._getMeasuredBarShare(row); if (!measurement || measurement.share >= minimumBarShare) return; this._hideMinimumBarShareIcon(row, mode); }); } _shouldUseTopValueRow(mainLine) { var _a, _b, _c; if (!((_a = mainLine == null ? void 0 : mainLine.classList) == null ? void 0 : _a.contains("left-mode"))) return false; return ((_c = (_b = mainLine.closest) == null ? void 0 : _b.call(mainLine, ".row-stack")) == null ? void 0 : _c.dataset.forceTopValue) === "true"; } _getAdaptiveDensityForMainLine(mainLine) { var _a; if (!mainLine) return "normal"; if ((_a = mainLine.classList) == null ? void 0 : _a.contains("left-mode")) { return mainLine.dataset.leftDensity || "normal"; } return mainLine.dataset.rowDensity || "normal"; } _getAdaptiveDefaultHeightForDensity(density) { if (density === "compressed") return 24; if (density === "dense") return 28; return 38; } _getEffectiveRowHeight(baseHeight, heightExplicit, mainLine) { if (heightExplicit) return this._clampSupportedRowHeight(baseHeight); return this._clampSupportedRowHeight(this._getAdaptiveDefaultHeightForDensity(this._getAdaptiveDensityForMainLine(mainLine))); } _applyAdaptiveRowHeight() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".row[data-entity]").forEach((row) => { const mainLine = row.querySelector(".main-line"); const rowStack = row.querySelector(".row-stack"); if (!mainLine) return; const baseHeight = parseFloat(row.dataset.baseHeight || "38") || 38; const explicit = row.dataset.heightExplicit === "true"; const effectiveHeight = this._getEffectiveRowHeight(baseHeight, explicit, mainLine); row.style.setProperty("--sbcp-row-height", `${effectiveHeight}px`); if (rowStack) rowStack.style.setProperty("--sbcp-row-height", `${effectiveHeight}px`); mainLine.style.height = `${effectiveHeight}px`; const labelLeft = mainLine.querySelector(".label-left"); if (labelLeft) labelLeft.style.height = `${effectiveHeight}px`; const iconWrap = mainLine.querySelector(".icon-wrap"); if (iconWrap) { iconWrap.style.height = `${effectiveHeight}px`; iconWrap.style.minHeight = `${effectiveHeight}px`; } const track = mainLine.querySelector(".bar-track"); if (track) track.style.height = `${effectiveHeight}px`; const inlineValue = mainLine.querySelector(".value-right"); if (inlineValue) inlineValue.style.height = `${effectiveHeight}px`; }); } _applyTopRightValueLayout() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".main-line.left-mode").forEach((mainLine) => { var _a, _b, _c, _d, _e; const rowStack = mainLine.closest(".row-stack"); const inlineValue = mainLine.querySelector(".value-right"); const topValue = rowStack == null ? void 0 : rowStack.querySelector(".top-right-value"); if (!rowStack || !inlineValue || !topValue) return; const active = this._shouldUseTopValueRow(mainLine); rowStack.dataset.topValue = active ? "true" : "false"; topValue.dataset.active = active ? "true" : "false"; const display = this._decodeDataAttr(inlineValue.dataset.display || ""); const unit = this._decodeDataAttr(inlineValue.dataset.unit || ""); topValue.dataset.display = inlineValue.dataset.display || ""; topValue.dataset.unit = inlineValue.dataset.unit || ""; topValue.dataset.hideUnit = "false"; const availableWidth = (_e = (_d = (_c = (_a = rowStack.getBoundingClientRect) == null ? void 0 : _a.call(rowStack).width) != null ? _c : (_b = topValue.getBoundingClientRect) == null ? void 0 : _b.call(topValue).width) != null ? _d : topValue.clientWidth) != null ? _e : 0; const fullValueWidth = display ? Math.ceil(this._measureValueMarkupWidth(topValue, display, unit, false) + 2) : 0; const hideUnit = !!unit && availableWidth > 0 && fullValueWidth > availableWidth; topValue.dataset.hideUnit = hideUnit ? "true" : "false"; topValue.innerHTML = this._formatRightValueMarkup(display, unit, hideUnit); }); } _applyLeftLabelUsefulness() { if (!this.shadowRoot) return; this.shadowRoot.querySelectorAll(".main-line.left-mode").forEach((mainLine) => { const labelWrap = mainLine.querySelector(".label-left"); const labelText = mainLine.querySelector(".label-left-text"); if (!labelWrap || !labelText) return; labelWrap.dataset.hidden = "false"; const text = (labelText.textContent || "").trim(); const fullWidth = labelText.scrollWidth; const visibleWidth = labelText.clientWidth; const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); const shouldHide = this._shouldHideLeftLabel(text, fullWidth, visibleWidth, visibleChars); labelWrap.dataset.hidden = shouldHide ? "true" : "false"; }); } _runPostLayoutPasses(rows = null) { requestAnimationFrame(() => { this._applyRowDensity(); this._applyLeftModeDensity(); this._applyAboveLabelDensity(); this._applyHeroValueFit(); this._applyInsideLabelDensity(); this._applyValueWidthReservation(); requestAnimationFrame(() => { var _a; this._applyAdaptiveRowHeight(); this._applyValueVisibility(); this._applyLeftLabelUsefulness(); this._applyTopRightValueLayout(); this._ensureMinimumBarShare(rows); this._applyTopRightValueLayout(); this._applyLeftLabelUsefulness(); const targetRows = rows || ((_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll(".row[data-entity]")) || []; targetRows.forEach((row) => { this._positionTargetLabel(row); }); }); }); } _isTightUnit(unit) { return ["h", "m", "s"].includes(String(unit || "").trim()); } _encodeDataAttr(value) { return encodeURIComponent(String(value != null ? value : "")); } _decodeDataAttr(value) { const raw = String(value != null ? value : ""); try { return decodeURIComponent(raw); } catch (_err) { return raw; } } _parseColorToRgb(color) { const value = String(color || "").trim(); if (!value) return null; const hexMatch = value.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i); if (hexMatch) { const hex = hexMatch[1]; const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex; return { r: parseInt(full.slice(0, 2), 16), g: parseInt(full.slice(2, 4), 16), b: parseInt(full.slice(4, 6), 16) }; } const rgbMatch = value.match(/^rgba?\(([^)]+)\)$/i); if (rgbMatch) { const parts = rgbMatch[1].split(",").map((p) => p.trim()); if (parts.length >= 3) { return { r: Math.max(0, Math.min(255, parseFloat(parts[0]))), g: Math.max(0, Math.min(255, parseFloat(parts[1]))), b: Math.max(0, Math.min(255, parseFloat(parts[2]))) }; } } return null; } _rgbToHsl({ r, g, b }) { const rn = r / 255; const gn = g / 255; const bn = b / 255; const max = Math.max(rn, gn, bn); const min = Math.min(rn, gn, bn); const l = (max + min) / 2; if (max === min) { return { h: 0, s: 0, l: l * 100 }; } const d = max - min; const s = l > 0.5 ? d / (2 - max - min) : d / (max + min); let h; switch (max) { case rn: h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6; break; case gn: h = ((bn - rn) / d + 2) / 6; break; default: h = ((rn - gn) / d + 4) / 6; break; } return { h: h * 360, s: s * 100, l: l * 100 }; } _getMarkerContrastColor(color) { const rgb = this._parseColorToRgb(color); if (!rgb) return "#f3f4f6"; const { h, s, l } = this._rgbToHsl(rgb); const contrastL = Math.abs(l - 90) >= Math.abs(l - 10) ? 90 : 10; const contrastS = Math.max(40, Math.min(100, s)); return `hsl(${Math.round(h)} ${Math.round(contrastS)}% ${Math.round(contrastL)}%)`; } _getNeedleBorderColor(color) { const rgb = this._parseColorToRgb(color); if (!rgb) return "#000000"; const toLinear = (channel) => { const srgb = channel / 255; return srgb <= 0.04045 ? srgb / 12.92 : ((srgb + 0.055) / 1.055) ** 2.4; }; const luminance = 0.2126 * toLinear(rgb.r) + 0.7152 * toLinear(rgb.g) + 0.0722 * toLinear(rgb.b); return luminance < 0.22 ? "#ffffff" : "#000000"; } _formatDisplayWithUnit(display, unit) { if (!unit) return String(display); const cleanUnit = String(unit); return `${display}${this._isTightUnit(cleanUnit) ? "" : " "}${cleanUnit}`; } _formatRightValueMarkup(display, unit, hideUnit = false) { const escapedDisplay = escapeHtml(display); if (!unit || hideUnit) { return `${escapedDisplay}`; } const cleanUnit = String(unit); const escapedUnit = escapeHtml(cleanUnit); const tightUnit = this._isTightUnit(cleanUnit); const textClass = tightUnit ? "value-right-text tight-unit" : "value-right-text has-unit"; return `${escapedDisplay}${escapedUnit}`; } _formatAboveValueMarkup(display, unit, hideUnit = false) { return `${this._formatRightValueMarkup(display, unit, hideUnit)}`; } _formatInsideValueMarkup(display, unit, hideUnit = false) { const escapedDisplay = escapeHtml(display); if (!unit || hideUnit) return `${escapedDisplay}`; const cleanUnit = String(unit); const escapedUnit = escapeHtml(cleanUnit); const unitModeClass = this._isTightUnit(cleanUnit) ? "tight-unit" : "has-unit"; return `${escapedDisplay}${escapedUnit}`; } _buildRow(entityCfg, stateDisplay, unit, pct, color, peakPct, peakDisplay, targetPct, targetDisplay, peakColor, targetColor, minValue, maxValue) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u; const ecfg = this._resolve(entityCfg); const stateObj = (_c = (_b = (_a = this._hass) == null ? void 0 : _a.states) == null ? void 0 : _b[entityCfg.entity]) != null ? _c : null; const rowViewModel = stateObj ? buildRowViewModel({ hass: this._hass, cardConfig: this._config, entityConfig: ecfg, entityState: stateObj, peaks: this._peaks }) : null; const layout = ecfg.layout; const bar = ecfg.bar; const targetMarkerCfg = ecfg.target_marker; const peakMarkerCfg = ecfg.peak_marker; const safeMin = Number.isFinite(minValue) ? minValue : 0; const safeMax = Number.isFinite(maxValue) ? maxValue : 100; const baselinePct = (_d = rowViewModel == null ? void 0 : rowViewModel.baselinePercent) != null ? _d : this._resolveBaselinePct(ecfg, safeMin, safeMax); const lp = layout.label.position; const h = (_f = (_e = rowViewModel == null ? void 0 : rowViewModel.attributes) == null ? void 0 : _e.baseHeight) != null ? _f : layout.height; const name = (_j = (_i = (_g = rowViewModel == null ? void 0 : rowViewModel.name) != null ? _g : ecfg.name) != null ? _i : (_h = stateObj == null ? void 0 : stateObj.attributes) == null ? void 0 : _h.friendly_name) != null ? _j : entityCfg.entity; const escapedEntityId = escapeHtml((_k = rowViewModel == null ? void 0 : rowViewModel.entityId) != null ? _k : entityCfg.entity); const escapedName = escapeHtml(name); const targetEnabled = (targetMarkerCfg == null ? void 0 : targetMarkerCfg.enabled) !== false; const peakMarkerColor = peakColor || "#888"; const targetMarkerColor = targetColor || "#888"; const peakContrastColor = this._getMarkerContrastColor(peakMarkerColor); const targetContrastColor = this._getMarkerContrastColor(targetMarkerColor); const rawValue = (_l = rowViewModel == null ? void 0 : rowViewModel.numericValue) != null ? _l : this._getFiniteNumber(stateDisplay); const needleState = (_m = rowViewModel == null ? void 0 : rowViewModel.needle) != null ? _m : this._getNeedleRenderState(rawValue, ecfg, safeMin, safeMax, baselinePct); const fillState = this._getFillRenderState(pct, "var(--sbcp-row-height)", ecfg, color, targetPct, baselinePct, safeMin, safeMax, needleState.show); const peakMarker = peakMarkerCfg.show && peakPct !== null ? `
` : ""; const targetMarker = `
`; const targetValueLabel = targetEnabled && targetMarkerCfg.show_label ? `
${targetDisplay !== null ? escapeHtml(targetDisplay) : ""}
` : ""; const needleMarker = ((_o = (_n = ecfg.bar) == null ? void 0 : _n.needle) == null ? void 0 : _o.show) && !Number.isFinite(baselinePct) ? `
` : ""; const paintLayers = fillState.paintLayers.map((layer) => `
`).join(""); const aboveLabel = lp === "above" ? `
${ecfg.icon && ecfg.icon !== false ? `
` : ""}
${escapedName} ${this._formatAboveValueMarkup(stateDisplay, unit, false)}
` : ""; const heroSize = (_q = layout.hero.size) != null ? _q : "small"; const heroFontSize = layout.hero.value_size; const heroHeader = lp === "hero" ? `
${escapedName} ${this._formatRightValueMarkup(stateDisplay, unit, false)}
` : ""; const innerLabel = lp === "inside" ? `
${escapedName} ${this._formatInsideValueMarkup(stateDisplay, unit, false)}
` : ""; const leftLabel = lp === "left" ? `
${escapedName}
` : ""; const rightValue = lp !== "inside" && lp !== "above" && lp !== "hero" ? `
${this._formatRightValueMarkup(stateDisplay, unit, false)}
` : ""; const topRightValue = lp === "left" ? `
${this._formatRightValueMarkup(stateDisplay, unit, false)}
` : ""; const escapedIcon = ecfg.icon && ecfg.icon !== false ? escapeHtml(ecfg.icon) : ""; const mainIcon = escapedIcon && lp !== "hero" ? `
` : ""; return `
${aboveLabel} ${heroHeader} ${topRightValue}
${mainIcon} ${leftLabel}
${paintLayers}
${innerLabel} ${peakMarker} ${targetMarker} ${needleMarker}
${targetValueLabel}
${rightValue}
`; } _patchRow(row, entityCfg, stateObj) { var _a; if (!row || !stateObj) return; const ecfg = this._resolve(entityCfg); const rowViewModel = buildRowViewModel({ hass: this._hass, cardConfig: this._config, entityConfig: ecfg, entityState: stateObj, peaks: this._peaks }); const rawVal = rowViewModel.numericValue; const safeMin = rowViewModel.min; const safeMax = rowViewModel.max; const targetVal = rowViewModel.target; const pct = rowViewModel.percent; const color = this._getColor(pct, ecfg, safeMin, safeMax); const display = rowViewModel.displayValue; const displayUnit = rowViewModel.displayUnit; const fillReveal = row.querySelector(".bar-fill-reveal"); const paintLayer = row.querySelector('.bar-paint-layer[data-layer="base"]'); const liveTargetPct = rowViewModel.targetPercent; const liveBaselinePct = rowViewModel.baselinePercent; const needleState = rowViewModel.needle; const fillState = this._getFillRenderState(pct, "var(--sbcp-row-height)", ecfg, color, liveTargetPct, liveBaselinePct, safeMin, safeMax, needleState.show); if (fillReveal) { this._setStyleTextIfChanged(fillReveal, fillState.revealStyle); this._setClassNameIfChanged(fillReveal, `bar-fill-reveal${ecfg.bar.animated ? "" : " no-anim"}`); } if (paintLayer) { const baseLayerState = fillState.paintLayers.find((layer) => layer.id === "base"); if (baseLayerState) { this._setStyleTextIfChanged(paintLayer, `z-index:${baseLayerState.zIndex};${baseLayerState.paintStyle}${baseLayerState.revealStyle}`); } } const aboveTargetLayer = row.querySelector('.bar-paint-layer[data-layer="above-target"]'); if (aboveTargetLayer) { const aboveTargetState = fillState.paintLayers.find((layer) => layer.id === "above-target"); if (aboveTargetState) { this._setStyleTextIfChanged(aboveTargetLayer, `z-index:${aboveTargetState.zIndex};${aboveTargetState.paintStyle}${aboveTargetState.revealStyle}`); } } const needleEl = row.querySelector(".needle-marker"); if (needleEl) { this._setStyleIfChanged(needleEl, "display", needleState.show ? "block" : "none"); this._setStyleIfChanged(needleEl, "left", `${(_a = needleState.pct) != null ? _a : 0}%`); this._setStyleIfChanged(needleEl, "--needle-color", needleState.color); this._setStyleIfChanged(needleEl, "--needle-border-color", needleState.borderColor); this._setDatasetIfChanged(needleEl, "edge", needleState.edge); } this._setDatasetIfChanged(row, "baseHeight", rowViewModel.attributes.baseHeight); this._setDatasetIfChanged(row, "heightExplicit", rowViewModel.attributes.heightExplicit ? "true" : "false"); this._setDatasetIfChanged(row, "barAnimated", rowViewModel.attributes.barAnimated ? "true" : "false"); const valueEl = row.querySelector(".value-right"); if (valueEl) { valueEl.dataset.display = this._encodeDataAttr(display); valueEl.dataset.unit = this._encodeDataAttr(displayUnit); valueEl.dataset.hideUnit = "false"; valueEl.innerHTML = this._formatRightValueMarkup(display, displayUnit, false); } const topValueEl = row.querySelector(".top-right-value"); if (topValueEl) { topValueEl.dataset.display = this._encodeDataAttr(display); topValueEl.dataset.unit = this._encodeDataAttr(displayUnit); topValueEl.dataset.hideUnit = "false"; topValueEl.innerHTML = this._formatRightValueMarkup(display, displayUnit, false); } const innerLabel = row.querySelector(".bar-inner-label"); if (innerLabel) { const valueSpan = innerLabel.querySelector(".inside-value"); if (valueSpan) { valueSpan.dataset.display = this._encodeDataAttr(display); valueSpan.dataset.unit = this._encodeDataAttr(displayUnit); valueSpan.dataset.hideUnit = "false"; valueSpan.dataset.hideValue = "false"; valueSpan.innerHTML = this._formatInsideValueMarkup(display, displayUnit, false); } } const heroHeader = row.querySelector(".hero-header"); if (heroHeader) { const heroLine = row.querySelector(".hero-line"); this._setStyleIfChanged( heroLine, "--sbcp-hero-base-size", Number.isFinite(ecfg.layout.hero.value_size) ? `${ecfg.layout.hero.value_size}px` : null ); heroHeader.innerHTML = `${escapeHtml(rowViewModel.name)}${this._formatRightValueMarkup(display, displayUnit, false)}`; } const aboveLabel = heroHeader ? null : row.querySelector(".above-bar-label"); if (aboveLabel) { aboveLabel.innerHTML = `${escapeHtml(rowViewModel.name)}${this._formatAboveValueMarkup(display, displayUnit, false)}`; } if (ecfg.peak_marker.show && Number.isFinite(rawVal)) { const key = entityCfg.entity; if (this._peaks[key] === void 0 || rawVal > this._peaks[key]) { this._peaks[key] = rawVal; } const peakVal = this._peaks[key]; const peakPct = this._toScalePct(peakVal, safeMin, safeMax); const peakEl = row.querySelector(".peak-marker"); if (peakEl) { if (Number.isFinite(peakPct)) { this._setStyleIfChanged(peakEl, "left", `${peakPct}%`); } this._setStyleIfChanged(peakEl, "--marker-color", ecfg.peak_marker.color); this._setStyleIfChanged(peakEl, "--marker-contrast-color", this._getMarkerContrastColor(ecfg.peak_marker.color)); } } const targetEl = row.querySelector(".target-marker"); const targetLabelEl = row.querySelector(".target-value-label"); if (targetVal !== null) { const targetPct = rowViewModel.targetPercent; if (targetEl) { this._setStyleIfChanged(targetEl, "display", ""); this._setStyleIfChanged(targetEl, "left", `${targetPct}%`); this._setStyleIfChanged(targetEl, "--marker-color", ecfg.target_marker.color); this._setStyleIfChanged(targetEl, "--marker-contrast-color", this._getMarkerContrastColor(ecfg.target_marker.color)); } if (targetLabelEl) { this._setTextIfChanged(targetLabelEl, rowViewModel.targetDisplay); } } else { if (targetEl) this._setStyleIfChanged(targetEl, "display", "none"); if (targetLabelEl) this._setStyleIfChanged(targetLabelEl, "visibility", "hidden"); } } _update() { if (!this._hass || !this._config) return; const rowsEl = this.shadowRoot.querySelector(".rows"); if (!rowsEl) return; const entities = this._config.entities; if (!this._rendered) { let html = ""; for (let entityIndex = 0; entityIndex < entities.length; entityIndex++) { const entityCfg = entities[entityIndex]; const stateObj = this._hass.states[entityCfg.entity]; if (!stateObj) { html += `
Entity not found: ${escapeHtml(entityCfg.entity)}
`; continue; } const ecfg = this._resolve(entityCfg); const rowViewModel = buildRowViewModel({ hass: this._hass, cardConfig: this._config, entityConfig: ecfg, entityState: stateObj, peaks: this._peaks }); const rawVal = rowViewModel.numericValue; const safeMin = rowViewModel.min; const safeMax = rowViewModel.max; const targetVal = rowViewModel.target; const pct = rowViewModel.percent; const color = this._getColor(pct, ecfg, safeMin, safeMax); const display = rowViewModel.displayValue; const displayUnit = rowViewModel.displayUnit; const targetPct = rowViewModel.targetPercent; const targetDisplay = rowViewModel.targetDisplay; let peakPct = null, peakDisplay = null; if (ecfg.peak_marker.show && Number.isFinite(rawVal)) { if (this._peaks[entityCfg.entity] === void 0 || rawVal > this._peaks[entityCfg.entity]) { this._peaks[entityCfg.entity] = rawVal; } const peakVal = this._peaks[entityCfg.entity]; peakPct = this._toScalePct(peakVal, safeMin, safeMax); peakDisplay = this._formatNumericDisplay(peakVal, ecfg.formatting.decimal); } html += this._buildRow(entityCfg, display, displayUnit, pct, color, peakPct, peakDisplay, targetPct, targetDisplay, ecfg.peak_marker.color, ecfg.target_marker.color, safeMin, safeMax); } rowsEl.innerHTML = html; this._rendered = true; const builtRows = rowsEl.querySelectorAll(".row[data-entity]"); builtRows.forEach((row, idx) => { const entityCfg = entities[idx]; const stateObj = entityCfg ? this._hass.states[entityCfg.entity] : null; if (entityCfg && stateObj) { this._patchRow(row, entityCfg, stateObj); } }); this._runPostLayoutPasses(builtRows); builtRows.forEach((row) => { row.addEventListener("click", () => { const entityId = row.dataset.entity; const event = new CustomEvent("hass-more-info", { composed: true, detail: { entityId } }); this.dispatchEvent(event); }); }); return; } const rows = rowsEl.querySelectorAll(".row[data-entity]"); let rowIdx = 0; for (const entityCfg of entities) { const stateObj = this._hass.states[entityCfg.entity]; if (!stateObj) { rowIdx++; continue; } const row = rows[rowIdx]; if (!row) { rowIdx++; continue; } this._patchRow(row, entityCfg, stateObj); rowIdx++; } this._runPostLayoutPasses(rows); } }; } }); // src/editor/SensorBarCardPlusEditor.js var SensorBarCardPlusEditor; var init_SensorBarCardPlusEditor = __esm({ "src/editor/SensorBarCardPlusEditor.js"() { SensorBarCardPlusEditor = class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this._config = {}; this._draftConfig = {}; this._hass = null; this._isRendering = false; this._renderScheduled = false; this._lastRenderedConfigJson = null; this._lastEmittedConfigJson = null; this._shadowListenersAttached = false; this._expandedEntityOverrides = /* @__PURE__ */ new Set(); this._expandedOverrideGroups = /* @__PURE__ */ new Set(); this._expandedCardGroups = /* @__PURE__ */ new Set(); this._gradientStopsDrafts = /* @__PURE__ */ new Map(); this._gradientStopsUiRows = /* @__PURE__ */ new Map(); this._gradientStopPosTexts = /* @__PURE__ */ new Map(); this._gradientStopValidationMessages = /* @__PURE__ */ new Map(); this._segmentDrafts = /* @__PURE__ */ new Map(); this._segmentUiRows = /* @__PURE__ */ new Map(); this._segmentBoundaryTexts = /* @__PURE__ */ new Map(); this._targetAboveFillDrafts = /* @__PURE__ */ new Map(); this._baselineColorDrafts = /* @__PURE__ */ new Map(); this._pendingFocusSelector = null; this._boundHandleClick = (event) => this._handleClick(event); this._boundHandleChange = (event) => this._handleChange(event); this._boundHandleInput = (event) => this._handleInput(event); this._boundHandleValueChanged = (event) => this._handleValueChanged(event); this._boundHandleKeydown = (event) => this._handleKeydown(event); } setConfig(config) { var _a; const nextConfig = this._cloneDeep(config != null ? config : {}); const nextConfigJson = this._serializeConfig(nextConfig); const currentConfigJson = this._serializeConfig(this._config); const currentDraftJson = this._serializeConfig(this._draftConfig); if (nextConfigJson === currentConfigJson) { return; } if (nextConfigJson === currentDraftJson) { this._config = nextConfig; return; } const shouldRender = !((_a = this.shadowRoot) == null ? void 0 : _a.innerHTML) || nextConfigJson !== this._lastRenderedConfigJson; this._config = nextConfig; this._draftConfig = this._cloneDeep(nextConfig); this._gradientStopsDrafts = /* @__PURE__ */ new Map(); this._gradientStopsUiRows = /* @__PURE__ */ new Map(); this._gradientStopPosTexts = /* @__PURE__ */ new Map(); this._gradientStopValidationMessages = /* @__PURE__ */ new Map(); this._segmentDrafts = /* @__PURE__ */ new Map(); this._segmentUiRows = /* @__PURE__ */ new Map(); this._segmentBoundaryTexts = /* @__PURE__ */ new Map(); this._targetAboveFillDrafts = /* @__PURE__ */ new Map(); this._baselineColorDrafts = /* @__PURE__ */ new Map(); if (shouldRender) { this._render(); } } set hass(hass) { var _a; this._hass = hass; if (!((_a = this.shadowRoot) == null ? void 0 : _a.innerHTML)) { this._render(); return; } this._syncEntityPickers(); } _cloneContainer(value) { return Array.isArray(value) ? [...value] : { ...value != null ? value : {} }; } _cloneDeep(value) { if (Array.isArray(value)) { return value.map((entry) => this._cloneDeep(entry)); } if (this._isObject(value)) { const clone = {}; for (const [key, entry] of Object.entries(value)) { clone[key] = this._cloneDeep(entry); } return clone; } return value; } _serializeConfig(value) { const normalize = (input) => { if (Array.isArray(input)) { return input.map((entry) => normalize(entry)); } if (this._isObject(input)) { return Object.keys(input).sort().reduce((acc, key) => { acc[key] = normalize(input[key]); return acc; }, {}); } return input; }; return JSON.stringify(normalize(value != null ? value : null)); } _isObject(value) { return !!value && typeof value === "object" && !Array.isArray(value); } _setPathValue(target, path, value) { if (!path.length) { return value; } const root = this._cloneContainer(target != null ? target : {}); let cursor = root; let sourceCursor = target; for (let index = 0; index < path.length - 1; index++) { const key = path[index]; const nextSource = this._isObject(sourceCursor == null ? void 0 : sourceCursor[key]) || Array.isArray(sourceCursor == null ? void 0 : sourceCursor[key]) ? sourceCursor[key] : {}; cursor[key] = this._cloneContainer(nextSource); cursor = cursor[key]; sourceCursor = nextSource; } cursor[path[path.length - 1]] = value; return root; } _deletePathValue(target, path) { if (!path.length || !this._isObject(target)) { return target; } const [key, ...rest] = path; if (!(key in target)) { return target; } const cloned = this._cloneContainer(target); if (!rest.length) { delete cloned[key]; return cloned; } const nextValue = this._deletePathValue(cloned[key], rest); if (nextValue === cloned[key]) { return target; } if (this._isObject(nextValue) && !Object.keys(nextValue).length) { delete cloned[key]; return cloned; } cloned[key] = nextValue; return cloned; } _getPathValue(target, path) { let cursor = target; for (const key of path) { if (cursor == null) return void 0; cursor = cursor[key]; } return cursor; } _hasPath(target, path) { let cursor = target; for (const key of path) { if (!this._isObject(cursor) && !Array.isArray(cursor)) return false; if (!(key in cursor)) return false; cursor = cursor[key]; } return true; } _normalizeTextValue(value) { return typeof value === "string" ? value : value == null ? "" : String(value); } _normalizeOptionalEnabled(value) { return value === true ? true : value === false ? false : null; } _normalizeNumberValue(value) { if (value === "" || value === null || value === void 0) { return null; } const parsed = Number(value); return Number.isFinite(parsed) ? parsed : null; } _normalizeDecimalValue(value) { if (value === "" || value === null || value === void 0) { return null; } const parsed = Number(value); if (!Number.isFinite(parsed) || parsed < 0 || !Number.isInteger(parsed)) { return null; } return parsed; } _preferStructuredPath(structuredPath, legacyPath = null) { if (this._hasPath(this._draftConfig, structuredPath.slice(0, -1))) { return structuredPath; } if (this._hasPath(this._draftConfig, structuredPath)) { return structuredPath; } if (legacyPath && this._hasPath(this._draftConfig, legacyPath)) { return legacyPath; } return structuredPath; } _getEntitiesValue() { var _a, _b; if (Array.isArray(this._draftConfig.entities)) { return this._draftConfig.entities.map((entry) => { var _a2, _b2, _c; return typeof entry === "string" ? { entity: entry } : { entity: (_a2 = entry == null ? void 0 : entry.entity) != null ? _a2 : "", name: (_b2 = entry == null ? void 0 : entry.name) != null ? _b2 : "", icon: (_c = entry == null ? void 0 : entry.icon) != null ? _c : "" }; }); } if (this._draftConfig.entity) { return [{ entity: this._draftConfig.entity, name: (_a = this._draftConfig.name) != null ? _a : "", icon: (_b = this._draftConfig.icon) != null ? _b : "" }]; } return []; } _getRawEntityRows() { if (Array.isArray(this._draftConfig.entities)) { return this._cloneDeep(this._draftConfig.entities); } if (this._draftConfig.entity !== void 0) { const hasTopLevelIdentity = this._draftConfig.name !== void 0 || this._draftConfig.icon !== void 0; if (!hasTopLevelIdentity) { return [this._draftConfig.entity]; } return [{ entity: this._draftConfig.entity, ...this._draftConfig.name !== void 0 ? { name: this._draftConfig.name } : {}, ...this._draftConfig.icon !== void 0 ? { icon: this._draftConfig.icon } : {} }]; } return []; } _buildEntityConfigEntries(entities) { const usesShorthand = !Array.isArray(this._draftConfig.entities) && this._draftConfig.entity !== void 0; const source = Array.isArray(this._draftConfig.entities) ? this._draftConfig.entities : this._draftConfig.entity !== void 0 ? [{ entity: this._draftConfig.entity, ...this._draftConfig.name !== void 0 ? { name: this._draftConfig.name } : {}, ...this._draftConfig.icon !== void 0 ? { icon: this._draftConfig.icon } : {} }] : []; const entries = entities.map((entry, index) => { const rawEntry = source[index]; if (this._isObject(rawEntry)) { const mergedEntry = { ...rawEntry, entity: entry.entity }; const normalizedName2 = this._normalizeTextValue(entry.name).trim(); if (normalizedName2) { mergedEntry.name = normalizedName2; } else { delete mergedEntry.name; } const rawIconValue = entry == null ? void 0 : entry.icon; const normalizedIcon2 = typeof rawIconValue === "string" ? rawIconValue.trim() : rawIconValue; if (normalizedIcon2 === false) { mergedEntry.icon = false; } else if (typeof normalizedIcon2 === "string" && normalizedIcon2) { mergedEntry.icon = normalizedIcon2; } else if (rawEntry.icon === false) { mergedEntry.icon = false; } else { delete mergedEntry.icon; } return mergedEntry; } const nextEntry = { entity: entry.entity }; const normalizedName = this._normalizeTextValue(entry.name).trim(); if (normalizedName) { nextEntry.name = normalizedName; } const normalizedIcon = typeof (entry == null ? void 0 : entry.icon) === "string" ? entry.icon.trim() : entry == null ? void 0 : entry.icon; if (normalizedIcon === false) { nextEntry.icon = false; } else if (typeof normalizedIcon === "string" && normalizedIcon) { nextEntry.icon = normalizedIcon; } return nextEntry; }); if (!usesShorthand) { return entries.map((entry) => { if (this._isObject(entry) && Object.keys(entry).length === 1 && entry.entity !== void 0) { return entry.entity; } return entry; }); } return entries; } _updateConfig(nextConfig) { this._draftConfig = this._cloneDeep(nextConfig); } _emitConfigChanged() { const emittedConfig = this._cleanupEditorEmittedConfig(this._cloneDeep(this._draftConfig)); const nextConfigJson = this._serializeConfig(emittedConfig); if (nextConfigJson === this._lastEmittedConfigJson) { return false; } this._lastEmittedConfigJson = nextConfigJson; this.dispatchEvent(new CustomEvent("config-changed", { detail: { config: emittedConfig }, bubbles: true, composed: true })); return true; } _scheduleRender() { if (this._renderScheduled || this._isRendering) return; this._renderScheduled = true; setTimeout(() => { this._renderScheduled = false; this._render(); }, 0); } _applyUserConfig(nextConfig, options = {}) { const { rerender = false } = options; const nextConfigJson = this._serializeConfig(nextConfig); const currentDraftJson = this._serializeConfig(this._draftConfig); if (nextConfigJson === currentDraftJson) { return false; } this._updateConfig(nextConfig); this._emitConfigChanged(); this._refreshDerivedEditorUi(); if (rerender) { this._scheduleRender(); } return true; } _getShadowElementById(id) { var _a, _b, _c, _d, _e, _f; if (!this.shadowRoot) { return null; } return (_f = (_e = (_b = (_a = this.shadowRoot).getElementById) == null ? void 0 : _b.call(_a, id)) != null ? _e : (_d = (_c = this.shadowRoot).querySelector) == null ? void 0 : _d.call(_c, `#${id}`)) != null ? _f : null; } _setElementChecked(id, checked) { const element = this._getShadowElementById(id); if (element) { element.checked = !!checked; } } _setElementText(id, value) { const element = this._getShadowElementById(id); if (element) { element.textContent = value; } } _refreshDerivedEditorUi() { if (!this.shadowRoot) { return; } this._refreshCardDerivedUi(); this._refreshEntityDerivedUi(); } _refreshCardDerivedUi() { this._setElementText("card-group-segments-summary", this._getSegmentsSummary({ type: "card" })); this._setElementText("card-group-gradient-stops-summary", this._getGradientStopsSummary({ type: "card" })); this._setElementChecked("target-above-fill-enabled", this._isTargetAboveFillEnabled({ type: "card" })); this._setElementChecked("baseline-above-color-enabled", this._isBaselineDirectionalColorEnabled({ type: "card" }, "above")); this._setElementChecked("baseline-below-color-enabled", this._isBaselineDirectionalColorEnabled({ type: "card" }, "below")); this._refreshSegmentUi({ type: "card" }); } _refreshEntityDerivedUi() { const count = this._getEntitiesValue().length; for (let index = 0; index < count; index += 1) { const scope = { type: "entity", index }; this._setElementChecked(`entity-${index}-scale-inherit`, !this._hasResolvableOverride(this._getResolvableScopedValue(scope, "min")) && !this._hasResolvableOverride(this._getResolvableScopedValue(scope, "max"))); this._setElementChecked(`entity-${index}-target-inherit`, !this._hasTargetOverride(scope)); this._setElementChecked(`entity-${index}-baseline-inherit`, !this._hasBaselineOverride(scope)); this._setElementChecked(`entity-${index}-needle-inherit`, !this._hasNeedleOverride(scope)); this._setElementChecked(`entity-${index}-peak-inherit`, !this._hasPeakOverride(scope)); this._setElementChecked(`entity-${index}-bar-inherit`, !this._hasEntityBarAppearanceOverride(scope)); this._setElementChecked(`entity-${index}-segments-inherit`, !this._hasSegmentsOverride(scope)); this._setElementChecked(`entity-${index}-gradient-stops-inherit`, !this._hasGradientStopsOverride(scope)); this._setElementChecked(`entity-${index}-layout-inherit`, !this._hasLayoutOverride(scope)); this._setElementChecked(`entity-${index}-formatting-inherit`, !this._hasFormattingOverride(scope)); this._setElementChecked(`entity-${index}-target-above-fill-enabled`, this._isTargetAboveFillEnabled(scope)); this._setElementChecked(`entity-${index}-baseline-above-color-enabled`, this._isBaselineDirectionalColorEnabled(scope, "above")); this._setElementChecked(`entity-${index}-baseline-below-color-enabled`, this._isBaselineDirectionalColorEnabled(scope, "below")); this._setElementText(`entity-${index}-group-scale-summary`, this._getScaleOverrideSummary(scope)); this._setElementText(`entity-${index}-group-target-summary`, this._getTargetOverrideSummary(scope)); this._setElementText(`entity-${index}-group-baseline-summary`, this._getBaselineOverrideSummary(scope)); this._setElementText(`entity-${index}-group-needle-summary`, this._getNeedleSummary(scope)); this._setElementText(`entity-${index}-group-peak-summary`, this._getPeakSummary(scope)); this._setElementText(`entity-${index}-group-bar-summary`, this._getBarAppearanceSummary(scope)); this._setElementText(`entity-${index}-group-segments-summary`, this._getSegmentsSummary(scope)); this._setElementText(`entity-${index}-group-gradient-stops-summary`, this._getGradientStopsSummary(scope)); this._setElementText(`entity-${index}-group-layout-summary`, this._getLayoutSummary(scope)); this._setElementText(`entity-${index}-group-formatting-summary`, this._getFormattingSummary(scope)); this._refreshSegmentUi(scope); } } _queuePostRenderFocus(selector) { this._pendingFocusSelector = selector || null; } _applyPendingFocus() { if (!this._pendingFocusSelector || !this.shadowRoot) { return; } const selector = this._pendingFocusSelector; this._pendingFocusSelector = null; setTimeout(() => { var _a, _b; const element = (_b = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector) == null ? void 0 : _b.call(_a, selector); if (!element || typeof element.focus !== "function") { return; } try { element.focus({ preventScroll: true }); } catch (_error) { element.focus(); } }, 0); } _setValueAtPath(path, value, options = {}) { const nextConfig = value === void 0 ? this._deletePathValue(this._draftConfig, path) : this._setPathValue(this._draftConfig, path, value); return this._applyUserConfig(nextConfig, options); } _setTitle(value) { this._setValueAtPath(["title"], value); } _setEntityField(index, key, value) { const normalizedValue = this._normalizeTextValue(value); if (!Array.isArray(this._draftConfig.entities) && this._draftConfig.entity !== void 0 && index === 0) { if (!normalizedValue.trim()) { return this._setValueAtPath([key], void 0); } return this._setValueAtPath([key], normalizedValue.trim()); } const nextConfig = this._withEntityScopeConfig((entries) => { var _a; const rawEntry = entries[index]; const nextEntry = this._isObject(rawEntry) ? this._cloneDeep(rawEntry) : { entity: (_a = rawEntry == null ? void 0 : rawEntry.entity) != null ? _a : "" }; if (!normalizedValue.trim()) { delete nextEntry[key]; } else { nextEntry[key] = normalizedValue.trim(); } entries[index] = nextEntry; return entries; }); return this._applyUserConfig(nextConfig); } _cleanupEntityIdentityForEmit(target) { if (!this._isObject(target)) { return target; } const nextTarget = this._cloneDeep(target); const normalizedName = this._normalizeTextValue(nextTarget.name).trim(); if (!normalizedName) { delete nextTarget.name; } else { nextTarget.name = normalizedName; } if (nextTarget.icon === false) { return nextTarget; } const normalizedIcon = this._normalizeTextValue(nextTarget.icon).trim(); if (!normalizedIcon) { delete nextTarget.icon; } else { nextTarget.icon = normalizedIcon; } return nextTarget; } _cleanupNeedleForEmit(target, scope = { type: "card" }) { var _a; if (!this._isObject(target) || !this._isObject(target.bar)) { return target; } const nextTarget = this._cloneDeep(target); const rawNeedle = (_a = nextTarget.bar) == null ? void 0 : _a.needle; if (rawNeedle === void 0) { return nextTarget; } const defaultColor = this._normalizeColorComparisonValue("#ffffff"); let nextNeedle = null; if (rawNeedle === true) { nextNeedle = { show: true }; } else if (rawNeedle === false) { nextNeedle = (scope == null ? void 0 : scope.type) === "entity" ? { show: false } : null; } else if (this._isObject(rawNeedle)) { const color = this._normalizeTextValue(rawNeedle.color).trim(); if (rawNeedle.show === true) { nextNeedle = { show: true }; } else if (rawNeedle.show === false) { nextNeedle = (scope == null ? void 0 : scope.type) === "entity" ? { show: false } : null; } else if ((scope == null ? void 0 : scope.type) === "entity" && color && this._normalizeColorComparisonValue(color) !== defaultColor) { nextNeedle = {}; } if (nextNeedle && color && this._normalizeColorComparisonValue(color) !== defaultColor) { nextNeedle.color = color; } } else { nextNeedle = null; } if (nextNeedle) { nextTarget.bar.needle = nextNeedle; } else { delete nextTarget.bar.needle; if (!Object.keys(nextTarget.bar).length) { delete nextTarget.bar; } } return nextTarget; } _cleanupResolvableValueForEmit(value) { const nextValue = {}; if (this._isObject(value)) { const fixed = this._normalizeNumberValue(value.fixed); const entity = this._normalizeTextValue(value.entity).trim(); if (fixed !== null) { nextValue.fixed = fixed; } if (entity) { nextValue.entity = entity; } } else { const fixed = this._normalizeNumberValue(value); if (fixed !== null) { nextValue.fixed = fixed; } } return Object.keys(nextValue).length ? nextValue : null; } _cleanupScaleForEmit(target) { if (!this._isObject(target) || !this._isObject(target.scale)) { return target; } const nextTarget = this._cloneDeep(target); const nextScale = this._cloneDeep(nextTarget.scale); ["min", "max"].forEach((key) => { if (!Object.prototype.hasOwnProperty.call(nextScale, key)) { return; } const cleanedValue = this._cleanupResolvableValueForEmit(nextScale[key]); if (cleanedValue) { nextScale[key] = cleanedValue; delete nextTarget[key]; delete nextTarget[`${key}_entity`]; } else { delete nextScale[key]; } }); if (Object.keys(nextScale).length) { nextTarget.scale = nextScale; } else { delete nextTarget.scale; } return nextTarget; } _cleanupFormattingForEmit(target) { if (!this._isObject(target) || !this._isObject(target.formatting)) { return target; } const nextTarget = this._cloneDeep(target); const nextFormatting = this._cloneDeep(nextTarget.formatting); const unit = this._normalizeTextValue(nextFormatting.unit).trim(); const decimal = this._normalizeDecimalValue(nextFormatting.decimal); if (unit) { nextFormatting.unit = unit; delete nextTarget.unit; } else { delete nextFormatting.unit; } if (decimal !== null) { nextFormatting.decimal = decimal; delete nextTarget.decimal; } else { delete nextFormatting.decimal; } if (Object.keys(nextFormatting).length) { nextTarget.formatting = nextFormatting; } else { delete nextTarget.formatting; } return nextTarget; } _cleanupLayoutForEmit(target) { if (!this._isObject(target) || !this._isObject(target.layout)) { return target; } const nextTarget = this._cloneDeep(target); const nextLayout = this._cloneDeep(nextTarget.layout); const nextLabel = this._isObject(nextLayout.label) ? this._cloneDeep(nextLayout.label) : null; const nextHero = this._isObject(nextLayout.hero) ? this._cloneDeep(nextLayout.hero) : null; const height = this._normalizeNumberValue(nextLayout.height); const width = this._normalizeNumberValue(nextLabel == null ? void 0 : nextLabel.width); const valueSize = this._normalizeHeroValueSizeValue(nextHero == null ? void 0 : nextHero.value_size); const position = this._normalizeTextValue(nextLabel == null ? void 0 : nextLabel.position).trim(); if (height !== null && height >= 24) { nextLayout.height = height; delete nextTarget.height; } else { delete nextLayout.height; } if (nextLabel) { if (position) { nextLabel.position = position; delete nextTarget.label_position; } else { delete nextLabel.position; } if (width !== null) { nextLabel.width = width; delete nextTarget.label_width; } else { delete nextLabel.width; } if (Object.keys(nextLabel).length) { nextLayout.label = nextLabel; } else { delete nextLayout.label; } } if (nextHero) { if (valueSize !== null) { nextHero.value_size = valueSize; } else { delete nextHero.value_size; } if (Object.keys(nextHero).length) { nextLayout.hero = nextHero; } else { delete nextLayout.hero; } } if (Object.keys(nextLayout).length) { nextTarget.layout = nextLayout; } else { delete nextTarget.layout; } return nextTarget; } _cleanupTargetForEmit(target) { var _a, _b; if (!this._isObject(target) || !this._isObject(target.target)) { return target; } const nextTarget = this._cloneDeep(target); const nextMarker = this._cloneDeep(nextTarget.target); const cleanedAt = this._cleanupResolvableValueForEmit(nextMarker.at); const color = this._normalizeTextValue(nextMarker.color).trim(); const labelShow = ((_a = nextMarker.label) == null ? void 0 : _a.show) === true; const fillColor = this._normalizeTextValue((_b = nextMarker.when_exceeded) == null ? void 0 : _b.fill_color).trim(); if (typeof nextMarker.enabled !== "boolean") { delete nextMarker.enabled; } if (cleanedAt) { nextMarker.at = cleanedAt; delete nextTarget.target_entity; } else { delete nextMarker.at; } if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#888")) { nextMarker.color = color; delete nextTarget.target_color; } else { delete nextMarker.color; } if (labelShow) { nextMarker.label = { ...this._isObject(nextMarker.label) ? nextMarker.label : {}, show: true }; delete nextTarget.show_target_label; } else { delete nextMarker.label; } if (fillColor) { nextMarker.when_exceeded = { ...this._isObject(nextMarker.when_exceeded) ? nextMarker.when_exceeded : {}, fill_color: fillColor }; delete nextTarget.above_target_color; } else { delete nextMarker.when_exceeded; } if (Object.keys(nextMarker).length) { nextTarget.target = nextMarker; } else { delete nextTarget.target; } return nextTarget; } _cleanupBaselineForEmit(target) { if (!this._isObject(target) || !this._isObject(target.baseline)) { return target; } const nextTarget = this._cloneDeep(target); const nextBaseline = this._cloneDeep(nextTarget.baseline); const cleanedAt = this._cleanupResolvableValueForEmit(nextBaseline.at); if (typeof nextBaseline.enabled !== "boolean") { delete nextBaseline.enabled; } if (cleanedAt) { nextBaseline.at = cleanedAt; } else { delete nextBaseline.at; } ["above", "below"].forEach((direction) => { if (!this._isObject(nextBaseline[direction])) { delete nextBaseline[direction]; return; } const color = this._normalizeTextValue(nextBaseline[direction].color).trim(); if (color) { nextBaseline[direction] = { ...nextBaseline[direction], color }; } else { delete nextBaseline[direction]; } }); if (Object.keys(nextBaseline).length) { nextTarget.baseline = nextBaseline; } else { delete nextTarget.baseline; } return nextTarget; } _cleanupPeakForEmit(target) { if (!this._isObject(target) || !this._isObject(target.peak)) { return target; } const nextTarget = this._cloneDeep(target); const nextPeak = this._cloneDeep(nextTarget.peak); const color = this._normalizeTextValue(nextPeak.color).trim(); if (typeof nextPeak.enabled !== "boolean") { delete nextPeak.enabled; } if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#888")) { nextPeak.color = color; delete nextTarget.peak_color; } else { delete nextPeak.color; } if (Object.keys(nextPeak).length) { nextTarget.peak = nextPeak; } else { delete nextTarget.peak; } return nextTarget; } _cleanupBarForEmit(target) { if (!this._isObject(target) || !this._isObject(target.bar)) { return target; } const nextTarget = this._cloneDeep(target); const nextBar = this._cloneDeep(nextTarget.bar); const fillStyle = this._normalizeTextValue(nextBar.fill_style).trim(); const color = this._normalizeTextValue(nextBar.color).trim(); const segments = Array.isArray(nextBar.segments) ? nextBar.segments : null; const gradientStops = Array.isArray(nextBar.gradient_stops) ? nextBar.gradient_stops : null; if (fillStyle && fillStyle !== "bands") { nextBar.fill_style = fillStyle; delete nextTarget.color_mode; } else { delete nextBar.fill_style; } if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#4a9eff")) { nextBar.color = color; delete nextTarget.color; } else { delete nextBar.color; } if (nextBar.solid_fill === true) { nextBar.solid_fill = true; } else { delete nextBar.solid_fill; } if (segments && segments.length && !this._segmentsEqualForEditor(segments, this._getDefaultSegments())) { nextBar.segments = segments; delete nextTarget.segments; delete nextTarget.severity; } else { delete nextBar.segments; } if (gradientStops && gradientStops.length >= 2 && !this._isDefaultGradientStops(gradientStops)) { nextBar.gradient_stops = this._sanitizeGradientStopsForEmit(gradientStops); delete nextTarget.gradient_stops; } else { delete nextBar.gradient_stops; } if (Object.keys(nextBar).length) { nextTarget.bar = nextBar; } else { delete nextTarget.bar; } return nextTarget; } _getEditorKnownKeyOrder(path = []) { const pathKey = path.join("."); switch (pathKey) { case "": return ["type", "title", "entities", "scale", "target", "baseline", "peak", "layout", "formatting", "bar"]; case "entities.*": return ["entity", "name", "icon", "scale", "target", "baseline", "peak", "layout", "formatting", "bar"]; case "scale": return ["min", "max"]; case "scale.min": case "scale.max": case "target.at": case "baseline.at": return ["fixed", "entity"]; case "target": return ["enabled", "at", "color", "label", "when_exceeded"]; case "target.label": return ["show"]; case "target.when_exceeded": return ["fill_color"]; case "baseline": return ["enabled", "at", "above", "below"]; case "baseline.above": case "baseline.below": return ["color"]; case "peak": return ["enabled", "color"]; case "layout": return ["height", "label", "hero"]; case "layout.label": return ["position", "hero_size", "width"]; case "layout.hero": return ["size", "value_size"]; case "formatting": return ["unit", "decimal"]; case "bar": return ["fill_style", "color", "solid_fill", "needle", "segments", "gradient_stops"]; case "bar.needle": return ["show", "color"]; default: return null; } } _orderEditorConfigKeys(value, path = []) { var _a; if (Array.isArray(value)) { const nextPath = path[0] === "entities" ? ["entities", "*"] : path; return value.map((entry) => this._orderEditorConfigKeys(entry, nextPath)); } if (!this._isObject(value)) { return value; } const orderedValue = {}; const knownOrder = (_a = this._getEditorKnownKeyOrder(path)) != null ? _a : []; const seenKeys = /* @__PURE__ */ new Set(); knownOrder.forEach((key) => { if (!Object.prototype.hasOwnProperty.call(value, key)) { return; } orderedValue[key] = this._orderEditorConfigKeys(value[key], [...path, key]); seenKeys.add(key); }); Object.keys(value).forEach((key) => { if (seenKeys.has(key)) { return; } orderedValue[key] = this._orderEditorConfigKeys(value[key], [...path, key]); }); return orderedValue; } _cleanupEditorEmittedConfig(config) { if (!this._isObject(config)) { return config; } let nextConfig = this._cleanupEntityIdentityForEmit(config); nextConfig = this._cleanupScaleForEmit(nextConfig); nextConfig = this._cleanupTargetForEmit(nextConfig); nextConfig = this._cleanupBaselineForEmit(nextConfig); nextConfig = this._cleanupPeakForEmit(nextConfig); nextConfig = this._cleanupLayoutForEmit(nextConfig); nextConfig = this._cleanupFormattingForEmit(nextConfig); nextConfig = this._cleanupNeedleForEmit(nextConfig, { type: "card" }); nextConfig = this._cleanupBarForEmit(nextConfig); if (Array.isArray(nextConfig.entities)) { nextConfig.entities = nextConfig.entities.map((entry) => { if (!this._isObject(entry)) { return entry; } let cleanedEntry = this._cleanupEntityIdentityForEmit(entry); cleanedEntry = this._cleanupScaleForEmit(cleanedEntry); cleanedEntry = this._cleanupTargetForEmit(cleanedEntry); cleanedEntry = this._cleanupBaselineForEmit(cleanedEntry); cleanedEntry = this._cleanupPeakForEmit(cleanedEntry); cleanedEntry = this._cleanupLayoutForEmit(cleanedEntry); cleanedEntry = this._cleanupFormattingForEmit(cleanedEntry); cleanedEntry = this._cleanupNeedleForEmit(cleanedEntry, { type: "entity" }); cleanedEntry = this._cleanupBarForEmit(cleanedEntry); return cleanedEntry; }); } return this._orderEditorConfigKeys(nextConfig); } _getScopedPath(scope, keyPath) { const normalizedPath = Array.isArray(keyPath) ? keyPath : [keyPath]; if (!scope || scope.type === "card") { return normalizedPath; } if (scope.type === "entity") { return ["entities", scope.index, ...normalizedPath]; } return normalizedPath; } _normalizePath(keyPath) { return Array.isArray(keyPath) ? keyPath : [keyPath]; } _getEntityRawEntries() { if (Array.isArray(this._draftConfig.entities)) { return this._draftConfig.entities.map((entry) => this._isObject(entry) ? this._cloneDeep(entry) : { entity: entry }); } if (this._draftConfig.entity !== void 0) { return [{ entity: this._draftConfig.entity, ...this._draftConfig.name !== void 0 ? { name: this._draftConfig.name } : {}, ...this._draftConfig.icon !== void 0 ? { icon: this._draftConfig.icon } : {} }]; } return []; } _withEntityScopeConfig(mutator) { const rawEntries = this._getEntityRawEntries(); const nextEntries = mutator(rawEntries.map((entry) => this._cloneDeep(entry))); let nextConfig = this._setPathValue(this._draftConfig, ["entities"], nextEntries); if (!Array.isArray(this._draftConfig.entities) && this._draftConfig.entity !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["entity"]); if (this._draftConfig.name !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["name"]); } if (this._draftConfig.icon !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["icon"]); } } return nextConfig; } _setEntityRowsRaw(nextRows, options = {}) { var _a; const normalizedRows = this._cloneDeep(nextRows); if (Array.isArray(this._draftConfig.entities) || this._draftConfig.entity === void 0 || normalizedRows.length !== 1) { let nextConfig2 = this._setPathValue(this._draftConfig, ["entities"], normalizedRows); if (!Array.isArray(this._draftConfig.entities) && this._draftConfig.entity !== void 0) { nextConfig2 = this._deletePathValue(nextConfig2, ["entity"]); nextConfig2 = this._deletePathValue(nextConfig2, ["name"]); nextConfig2 = this._deletePathValue(nextConfig2, ["icon"]); } return this._applyUserConfig(nextConfig2, options); } const [row] = normalizedRows; if (typeof row === "string") { let nextConfig2 = this._setPathValue(this._draftConfig, ["entity"], row); nextConfig2 = this._deletePathValue(nextConfig2, ["name"]); nextConfig2 = this._deletePathValue(nextConfig2, ["icon"]); return this._applyUserConfig(nextConfig2, options); } let nextConfig = this._setPathValue(this._draftConfig, ["entity"], (_a = row == null ? void 0 : row.entity) != null ? _a : ""); if (row && Object.prototype.hasOwnProperty.call(row, "name")) { nextConfig = this._setPathValue(nextConfig, ["name"], row.name); } else { nextConfig = this._deletePathValue(nextConfig, ["name"]); } if (row && Object.prototype.hasOwnProperty.call(row, "icon")) { nextConfig = this._setPathValue(nextConfig, ["icon"], row.icon); } else { nextConfig = this._deletePathValue(nextConfig, ["icon"]); } return this._applyUserConfig(nextConfig, options); } _moveEntityRow(index, direction) { const rows = this._getRawEntityRows(); const nextIndex = index + direction; if (index < 0 || index >= rows.length || nextIndex < 0 || nextIndex >= rows.length) { return false; } const nextRows = this._cloneDeep(rows); [nextRows[index], nextRows[nextIndex]] = [nextRows[nextIndex], nextRows[index]]; return this._setEntityRowsRaw(nextRows, { rerender: true }); } _duplicateEntityRow(index) { const rows = this._getRawEntityRows(); if (index < 0 || index >= rows.length) { return false; } const sourceRow = this._cloneDeep(rows[index]); const duplicateRow = typeof sourceRow === "string" ? { entity: sourceRow } : this._cloneDeep(sourceRow); if (this._isObject(duplicateRow) && typeof duplicateRow.name === "string" && duplicateRow.name.trim()) { duplicateRow.name = `${duplicateRow.name.trim()} copy`; } const nextRows = this._cloneDeep(rows); nextRows.splice(index + 1, 0, duplicateRow); return this._setEntityRowsRaw(nextRows, { rerender: true }); } _removeEntityRow(index) { const rows = this._getRawEntityRows(); if (rows.length <= 1 || index < 0 || index >= rows.length) { return false; } const nextRows = rows.filter((_, rowIndex) => rowIndex !== index); return this._setEntityRowsRaw(nextRows, { rerender: true }); } _getScopedValue(scope, keyPath) { if ((scope == null ? void 0 : scope.type) === "entity") { const entry = this._getEntityRawEntries()[scope.index]; return this._getPathValue(entry, this._normalizePath(keyPath)); } return this._getPathValue(this._draftConfig, this._getScopedPath(scope, keyPath)); } _removeScopedValue(scope, keyPath, options = {}) { if ((scope == null ? void 0 : scope.type) === "entity") { const nextConfig = this._withEntityScopeConfig((entries) => { var _a, _b; const entry = this._isObject(entries[scope.index]) ? { ...entries[scope.index] } : { entity: (_b = (_a = entries[scope.index]) == null ? void 0 : _a.entity) != null ? _b : "" }; entries[scope.index] = this._deletePathValue(entry, this._normalizePath(keyPath)); return entries; }); return this._applyUserConfig(nextConfig, options); } return this._setValueAtPath(this._getScopedPath(scope, keyPath), void 0, options); } _applyScopedMutation(scope, mutator, options = {}) { if ((scope == null ? void 0 : scope.type) === "entity") { const nextConfig2 = this._withEntityScopeConfig((entries) => { var _a; const rawEntry = entries[scope.index]; const entry = this._isObject(rawEntry) ? this._cloneDeep(rawEntry) : { entity: (_a = rawEntry == null ? void 0 : rawEntry.entity) != null ? _a : "" }; entries[scope.index] = mutator(entry); return entries; }); return this._applyUserConfig(nextConfig2, options); } const nextConfig = mutator(this._cloneDeep(this._draftConfig)); return this._applyUserConfig(nextConfig, options); } _setScopedValue(scope, keyPath, value, options = {}) { return this._applyScopedMutation(scope, (target) => this._setPathValue(target, this._normalizePath(keyPath), value), options); } _removePathsFromTarget(target, keyPaths = []) { return keyPaths.reduce((nextTarget, keyPath) => this._deletePathValue(nextTarget, this._normalizePath(keyPath)), target); } _pruneEmptyObjectsInTarget(target, keyPath) { let nextTarget = target; const normalizedPath = this._normalizePath(keyPath); for (let index = normalizedPath.length; index > 0; index--) { const currentPath = normalizedPath.slice(0, index); const currentValue = this._getPathValue(nextTarget, currentPath); if (!this._isObject(currentValue) || Object.keys(currentValue).length) { break; } nextTarget = this._deletePathValue(nextTarget, currentPath); } return nextTarget; } _setCanonicalScopedValue(scope, canonicalPath, value, options = {}) { const { deprecatedKeys = [], prunePaths = [] } = options; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._setPathValue(target, this._normalizePath(canonicalPath), value); nextTarget = this._removePathsFromTarget(nextTarget, deprecatedKeys); const pathsToPrune = [this._normalizePath(canonicalPath).slice(0, -1), ...prunePaths.map((path) => this._normalizePath(path))]; pathsToPrune.forEach((path) => { if (path.length) { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, path); } }); return nextTarget; }, options); } _removeCanonicalScopedValue(scope, canonicalPath, options = {}) { const { deprecatedKeys = [], prunePaths = [] } = options; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, this._normalizePath(canonicalPath)); nextTarget = this._removePathsFromTarget(nextTarget, deprecatedKeys); const pathsToPrune = [this._normalizePath(canonicalPath).slice(0, -1), ...prunePaths.map((path) => this._normalizePath(path))]; pathsToPrune.forEach((path) => { if (path.length) { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, path); } }); return nextTarget; }, options); } _setScopedNumericOverride(scope, keyPath, rawValue, options = {}) { const normalizedValue = this._normalizeNumberValue(rawValue); if (rawValue === "" || rawValue === null || rawValue === void 0) { return this._removeScopedValue(scope, keyPath, options); } if (normalizedValue === null) { return false; } return this._setScopedValue(scope, keyPath, normalizedValue, options); } _setScopedTextOverride(scope, keyPath, rawValue, options = {}) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue) { return this._removeScopedValue(scope, keyPath, options); } return this._setScopedValue(scope, keyPath, normalizedValue, options); } _setCanonicalScopedNumericOverride(scope, canonicalPath, rawValue, options = {}) { const normalizedValue = this._normalizeNumberValue(rawValue); if (rawValue === "" || rawValue === null || rawValue === void 0 || normalizedValue === null) { return this._removeCanonicalScopedValue(scope, canonicalPath, options); } return this._setCanonicalScopedValue(scope, canonicalPath, normalizedValue, options); } _setCanonicalScopedTextOverride(scope, canonicalPath, rawValue, options = {}) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue) { return this._removeCanonicalScopedValue(scope, canonicalPath, options); } return this._setCanonicalScopedValue(scope, canonicalPath, normalizedValue, options); } _getResolvablePartsFromTarget(target, field, options = {}) { var _a, _b, _c, _d; const canonicalBasePath = (_a = options.canonicalBasePath) != null ? _a : ["scale", field]; const legacyFixedPath = (_b = options.legacyFixedPath) != null ? _b : [field]; const legacyEntityPath = (_c = options.legacyEntityPath) != null ? _c : [`${field}_entity`]; const structuredValue = this._getPathValue(target, canonicalBasePath); const legacyFixedValue = this._getPathValue(target, legacyFixedPath); const legacyEntityValue = this._getPathValue(target, legacyEntityPath); const structuredFixedValue = this._isObject(structuredValue) ? structuredValue == null ? void 0 : structuredValue.fixed : structuredValue; const structuredEntityValue = this._isObject(structuredValue) ? structuredValue == null ? void 0 : structuredValue.entity : void 0; return { fixed: structuredFixedValue != null ? structuredFixedValue : !this._isObject(legacyFixedValue) && legacyFixedValue !== void 0 ? legacyFixedValue : "", entity: (_d = structuredEntityValue != null ? structuredEntityValue : legacyEntityValue) != null ? _d : "" }; } _getResolvableScopedValue(scope, field, options = {}) { const target = (scope == null ? void 0 : scope.type) === "entity" ? this._getEntityRawEntries()[scope.index] : this._draftConfig; return this._getResolvablePartsFromTarget(target != null ? target : {}, field, options); } _getEffectiveResolvableScopedValue(scope, field, options = {}) { const localValue = this._getResolvableScopedValue(scope, field, options); if ((scope == null ? void 0 : scope.type) !== "entity") { return localValue; } const inheritedValue = this._getResolvableScopedValue({ type: "card" }, field, options); return { fixed: this._hasExplicitOverrideValue(localValue.fixed) ? localValue.fixed : inheritedValue.fixed, entity: this._hasExplicitOverrideValue(localValue.entity) ? localValue.entity : inheritedValue.entity }; } _setCanonicalResolvablePart(scope, field, part, rawValue, options = {}) { var _a, _b, _c, _d; const canonicalBasePath = (_a = options.canonicalBasePath) != null ? _a : ["scale", field]; const legacyFixedPath = (_b = options.legacyFixedPath) != null ? _b : [field]; const legacyEntityPath = (_c = options.legacyEntityPath) != null ? _c : [`${field}_entity`]; const prunePaths = (_d = options.prunePaths) != null ? _d : [canonicalBasePath, canonicalBasePath.slice(0, -1)]; const normalizedValue = part === "fixed" ? this._normalizeNumberValue(rawValue) : this._normalizeTextValue(rawValue).trim(); return this._applyScopedMutation(scope, (target) => { const currentParts = this._getResolvablePartsFromTarget(target != null ? target : {}, field, { canonicalBasePath, legacyFixedPath, legacyEntityPath }); const nextParts = { ...currentParts }; if (part === "fixed") { if (rawValue === "" || rawValue === null || rawValue === void 0 || normalizedValue === null) { delete nextParts.fixed; } else { nextParts.fixed = normalizedValue; } } else if (!normalizedValue) { delete nextParts.entity; } else { nextParts.entity = normalizedValue; } let nextTarget = this._cloneDeep(target); nextTarget = this._deletePathValue(nextTarget, legacyEntityPath); const legacyFixedValue = this._getPathValue(nextTarget, legacyFixedPath); if (!this._isObject(legacyFixedValue)) { nextTarget = this._deletePathValue(nextTarget, legacyFixedPath); } nextTarget = this._deletePathValue(nextTarget, canonicalBasePath); const hasFixed = nextParts.fixed !== void 0 && nextParts.fixed !== null && nextParts.fixed !== ""; const hasEntity = nextParts.entity !== void 0 && nextParts.entity !== null && nextParts.entity !== ""; if (hasFixed || hasEntity) { const nextValue = {}; if (hasFixed) nextValue.fixed = nextParts.fixed; if (hasEntity) nextValue.entity = nextParts.entity; nextTarget = this._setPathValue(nextTarget, canonicalBasePath, nextValue); } prunePaths.forEach((path) => { if (path.length) { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, path); } }); return nextTarget; }, options); } _clearCanonicalResolvableValue(scope, field, options = {}) { var _a, _b, _c, _d; const canonicalBasePath = (_a = options.canonicalBasePath) != null ? _a : ["scale", field]; const legacyFixedPath = (_b = options.legacyFixedPath) != null ? _b : [field]; const legacyEntityPath = (_c = options.legacyEntityPath) != null ? _c : [`${field}_entity`]; const prunePaths = (_d = options.prunePaths) != null ? _d : [canonicalBasePath, canonicalBasePath.slice(0, -1)]; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, canonicalBasePath); nextTarget = this._deletePathValue(nextTarget, legacyEntityPath); const legacyFixedValue = this._getPathValue(nextTarget, legacyFixedPath); if (!this._isObject(legacyFixedValue)) { nextTarget = this._deletePathValue(nextTarget, legacyFixedPath); } prunePaths.forEach((path) => { if (path.length) { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, path); } }); return nextTarget; }, options); } _getScopedDisplayValue(scope, canonicalPath, fallbackPaths = []) { const valuesToTry = [canonicalPath, ...fallbackPaths]; for (const path of valuesToTry) { const value = this._getScopedValue(scope, path); if (value !== void 0 && value !== null && value !== "") { return value; } } return ""; } _getEffectiveScopedDisplayValue(scope, canonicalPath, fallbackPaths = []) { const valuesToTry = [canonicalPath, ...fallbackPaths]; for (const path of valuesToTry) { const value = this._getScopedValue(scope, path); if (value !== void 0 && value !== null && value !== "") { return value; } } if ((scope == null ? void 0 : scope.type) === "entity") { for (const path of valuesToTry) { const value = this._getScopedValue({ type: "card" }, path); if (value !== void 0 && value !== null && value !== "") { return value; } } } return ""; } _getScopedFormattingValue(scope, key) { var _a, _b; return (_b = (_a = this._getScopedValue(scope, ["formatting", key])) != null ? _a : this._getScopedValue(scope, [key])) != null ? _b : ""; } _getEffectiveScopedFormattingValue(scope, key) { return this._getEffectiveScopedDisplayValue(scope, ["formatting", key], [[key]]); } _setScopedFormattingUnit(scope, rawValue) { return this._setCanonicalScopedTextOverride(scope, ["formatting", "unit"], rawValue, { deprecatedKeys: [["unit"]], prunePaths: [["formatting"]] }); } _setScopedFormattingDecimal(scope, rawValue) { const normalizedValue = this._normalizeDecimalValue(rawValue); if (rawValue === "" || rawValue === null || rawValue === void 0) { return this._removeCanonicalScopedValue(scope, ["formatting", "decimal"], { deprecatedKeys: [["decimal"]], prunePaths: [["formatting"]] }); } if (normalizedValue === null) { return false; } return this._setCanonicalScopedValue(scope, ["formatting", "decimal"], normalizedValue, { deprecatedKeys: [["decimal"]], prunePaths: [["formatting"]] }); } _clearFormattingOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["formatting", "unit"]); nextTarget = this._deletePathValue(nextTarget, ["formatting", "decimal"]); nextTarget = this._deletePathValue(nextTarget, ["unit"]); nextTarget = this._deletePathValue(nextTarget, ["decimal"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["formatting"]); return nextTarget; }, { rerender: true }); } _hasFormattingOverride(scope) { var _a; const formattingValue = (_a = this._getScopedValue(scope, ["formatting"])) != null ? _a : {}; if (this._isObject(formattingValue) && (Object.prototype.hasOwnProperty.call(formattingValue, "unit") || Object.prototype.hasOwnProperty.call(formattingValue, "decimal"))) { return true; } return this._getScopedValue(scope, ["unit"]) !== void 0 || this._getScopedValue(scope, ["decimal"]) !== void 0; } _getScopedLayoutValue(scope, key) { var _a, _b, _c, _d, _e, _f, _g, _h, _i; if (key === "height") { return (_b = (_a = this._getScopedValue(scope, ["layout", "height"])) != null ? _a : this._getScopedValue(scope, ["height"])) != null ? _b : ""; } if (key === "position") { return (_d = (_c = this._getScopedValue(scope, ["layout", "label", "position"])) != null ? _c : this._getScopedValue(scope, ["label_position"])) != null ? _d : ""; } if (key === "width") { return (_f = (_e = this._getScopedValue(scope, ["layout", "label", "width"])) != null ? _e : this._getScopedValue(scope, ["label_width"])) != null ? _f : ""; } if (key === "hero_size") { return (_h = (_g = this._getScopedValue(scope, ["layout", "hero", "size"])) != null ? _g : this._getScopedValue(scope, ["layout", "label", "hero_size"])) != null ? _h : ""; } if (key === "value_size") { return (_i = this._getScopedValue(scope, ["layout", "hero", "value_size"])) != null ? _i : ""; } return ""; } _getEffectiveScopedLayoutValue(scope, key) { if (key === "height") { return this._getEffectiveScopedDisplayValue(scope, ["layout", "height"], [["height"]]); } if (key === "position") { return this._getEffectiveScopedDisplayValue(scope, ["layout", "label", "position"], [["label_position"]]); } if (key === "width") { return this._getEffectiveScopedDisplayValue(scope, ["layout", "label", "width"], [["label_width"]]); } if (key === "hero_size") { return this._getEffectiveScopedDisplayValue(scope, ["layout", "hero", "size"], [["layout", "label", "hero_size"]]); } if (key === "value_size") { return this._getEffectiveScopedDisplayValue(scope, ["layout", "hero", "value_size"]); } return ""; } _setScopedLayoutLabelPosition(scope, value) { if (!value) { return this._removeCanonicalScopedValue(scope, ["layout", "label", "position"], { deprecatedKeys: [["label_position"]], prunePaths: [["layout", "label"], ["layout"]], rerender: true }); } const didSet = this._setCanonicalScopedValue(scope, ["layout", "label", "position"], value, { deprecatedKeys: [["label_position"]], prunePaths: [["layout", "label"], ["layout"]], rerender: true }); if (!didSet || value === "hero") return didSet; this._removeCanonicalScopedValue(scope, ["layout", "label", "hero_size"], { prunePaths: [["layout", "label"], ["layout"]], rerender: true }); this._removeCanonicalScopedValue(scope, ["layout", "hero"], { prunePaths: [["layout"]], rerender: true }); return true; } _setLayoutLabelPosition(value) { return this._setScopedLayoutLabelPosition({ type: "card" }, value); } _setScopedLayoutHeroSize(scope, value) { if (!value) { return this._removeCanonicalScopedValue(scope, ["layout", "hero", "size"], { deprecatedKeys: [["layout", "label", "hero_size"]], prunePaths: [["layout", "hero"], ["layout"]] }); } return this._setCanonicalScopedValue(scope, ["layout", "hero", "size"], value, { deprecatedKeys: [["layout", "label", "hero_size"]], prunePaths: [["layout", "hero"], ["layout"]] }); } _setLayoutHeroSize(value) { return this._setScopedLayoutHeroSize({ type: "card" }, value); } _normalizeHeroValueSizeValue(value) { const numericValue = this._normalizeNumberValue(value); if (numericValue === null) return null; return Math.min(112, Math.max(12, numericValue)); } _setScopedLayoutHeroValueSize(scope, value) { if (value === "" || value === null || value === void 0) { return this._removeCanonicalScopedValue(scope, ["layout", "hero", "value_size"], { prunePaths: [["layout", "hero"], ["layout"]] }); } const valueSize = this._normalizeHeroValueSizeValue(value); if (valueSize === null) return false; return this._setCanonicalScopedValue(scope, ["layout", "hero", "value_size"], valueSize, { prunePaths: [["layout", "hero"], ["layout"]] }); } _setLayoutHeroValueSize(value) { return this._setScopedLayoutHeroValueSize({ type: "card" }, value); } _setScopedLayoutHeight(scope, value) { const numericValue = this._normalizeNumberValue(value); if (value === "" || value === null || value === void 0) { return this._removeCanonicalScopedValue(scope, ["layout", "height"], { deprecatedKeys: [["height"]], prunePaths: [["layout"]] }); } if (numericValue === null || numericValue < 24) { return false; } return this._setCanonicalScopedValue(scope, ["layout", "height"], numericValue, { deprecatedKeys: [["height"]], prunePaths: [["layout"]] }); } _setLayoutHeight(value) { return this._setScopedLayoutHeight({ type: "card" }, value); } _setScopedLayoutLabelWidth(scope, value) { const numericValue = this._normalizeNumberValue(value); if (value === "" || value === null || value === void 0) { return this._removeCanonicalScopedValue(scope, ["layout", "label", "width"], { deprecatedKeys: [["label_width"]], prunePaths: [["layout", "label"], ["layout"]] }); } if (numericValue === null) { return false; } return this._setCanonicalScopedValue(scope, ["layout", "label", "width"], numericValue, { deprecatedKeys: [["label_width"]], prunePaths: [["layout", "label"], ["layout"]] }); } _clearLayoutOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["layout", "height"]); nextTarget = this._deletePathValue(nextTarget, ["layout", "label", "position"]); nextTarget = this._deletePathValue(nextTarget, ["layout", "label", "hero_size"]); nextTarget = this._deletePathValue(nextTarget, ["layout", "label", "width"]); nextTarget = this._deletePathValue(nextTarget, ["layout", "hero"]); nextTarget = this._deletePathValue(nextTarget, ["height"]); nextTarget = this._deletePathValue(nextTarget, ["label_position"]); nextTarget = this._deletePathValue(nextTarget, ["label_width"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["layout", "label"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["layout"]); return nextTarget; }, { rerender: true }); } _hasLayoutOverride(scope) { var _a, _b; const layoutValue = (_a = this._getScopedValue(scope, ["layout"])) != null ? _a : {}; const labelValue = this._isObject(layoutValue) ? (_b = layoutValue.label) != null ? _b : {} : {}; if (this._isObject(layoutValue) && (Object.prototype.hasOwnProperty.call(layoutValue, "height") || this._isObject(labelValue) && (Object.prototype.hasOwnProperty.call(labelValue, "position") || Object.prototype.hasOwnProperty.call(labelValue, "hero_size") || Object.prototype.hasOwnProperty.call(labelValue, "width")))) { return true; } if (this._isObject(layoutValue) && this._isObject(layoutValue.hero) && Object.keys(layoutValue.hero).length) { return true; } return this._getScopedValue(scope, ["height"]) !== void 0 || this._getScopedValue(scope, ["label_position"]) !== void 0 || this._getScopedValue(scope, ["label_width"]) !== void 0; } _setScaleBound(key, value) { return this._setCanonicalResolvablePart({ type: "card" }, key, "fixed", value); } _clearScaleOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["scale", "min"]); nextTarget = this._deletePathValue(nextTarget, ["scale", "max"]); nextTarget = this._deletePathValue(nextTarget, ["min"]); nextTarget = this._deletePathValue(nextTarget, ["max"]); nextTarget = this._deletePathValue(nextTarget, ["min_entity"]); nextTarget = this._deletePathValue(nextTarget, ["max_entity"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["scale"]); return nextTarget; }, { rerender: true }); } _setBarFillStyle(value) { return this._setScopedBarFillStyle({ type: "card" }, value); } _setBarColor(value) { return this._setScopedBarColor({ type: "card" }, value); } _setGradientStops(stops, options = {}) { return this._setScopedGradientStops({ type: "card" }, stops, options); } _setSegments(segments, options = {}) { return this._setScopedSegments({ type: "card" }, segments, options); } _getDefaultGradientStops() { return [ { pos: 0, color: "#4CAF50" }, { pos: 50, color: "#FF9800" }, { pos: 100, color: "#F44336" } ]; } _normalizeGradientStopPosValue(rawValue) { const numericValue = this._normalizeNumberValue(rawValue); if (numericValue === null || !Number.isFinite(numericValue)) { return null; } if (numericValue < 0 || numericValue > 100) { return null; } return numericValue; } _sanitizeGradientStopsForEmit(stops) { if (!Array.isArray(stops)) { return []; } return stops.map((stop) => { if (!this._isObject(stop)) { return null; } const pos = this._normalizeGradientStopPosValue(stop.pos); const color = this._normalizeTextValue(stop.color).trim(); if (pos === null || !color) { return null; } return { ...stop, pos, color }; }).filter(Boolean).sort((left, right) => left.pos - right.pos); } _getGradientStopDraftColorDefault(scope = { type: "card" }) { var _a; const committedStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); if (committedStops.length) { return (_a = committedStops[committedStops.length - 1].color) != null ? _a : "#4CAF50"; } return this._getDefaultGradientStops()[0].color; } _getNextSuggestedGradientStopPos(scope = { type: "card" }) { const committedStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); if (!committedStops.length) { return 0; } const highest = committedStops[committedStops.length - 1]; if (highest.pos >= 100) { return ""; } let suggestedPos; if (committedStops.length === 1) { suggestedPos = highest.pos + 25; } else { const previous = committedStops[committedStops.length - 2]; suggestedPos = highest.pos + (highest.pos - previous.pos); } const clampedPos = Math.min(100, Math.max(0, suggestedPos)); if (committedStops.some((stop) => stop.pos === clampedPos)) { return ""; } return clampedPos; } _getGradientStopsDraftKey(scope) { return (scope == null ? void 0 : scope.type) === "entity" ? `entity:${scope.index}` : "card"; } _getGradientStopPosTextKey(scope, stopIndex) { return `${this._getGradientStopsDraftKey(scope)}:pos:${stopIndex}`; } _getGradientStopPosText(scope = { type: "card" }, stopIndex, fallbackValue = "") { const key = this._getGradientStopPosTextKey(scope, stopIndex); if (this._gradientStopPosTexts.has(key)) { return this._gradientStopPosTexts.get(key); } if (fallbackValue === "" || fallbackValue === null || fallbackValue === void 0) { return ""; } return String(fallbackValue); } _setGradientStopPosText(scope, stopIndex, rawValue) { this._gradientStopPosTexts.set( this._getGradientStopPosTextKey(scope, stopIndex), this._normalizeTextValue(rawValue) ); } _clearGradientStopPosText(scope, stopIndex) { this._gradientStopPosTexts.delete(this._getGradientStopPosTextKey(scope, stopIndex)); } _clearGradientStopScopeTextState(scope) { const prefix = `${this._getGradientStopsDraftKey(scope)}:pos:`; for (const key of this._gradientStopPosTexts.keys()) { if (key.startsWith(prefix)) { this._gradientStopPosTexts.delete(key); } } for (const key of this._gradientStopValidationMessages.keys()) { if (key.startsWith(prefix)) { this._gradientStopValidationMessages.delete(key); } } } _getGradientStopsUiRows(scope = { type: "card" }) { const key = this._getGradientStopsDraftKey(scope); if (this._gradientStopsUiRows.has(key)) { return this._cloneDeep(this._gradientStopsUiRows.get(key)); } return null; } _setGradientStopsUiRows(scope, stops) { this._gradientStopsUiRows.set(this._getGradientStopsDraftKey(scope), this._cloneDeep(stops)); } _getStoredScopedGradientStops(scope = { type: "card" }) { const structuredValue = this._getScopedValue(scope, ["bar", "gradient_stops"]); if (structuredValue !== void 0) { return structuredValue; } const legacyValue = this._getScopedValue(scope, ["gradient_stops"]); if (legacyValue !== void 0) { return legacyValue; } return null; } _getFallbackGradientStops(scope = { type: "card" }) { if ((scope == null ? void 0 : scope.type) === "entity") { const inheritedStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue({ type: "card" })); return inheritedStops.length ? inheritedStops : this._getDefaultGradientStops(); } return this._getDefaultGradientStops(); } _createGradientStopDraftState(scope = { type: "card" }) { const suggestedPos = this._getNextSuggestedGradientStopPos(scope); return { pos: suggestedPos === "" ? "" : String(suggestedPos), color: this._getGradientStopDraftColorDefault(scope) }; } _getGradientStopsDraftState(scope = { type: "card" }) { const key = this._getGradientStopsDraftKey(scope); if (!this._gradientStopsDrafts.has(key)) { this._gradientStopsDrafts.set(key, this._createGradientStopDraftState(scope)); } return this._cloneDeep(this._gradientStopsDrafts.get(key)); } _setGradientStopsDraftState(scope, nextDraft, options = {}) { var _a, _b; this._gradientStopsDrafts.set(this._getGradientStopsDraftKey(scope), { pos: (_a = nextDraft == null ? void 0 : nextDraft.pos) != null ? _a : "", color: (_b = nextDraft == null ? void 0 : nextDraft.color) != null ? _b : this._getGradientStopDraftColorDefault(scope) }); if (options == null ? void 0 : options.refreshOnly) { this._refreshGradientDraftUi(scope); return; } this._render(); } _setGradientStopsDraftField(scope, field, rawValue) { const currentDraft = this._getGradientStopsDraftState(scope); const nextValue = field === "color" ? this._normalizeTextValue(rawValue).trim() : this._normalizeTextValue(rawValue); this._setGradientStopsDraftState(scope, { ...currentDraft, [field]: nextValue }, { refreshOnly: field === "pos" }); } _getValidGradientDraftStop(scope = { type: "card" }) { const draft = this._getGradientStopsDraftState(scope); const pos = this._normalizeGradientStopPosValue(draft.pos); const color = this._normalizeTextValue(draft.color).trim(); if (pos === null || !color) { return null; } return { pos, color }; } _hasGradientStopDuplicate(scope = { type: "card" }, candidatePos, excludeIndex = null) { return this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)).some((stop, index) => index !== excludeIndex && stop.pos === candidatePos); } _canAddGradientStop(scope = { type: "card" }) { const draftStop = this._getValidGradientDraftStop(scope); if (!draftStop) { return false; } return !this._hasGradientStopDuplicate(scope, draftStop.pos); } _getGradientDraftValidationMessage(scope = { type: "card" }) { const draft = this._getGradientStopsDraftState(scope); const normalizedPosText = this._normalizeTextValue(draft.pos).trim(); const normalizedColor = this._normalizeTextValue(draft.color).trim(); if (!normalizedPosText) { return "Enter a position to add a stop."; } if (this._normalizeGradientStopPosValue(draft.pos) === null) { return "Enter a value from 0 to 100."; } if (!normalizedColor) { return "Choose a color to add a stop."; } if (this._hasGradientStopDuplicate(scope, this._normalizeGradientStopPosValue(draft.pos))) { return "Position already exists."; } return ""; } _isDefaultGradientStops(stops) { const sanitizedStops = this._sanitizeGradientStopsForEmit(stops); const defaultStops = this._getDefaultGradientStops(); if (sanitizedStops.length !== defaultStops.length) { return false; } return sanitizedStops.every((stop, index) => stop.pos === defaultStops[index].pos && this._normalizeColorComparisonValue(stop.color) === this._normalizeColorComparisonValue(defaultStops[index].color)); } _setScopedGradientStops(scope, stops, options = {}) { var _a; const sanitizedStops = this._sanitizeGradientStopsForEmit(stops); const shouldRemove = sanitizedStops.length < 2 || this._isDefaultGradientStops(sanitizedStops); const previousUiRowsJson = this._serializeConfig((_a = this._getGradientStopsUiRows(scope)) != null ? _a : []); this._clearGradientStopScopeTextState(scope); this._setGradientStopsUiRows(scope, sanitizedStops); const applied = this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["gradient_stops"]); nextTarget = this._deletePathValue(nextTarget, ["bar", "gradient_stops"]); if (!shouldRemove) { nextTarget = this._setPathValue(nextTarget, ["bar", "gradient_stops"], sanitizedStops); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }, options); if (applied === false && (options == null ? void 0 : options.rerender) && this._serializeConfig(sanitizedStops) !== previousUiRowsJson) { this._render(); } if (applied !== false && !(options == null ? void 0 : options.rerender)) { this._refreshGradientDraftUi(scope); } return applied; } _clearGradientStopsOverride(scope) { var _a; const previousUiRowsJson = this._serializeConfig((_a = this._getGradientStopsUiRows(scope)) != null ? _a : []); this._gradientStopsDrafts.delete(this._getGradientStopsDraftKey(scope)); this._gradientStopsUiRows.delete(this._getGradientStopsDraftKey(scope)); this._clearGradientStopScopeTextState(scope); const applied = this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["bar", "gradient_stops"]); nextTarget = this._deletePathValue(nextTarget, ["gradient_stops"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }, { rerender: true }); if (applied === false && previousUiRowsJson !== this._serializeConfig([])) { this._render(); } return applied; } _setScopedSegments(scope, segments, options = {}) { const nextSegments = (options == null ? void 0 : options.sort) === false ? this._cloneDeep(segments) : this._sortSegmentsForEditor(segments); const fallbackSegments = this._getFallbackSegments(scope); const shouldRemove = !Array.isArray(nextSegments) || !nextSegments.length || fallbackSegments.length > 0 && this._segmentsEqualForEditor(nextSegments, fallbackSegments); this._setSegmentsUiRows(scope, nextSegments); const applied = this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["bar", "segments"]); nextTarget = this._deletePathValue(nextTarget, ["segments"]); nextTarget = this._deletePathValue(nextTarget, ["severity"]); if (!shouldRemove) { nextTarget = this._setPathValue(nextTarget, ["bar", "segments"], nextSegments); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }, options); if (applied !== false) { this._refreshSegmentUi(scope); } return applied; } _clearSegmentsOverride(scope) { this._segmentDrafts.delete(this._getSegmentsScopeKey(scope)); this._segmentUiRows.delete(this._getSegmentsScopeKey(scope)); this._clearSegmentScopeTextState(scope); return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["bar", "segments"]); nextTarget = this._deletePathValue(nextTarget, ["segments"]); nextTarget = this._deletePathValue(nextTarget, ["severity"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }, { rerender: true }); } _setNeedle(value) { return this._setScopedNeedleMode({ type: "card" }, value ? "enabled" : "disabled"); } _getScopedPeakConfig(scope) { var _a, _b; const rawPeak = this._getScopedValue(scope, ["peak"]); const rawPeakMarker = this._getScopedValue(scope, ["peak_marker"]); const rawLegacyShow = this._getScopedValue(scope, ["show_peak"]); const rawLegacyColor = this._getScopedValue(scope, ["peak_color"]); const defaultColor = "#888"; let mode = (scope == null ? void 0 : scope.type) === "entity" ? "inherit" : "disabled"; let color = ""; if (this._isObject(rawPeak)) { if (rawPeak.enabled === true) { mode = "enabled"; } else if (rawPeak.enabled === false) { mode = "disabled"; } color = (_a = rawPeak.color) != null ? _a : color; } if (this._isObject(rawPeakMarker)) { if (rawPeakMarker.show === true) { mode = "enabled"; } else if (rawPeakMarker.show === false) { mode = "disabled"; } else if ((scope == null ? void 0 : scope.type) !== "entity") { mode = "disabled"; } color = (_b = rawPeakMarker.color) != null ? _b : color; } if (rawLegacyShow === true) { mode = "enabled"; } else if (rawLegacyShow === false) { mode = "disabled"; } color = color || rawLegacyColor || ""; if (color && this._normalizeColorComparisonValue(color) === this._normalizeColorComparisonValue(defaultColor)) { color = ""; } return { mode, color }; } _getEffectiveScopedPeakConfig(scope) { const localPeak = this._getScopedPeakConfig(scope); if ((scope == null ? void 0 : scope.type) !== "entity") { return localPeak; } if (!this._hasPeakOverride(scope)) { return this._getScopedPeakConfig({ type: "card" }); } const inheritedPeak = this._getScopedPeakConfig({ type: "card" }); return { mode: localPeak.mode === "inherit" ? inheritedPeak.mode : localPeak.mode, color: localPeak.color || inheritedPeak.color }; } _hasPeakOverride(scope) { var _a, _b; const peakValue = (_a = this._getScopedValue(scope, ["peak"])) != null ? _a : {}; if (this._isObject(peakValue) && (Object.prototype.hasOwnProperty.call(peakValue, "enabled") || Object.prototype.hasOwnProperty.call(peakValue, "color"))) { return true; } const peakMarkerValue = (_b = this._getScopedValue(scope, ["peak_marker"])) != null ? _b : {}; if (this._isObject(peakMarkerValue) && (Object.prototype.hasOwnProperty.call(peakMarkerValue, "show") || Object.prototype.hasOwnProperty.call(peakMarkerValue, "color"))) { return true; } return this._getScopedValue(scope, ["show_peak"]) !== void 0 || this._getScopedValue(scope, ["peak_color"]) !== void 0; } _getPeakSummary(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasPeakOverride(scope)) return "Inherited"; const peak = this._getScopedPeakConfig(scope); if (peak.mode === "disabled") return peak.color ? "Disabled \u2022 Custom color" : "Disabled"; if (peak.mode === "enabled") return peak.color ? "Enabled \u2022 Custom color" : "Enabled"; if (peak.color) return "Custom color"; return "Inherited"; } _clearPeakOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["peak", "enabled"]); nextTarget = this._deletePathValue(nextTarget, ["peak", "color"]); nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["peak"]); return nextTarget; }, { rerender: true }); } _setScopedPeakEnabled(scope, value) { const boolValue = !!value; const defaultColor = "#888"; return this._applyScopedMutation(scope, (target) => { var _a, _b, _c; let nextTarget = this._cloneDeep(target); const currentPeak = this._isObject(this._getPathValue(nextTarget, ["peak"])) ? this._cloneDeep(this._getPathValue(nextTarget, ["peak"])) : {}; const currentColor = (_c = (_b = (_a = currentPeak.color) != null ? _a : this._isObject(this._getPathValue(nextTarget, ["peak_marker"])) ? this._getPathValue(nextTarget, ["peak_marker", "color"]) : void 0) != null ? _b : this._getPathValue(nextTarget, ["peak_color"])) != null ? _c : defaultColor; if ((scope == null ? void 0 : scope.type) === "entity" || boolValue) { currentPeak.enabled = boolValue; } else { delete currentPeak.enabled; } if (currentColor && this._normalizeColorComparisonValue(currentColor) !== this._normalizeColorComparisonValue(defaultColor)) { currentPeak.color = currentColor; } else { delete currentPeak.color; } if (Object.keys(currentPeak).length) { nextTarget = this._setPathValue(nextTarget, ["peak"], currentPeak); } else { nextTarget = this._deletePathValue(nextTarget, ["peak"]); } nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["peak"]); return nextTarget; }); } _setScopedPeakColor(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); const defaultColor = "#888"; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const currentPeak = this._isObject(this._getPathValue(nextTarget, ["peak"])) ? this._cloneDeep(this._getPathValue(nextTarget, ["peak"])) : {}; const currentConfig = this._getScopedPeakConfig(scope); delete currentPeak.color; if (normalizedValue && this._normalizeColorComparisonValue(normalizedValue) !== this._normalizeColorComparisonValue(defaultColor)) { currentPeak.color = normalizedValue; } if ((scope == null ? void 0 : scope.type) === "entity") { if (currentConfig.mode === "enabled") currentPeak.enabled = true; if (currentConfig.mode === "disabled") currentPeak.enabled = false; } else if (currentConfig.mode === "enabled") { currentPeak.enabled = true; } if (Object.keys(currentPeak).length) { nextTarget = this._setPathValue(nextTarget, ["peak"], currentPeak); } else { nextTarget = this._deletePathValue(nextTarget, ["peak"]); } nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["peak"]); return nextTarget; }); } _setFixedMarkerValue(rootKey, enabled, value) { const numericValue = this._normalizeNumberValue(value); if (!enabled || numericValue === null) { return this._removeCanonicalScopedValue({ type: "card" }, [rootKey, "at", "fixed"], { deprecatedKeys: rootKey === "target" ? [["target_entity"]] : [], prunePaths: [[rootKey, "at"], [rootKey]] }); } return this._setCanonicalScopedValue({ type: "card" }, [rootKey, "at", "fixed"], numericValue, { deprecatedKeys: rootKey === "target" ? [["target_entity"]] : [], prunePaths: [[rootKey, "at"], [rootKey]] }); } _setPeakShow(value) { return this._setScopedPeakEnabled({ type: "card" }, value); } _readFixedMarker(rootKey) { const rawValue = this._draftConfig[rootKey]; if (this._isObject(rawValue)) { const fixed = this._isObject(rawValue == null ? void 0 : rawValue.at) ? rawValue.at.fixed : rawValue == null ? void 0 : rawValue.at; return { enabled: fixed !== void 0 && fixed !== null && fixed !== "", value: fixed != null ? fixed : "" }; } return { enabled: rawValue !== void 0 && rawValue !== null && rawValue !== "", value: rawValue != null ? rawValue : "" }; } _getGradientStopsValue() { return this._getScopedGradientStopsValue({ type: "card" }); } _getSegmentsValue() { return this._getScopedSegmentsValue({ type: "card" }); } _getSegmentsScopeKey(scope = { type: "card" }) { return (scope == null ? void 0 : scope.type) === "entity" ? `entity:${scope.index}` : "card"; } _getSegmentBoundaryTextKey(scope, segmentIndex, field) { return `${this._getSegmentsScopeKey(scope)}:${segmentIndex}:${field}`; } _getSegmentBoundaryText(scope = { type: "card" }, segmentIndex, field, fallbackValue = "") { const key = this._getSegmentBoundaryTextKey(scope, segmentIndex, field); if (this._segmentBoundaryTexts.has(key)) { return this._segmentBoundaryTexts.get(key); } return this._formatSegmentBoundaryValue(fallbackValue); } _setSegmentBoundaryText(scope, segmentIndex, field, rawValue) { this._segmentBoundaryTexts.set( this._getSegmentBoundaryTextKey(scope, segmentIndex, field), this._normalizeTextValue(rawValue) ); } _clearSegmentBoundaryText(scope, segmentIndex, field) { this._segmentBoundaryTexts.delete(this._getSegmentBoundaryTextKey(scope, segmentIndex, field)); } _clearSegmentScopeTextState(scope) { const prefix = `${this._getSegmentsScopeKey(scope)}:`; for (const key of this._segmentBoundaryTexts.keys()) { if (key.startsWith(prefix)) { this._segmentBoundaryTexts.delete(key); } } } _getSegmentsUiRows(scope = { type: "card" }) { const key = this._getSegmentsScopeKey(scope); if (this._segmentUiRows.has(key)) { return this._cloneDeep(this._segmentUiRows.get(key)); } return null; } _setSegmentsUiRows(scope, rows) { this._segmentUiRows.set(this._getSegmentsScopeKey(scope), this._cloneDeep(rows)); } _getSegmentDraftState(scope = { type: "card" }) { const key = this._getSegmentsScopeKey(scope); if (!this._segmentDrafts.has(key)) { this._segmentDrafts.set(key, this._createSegmentDraftState(scope)); } return this._cloneDeep(this._segmentDrafts.get(key)); } _setSegmentDraftState(scope, nextDraft, options = {}) { var _a, _b, _c; this._segmentDrafts.set(this._getSegmentsScopeKey(scope), { from: (_a = nextDraft == null ? void 0 : nextDraft.from) != null ? _a : "", to: (_b = nextDraft == null ? void 0 : nextDraft.to) != null ? _b : "", color: (_c = nextDraft == null ? void 0 : nextDraft.color) != null ? _c : this._getSegmentDraftColorDefault(scope) }); if (options == null ? void 0 : options.refreshOnly) { this._refreshSegmentUi(scope); return; } this._render(); } _setSegmentDraftField(scope, field, rawValue) { const currentDraft = this._getSegmentDraftState(scope); const nextValue = field === "color" ? this._normalizeTextValue(rawValue).trim() : this._normalizeTextValue(rawValue); this._setSegmentDraftState(scope, { ...currentDraft, [field]: nextValue }, { refreshOnly: true }); } _isSegmentFillStyle(fillStyle) { return ["bands", "soft_bands", "band_gradient"].includes(fillStyle); } _getDefaultSegments() { return [ { from: "0%", to: "33%", color: "#4CAF50" }, { from: "33%", to: "75%", color: "#FF9800" }, { from: "75%", to: "100%", color: "#F44336" } ]; } _getStoredScopedSegments(scope = { type: "card" }) { const structuredValue = this._getScopedValue(scope, ["bar", "segments"]); if (structuredValue !== void 0) { return structuredValue; } const legacySegments = this._getScopedValue(scope, ["segments"]); if (legacySegments !== void 0) { return legacySegments; } const legacySeverity = this._getScopedValue(scope, ["severity"]); if (legacySeverity !== void 0) { return legacySeverity; } return null; } _parseSegmentBoundaryInput(rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue) { return null; } const percentMatch = normalizedValue.match(/^\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*%\s*$/); const percent = percentMatch ? parseFloat(percentMatch[1]) : null; if (Number.isFinite(percent)) { return `${percent}%`; } const numericValue = this._normalizeNumberValue(normalizedValue); return numericValue === null ? null : numericValue; } _formatSegmentBoundaryValue(value) { if (typeof value === "string") { return value; } if (typeof value === "number" && Number.isFinite(value)) { return String(value); } if (this._isObject(value)) { if (Number.isFinite(value.percent)) { return `${value.percent}%`; } if (Number.isFinite(this._getFiniteNumber(value.fixed))) { return String(this._getFiniteNumber(value.fixed)); } } return ""; } _getSegmentDraftColorDefault(scope = { type: "card" }) { var _a; const segments = this._getScopedSegmentsValue(scope); if (segments.length) { return this._normalizeTextValue((_a = segments[segments.length - 1]) == null ? void 0 : _a.color).trim() || "#4a9eff"; } return "#4CAF50"; } _getNewSegmentDefaults(scope = { type: "card" }) { var _a; const segments = this._getScopedSegmentsValue(scope); const previous = segments[segments.length - 1]; const previousTo = (_a = previous == null ? void 0 : previous.to) != null ? _a : null; return { from: previousTo != null ? previousTo : "0%", to: "100%", color: "#4a9eff" }; } _createSegmentDraftState(scope = { type: "card" }) { var _a; const defaults = this._getNewSegmentDefaults(scope); const formattedFrom = this._formatSegmentBoundaryValue(defaults.from); const formattedTo = this._formatSegmentBoundaryValue(defaults.to); const draftFrom = formattedFrom === "100%" || formattedFrom === "100" ? "" : formattedFrom; const draftTo = draftFrom ? formattedTo : ""; return { from: draftFrom, to: draftTo, color: (_a = defaults.color) != null ? _a : this._getSegmentDraftColorDefault(scope) }; } _normalizeSegmentForEditorComparison(segment) { if (!this._isObject(segment)) { return null; } const from = this._formatSegmentBoundaryValue(segment.from).trim(); const to = this._formatSegmentBoundaryValue(segment.to).trim(); const color = this._normalizeColorComparisonValue(segment.color); if (!from || !to || !color) { return null; } return { from, to, color }; } _segmentsEqualForEditor(leftSegments, rightSegments) { const left = Array.isArray(leftSegments) ? leftSegments.map((segment) => this._normalizeSegmentForEditorComparison(segment)).filter(Boolean) : []; const right = Array.isArray(rightSegments) ? rightSegments.map((segment) => this._normalizeSegmentForEditorComparison(segment)).filter(Boolean) : []; if (left.length !== right.length) { return false; } return left.every((segment, index) => segment.from === right[index].from && segment.to === right[index].to && segment.color === right[index].color); } _getFallbackSegments(scope = { type: "card" }) { if ((scope == null ? void 0 : scope.type) === "entity") { const cardStoredSegments = this._getStoredScopedSegments({ type: "card" }); if (cardStoredSegments !== null) { return this._cloneDeep(this._getScopedSegmentsValue({ type: "card" })); } } if (!this._isSegmentFillStyle(this._getEffectiveFillStyleValue(scope))) { return []; } return this._cloneDeep(this._getDefaultSegments()); } _parseSegmentBoundaryText(rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue) { return { state: "empty", value: null }; } const parsed = this._parseSegmentBoundaryInput(normalizedValue); if (parsed === null) { return { state: "invalid", value: null }; } return { state: "valid", value: parsed }; } _compareSegmentBoundaries(left, right) { const leftValue = this._getSegmentPreviewBoundaryValue(left); const rightValue = this._getSegmentPreviewBoundaryValue(right); if (leftValue === null || rightValue === null) { return null; } if (leftValue < rightValue) return -1; if (leftValue > rightValue) return 1; return 0; } _buildSegmentValidationRows(scope = { type: "card" }) { var _a; const rows = (_a = this._getSegmentsUiRows(scope)) != null ? _a : this._getScopedSegmentsValue(scope); return rows.map((segment, index) => { const rawFrom = this._getSegmentBoundaryText(scope, index, "from", segment == null ? void 0 : segment.from); const rawTo = this._getSegmentBoundaryText(scope, index, "to", segment == null ? void 0 : segment.to); const parsedFrom = this._parseSegmentBoundaryText(rawFrom); const parsedTo = this._parseSegmentBoundaryText(rawTo); return { index, rawFrom, rawTo, parsedFrom, parsedTo }; }); } _getSegmentRowValidationMessage(scope = { type: "card" }, segmentIndex) { const rows = this._buildSegmentValidationRows(scope); const row = rows[segmentIndex]; if (!row) { return ""; } if (row.parsedFrom.state === "invalid" || row.parsedTo.state === "invalid" || row.parsedFrom.state === "empty" || row.parsedTo.state === "empty") { return "Enter valid from/to values."; } if (this._compareSegmentBoundaries(row.parsedFrom.value, row.parsedTo.value) !== -1) { return "From must be below To."; } const candidateFrom = this._getSegmentPreviewBoundaryValue(row.parsedFrom.value); const candidateTo = this._getSegmentPreviewBoundaryValue(row.parsedTo.value); for (const other of rows) { if (other.index === segmentIndex) continue; if (other.parsedFrom.state !== "valid" || other.parsedTo.state !== "valid") continue; const otherFrom = this._getSegmentPreviewBoundaryValue(other.parsedFrom.value); const otherTo = this._getSegmentPreviewBoundaryValue(other.parsedTo.value); if (candidateFrom === otherFrom) { return "Duplicate segment start."; } if (candidateFrom < otherTo && candidateTo > otherFrom) { return "Segments overlap."; } } return ""; } _getValidSegmentDraft(scope = { type: "card" }) { const draft = this._getSegmentDraftState(scope); const parsedFrom = this._parseSegmentBoundaryText(draft.from); const parsedTo = this._parseSegmentBoundaryText(draft.to); const color = this._normalizeTextValue(draft.color).trim(); if (parsedFrom.state !== "valid" || parsedTo.state !== "valid" || !color) { return null; } if (this._compareSegmentBoundaries(parsedFrom.value, parsedTo.value) !== -1) { return null; } const candidateFrom = this._getSegmentPreviewBoundaryValue(parsedFrom.value); const candidateTo = this._getSegmentPreviewBoundaryValue(parsedTo.value); const rows = this._buildSegmentValidationRows(scope); for (const row of rows) { if (row.parsedFrom.state !== "valid" || row.parsedTo.state !== "valid") continue; const otherFrom = this._getSegmentPreviewBoundaryValue(row.parsedFrom.value); const otherTo = this._getSegmentPreviewBoundaryValue(row.parsedTo.value); if (candidateFrom === otherFrom || candidateFrom < otherTo && candidateTo > otherFrom) { return null; } } return { from: parsedFrom.value, to: parsedTo.value, color }; } _canAddSegment(scope = { type: "card" }) { return !!this._getValidSegmentDraft(scope); } _getSegmentDraftValidationMessage(scope = { type: "card" }) { const draft = this._getSegmentDraftState(scope); const parsedFrom = this._parseSegmentBoundaryText(draft.from); const parsedTo = this._parseSegmentBoundaryText(draft.to); const color = this._normalizeTextValue(draft.color).trim(); if (!this._normalizeTextValue(draft.from).trim() && !this._normalizeTextValue(draft.to).trim()) { return ""; } if (parsedFrom.state !== "valid" || parsedTo.state !== "valid") { return "Enter valid from/to values."; } if (this._compareSegmentBoundaries(parsedFrom.value, parsedTo.value) !== -1) { return "From must be below To."; } if (!color) { return "Choose a color to add a segment."; } const candidateFrom = this._getSegmentPreviewBoundaryValue(parsedFrom.value); const candidateTo = this._getSegmentPreviewBoundaryValue(parsedTo.value); const rows = this._buildSegmentValidationRows(scope); for (const row of rows) { if (row.parsedFrom.state !== "valid" || row.parsedTo.state !== "valid") continue; const otherFrom = this._getSegmentPreviewBoundaryValue(row.parsedFrom.value); const otherTo = this._getSegmentPreviewBoundaryValue(row.parsedTo.value); if (candidateFrom === otherFrom) { return "Duplicate segment start."; } if (candidateFrom < otherTo && candidateTo > otherFrom) { return "Segments overlap."; } } return ""; } _getSegmentPreviewBoundaryValue(value) { if (typeof value === "string") { const match = value.trim().match(/^([+-]?(?:\d+(?:\.\d+)?|\.\d+))%$/); if (match) { const parsed = parseFloat(match[1]); return Number.isFinite(parsed) ? parsed : null; } } if (typeof value === "number" && Number.isFinite(value)) { return value; } if (this._isObject(value)) { if (Number.isFinite(value.percent)) { return value.percent; } const fixedValue = this._getFiniteNumber(value.fixed); if (Number.isFinite(fixedValue)) { return fixedValue; } } return null; } _sortSegmentsForEditor(segments) { if (!Array.isArray(segments)) { return []; } return this._cloneDeep(segments).sort((left, right) => { const leftFrom = this._getSegmentPreviewBoundaryValue(left == null ? void 0 : left.from); const rightFrom = this._getSegmentPreviewBoundaryValue(right == null ? void 0 : right.from); if (leftFrom === null && rightFrom === null) return 0; if (leftFrom === null) return 1; if (rightFrom === null) return -1; return leftFrom - rightFrom; }); } _getSegmentPreviewRows(scope = { type: "card" }) { var _a; const baseSegments = (_a = this._getSegmentsUiRows(scope)) != null ? _a : this._getScopedSegmentsValue(scope); const previewSegments = this._sortSegmentsForEditor(baseSegments); const validDraft = this._getValidSegmentDraft(scope); if (validDraft) { previewSegments.push(validDraft); } return this._sortSegmentsForEditor(previewSegments).filter((segment) => { const from = this._getSegmentPreviewBoundaryValue(segment == null ? void 0 : segment.from); const to = this._getSegmentPreviewBoundaryValue(segment == null ? void 0 : segment.to); return from !== null && to !== null && typeof (segment == null ? void 0 : segment.color) === "string" && segment.color.trim(); }); } _buildEditorSegmentPreviewStyle(scope = { type: "card" }) { const segments = this._getSegmentPreviewRows(scope); if (!segments.length) { return ""; } const fillStyle = this._getEffectiveFillStyleValue(scope); const stops = []; segments.forEach((segment) => { const from = Math.max(0, Math.min(100, this._getSegmentPreviewBoundaryValue(segment.from))); const to = Math.max(0, Math.min(100, this._getSegmentPreviewBoundaryValue(segment.to))); stops.push(`${segment.color} ${from}%`, `${segment.color} ${to}%`); }); if (fillStyle === "bands") { return `background:linear-gradient(to right,${stops.join(",")});background-repeat:no-repeat;`; } return `background:linear-gradient(to right,${stops.join(",")});background-repeat:no-repeat;`; } _getSegmentPreviewDomIds(scope = { type: "card" }) { if ((scope == null ? void 0 : scope.type) === "entity") { return { previewId: `entity-${scope.index}-segment-preview`, trackId: `entity-${scope.index}-segment-preview-track` }; } return { previewId: "card-segment-preview", trackId: "card-segment-preview-track" }; } _renderSegmentPreview(scope = { type: "card" }) { var _a; const { previewId, trackId } = this._getSegmentPreviewDomIds(scope); const segments = this._getSegmentPreviewRows(scope); const markers = []; segments.forEach((segment) => { const from = this._getSegmentPreviewBoundaryValue(segment.from); const to = this._getSegmentPreviewBoundaryValue(segment.to); if (from !== null) markers.push(from); if (to !== null) markers.push(to); }); const uniqueMarkers = [...new Set(markers)].sort((left, right) => left - right); return `
${uniqueMarkers.map((marker, index) => ` `).join("")}
`; } _refreshSegmentPreview(scope = { type: "card" }) { var _a; const { previewId, trackId } = this._getSegmentPreviewDomIds(scope); const track = this._getShadowElementById(trackId); if (!track) { return; } track.setAttribute("style", (_a = this._buildEditorSegmentPreviewStyle(scope)) != null ? _a : ""); const segments = this._getSegmentPreviewRows(scope); const markers = []; segments.forEach((segment) => { const from = this._getSegmentPreviewBoundaryValue(segment.from); const to = this._getSegmentPreviewBoundaryValue(segment.to); if (from !== null) markers.push(from); if (to !== null) markers.push(to); }); const uniqueMarkers = [...new Set(markers)].sort((left, right) => left - right); track.innerHTML = uniqueMarkers.map((marker, index) => ` `).join(""); } _getSegmentDomIds(scope = { type: "card" }) { if ((scope == null ? void 0 : scope.type) === "entity") { return { hintPrefix: `entity-${scope.index}-segment-row-hint-`, draftHintId: `entity-${scope.index}-segment-draft-hint`, addSelector: `button[data-action="add-entity-segment"][data-index="${scope.index}"]` }; } return { hintPrefix: "segment-row-hint-", draftHintId: "segment-draft-hint", addSelector: 'button[data-action="add-segment"]' }; } _refreshSegmentUi(scope = { type: "card" }) { var _a, _b; this._refreshSegmentPreview(scope); if (!this.shadowRoot) { return; } const { hintPrefix, draftHintId, addSelector } = this._getSegmentDomIds(scope); const addButton = this.shadowRoot.querySelector(addSelector); if (addButton) { addButton.disabled = !this._canAddSegment(scope); } const rows = (_a = this._getSegmentsUiRows(scope)) != null ? _a : this._getScopedSegmentsValue(scope); rows.forEach((_, index) => { var _a2; const hint = this._getShadowElementById(`${hintPrefix}${index}`); const message = this._getSegmentRowValidationMessage(scope, index); if (hint) { hint.textContent = message; (_a2 = hint.setAttribute) == null ? void 0 : _a2.call(hint, "style", message ? "" : "display:none"); } }); const draftHint = this._getShadowElementById(draftHintId); if (draftHint) { const message = this._getSegmentDraftValidationMessage(scope); draftHint.textContent = message; (_b = draftHint.setAttribute) == null ? void 0 : _b.call(draftHint, "style", message ? "" : "display:none"); } } _commitSegmentDraft(scope = { type: "card" }) { var _a; const draftSegment = this._getValidSegmentDraft(scope); if (!draftSegment) { this._refreshSegmentUi(scope); return false; } const committedSegments = (_a = this._getSegmentsUiRows(scope)) != null ? _a : this._getScopedSegmentsValue(scope); const nextSegments = this._sortSegmentsForEditor([...committedSegments, draftSegment]); const applied = this._setScopedSegments(scope, nextSegments, { rerender: true }); if (applied !== false) { this._segmentDrafts.set(this._getSegmentsScopeKey(scope), this._createSegmentDraftState(scope)); } return applied; } _commitSegmentBoundaryEdit(scope = { type: "card" }, segmentIndex, field, rawValue, inputEl = null) { var _a, _b; this._setSegmentBoundaryText(scope, segmentIndex, field, rawValue); const normalizedText = this._normalizeTextValue(rawValue).trim(); const parsedValue = this._parseSegmentBoundaryInput(rawValue); const nextValue = parsedValue === null ? normalizedText : parsedValue; const currentSegments = (_a = this._getSegmentsUiRows(scope)) != null ? _a : this._getScopedSegmentsValue(scope); const nextSegments = currentSegments.map((segment, currentIndex) => currentIndex === segmentIndex ? { ...segment, [field]: nextValue } : segment); this._clearSegmentBoundaryText(scope, segmentIndex, field); const applied = this._setScopedSegments(scope, nextSegments, { rerender: true }); const message = this._getSegmentRowValidationMessage(scope, segmentIndex); if (inputEl == null ? void 0 : inputEl.setCustomValidity) { inputEl.setCustomValidity(message || ""); if (message) { (_b = inputEl.reportValidity) == null ? void 0 : _b.call(inputEl); } } return applied; } _commitGradientStopDraft(scope = { type: "card" }) { const draftStop = this._getValidGradientDraftStop(scope); if (!draftStop || this._hasGradientStopDuplicate(scope, draftStop.pos)) { this._refreshGradientDraftUi(scope); return false; } const committedStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); const nextStops = [...committedStops, draftStop].sort((left, right) => left.pos - right.pos); const applied = this._setScopedGradientStops(scope, nextStops, { rerender: true }); if (applied !== false) { this._gradientStopsDrafts.set(this._getGradientStopsDraftKey(scope), { pos: (() => { const suggestion = this._getNextSuggestedGradientStopPos(scope); return suggestion === "" ? "" : String(suggestion); })(), color: draftStop.color }); } return applied; } _getGradientPreviewDomIds(scope = { type: "card" }) { if ((scope == null ? void 0 : scope.type) === "entity") { return { previewId: `entity-${scope.index}-gradient-preview`, trackId: `entity-${scope.index}-gradient-preview-track`, hintId: `entity-${scope.index}-gradient-draft-hint`, addSelector: `button[data-action="add-entity-gradient-stop"][data-index="${scope.index}"]`, draftInputId: `entity-${scope.index}-gradient-draft-pos` }; } return { previewId: "card-gradient-preview", trackId: "card-gradient-preview-track", hintId: "gradient-draft-hint", addSelector: 'button[data-action="add-gradient-stop"]', draftInputId: "gradient-draft-pos" }; } _refreshGradientDraftUi(scope = { type: "card" }) { var _a, _b, _c; if (!this.shadowRoot) { return; } const getById = (_b = (_a = this.shadowRoot.getElementById) == null ? void 0 : _a.bind(this.shadowRoot)) != null ? _b : ((id) => { var _a2, _b2, _c2; return (_c2 = (_b2 = (_a2 = this.shadowRoot).querySelector) == null ? void 0 : _b2.call(_a2, `#${id}`)) != null ? _c2 : null; }); const { previewId, trackId, hintId, addSelector, draftInputId } = this._getGradientPreviewDomIds(scope); const addButton = this.shadowRoot.querySelector(addSelector); if (addButton) { addButton.disabled = !this._canAddGradientStop(scope); } const draftInput = getById(draftInputId); if (draftInput && typeof draftInput.closest !== "function") { this._render(); return; } const draftContainer = draftInput == null ? void 0 : draftInput.closest(".gradient-stop-draft"); const nextMessage = this._getGradientDraftValidationMessage(scope); const existingHint = getById(hintId); if (nextMessage) { if (existingHint) { existingHint.textContent = nextMessage; } else if (draftContainer) { const hint = document.createElement("div"); hint.id = hintId; hint.className = "section-note"; hint.textContent = nextMessage; draftContainer.appendChild(hint); } } else if (existingHint) { existingHint.remove(); } const preview = getById(previewId); const track = getById(trackId); if (!preview || !track) { return; } track.setAttribute("style", (_c = this._getGradientPreviewStyle(scope)) != null ? _c : ""); const markerStops = this._buildGradientPreviewEffectiveStops(scope); const renderedStops = markerStops.length ? markerStops : this._getDefaultGradientStops(); track.innerHTML = renderedStops.map((stop, index) => ` `).join(""); } _commitGradientStopPosEdit(scope = { type: "card" }, stopIndex, rawValue, inputEl = null) { const nextPos = this._normalizeGradientStopPosValue(rawValue); if (nextPos === null || this._hasGradientStopDuplicate(scope, nextPos, stopIndex)) { if (inputEl == null ? void 0 : inputEl.setCustomValidity) { inputEl.setCustomValidity(nextPos === null ? "Enter a value from 0 to 100." : "Position already exists."); if (inputEl.reportValidity) { inputEl.reportValidity(); } } return false; } if (inputEl == null ? void 0 : inputEl.setCustomValidity) { inputEl.setCustomValidity(""); } const currentStops = this._getScopedGradientStopsValue(scope); const nextStops = currentStops.map((stop, currentStopIndex) => currentStopIndex === stopIndex ? { ...stop, pos: nextPos } : stop); this._clearGradientStopPosText(scope, stopIndex); return this._setScopedGradientStops(scope, nextStops, { rerender: true }); } _getFillStyleValue() { return this._getScopedFillStyleValue({ type: "card" }); } _getFillStyleFromColorMode(colorMode) { switch (colorMode) { case "single": return "solid"; case "gradient": return "gradient"; case "severity": return "bands"; case "severity_gradient": return "band_gradient"; default: return "bands"; } } _getScopedFillStyleValue(scope) { var _a; const fillStyle = this._getScopedValue(scope, ["bar", "fill_style"]); if (fillStyle) return fillStyle; const colorMode = (_a = this._getScopedValue(scope, ["bar", "color_mode"])) != null ? _a : this._getScopedValue(scope, ["color_mode"]); return this._getFillStyleFromColorMode(colorMode); } _getEffectiveScopedFillStyleValue(scope) { if ((scope == null ? void 0 : scope.type) !== "entity") { return this._getScopedFillStyleValue(scope); } return this._getEffectiveFillStyleValue(scope); } _setScopedBarFillStyle(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue || normalizedValue === "bands") { return this._removeCanonicalScopedValue(scope, ["bar", "fill_style"], { deprecatedKeys: [["color_mode"]], prunePaths: [["bar"]] }); } return this._setCanonicalScopedTextOverride(scope, ["bar", "fill_style"], normalizedValue, { deprecatedKeys: [["color_mode"]], prunePaths: [["bar"]] }); } _getScopedBarColorValue(scope) { var _a, _b; return (_b = (_a = this._getScopedValue(scope, ["bar", "color"])) != null ? _a : this._getScopedValue(scope, ["color"])) != null ? _b : "#4a9eff"; } _getEffectiveScopedBarColorValue(scope) { const value = this._getEffectiveScopedDisplayValue(scope, ["bar", "color"], [["color"]]); return value || "#4a9eff"; } _setScopedBarColor(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue || this._normalizeColorComparisonValue(normalizedValue) === this._normalizeColorComparisonValue("#4a9eff")) { return this._removeCanonicalScopedValue(scope, ["bar", "color"], { deprecatedKeys: [["color"]], prunePaths: [["bar"]] }); } return this._setCanonicalScopedTextOverride(scope, ["bar", "color"], normalizedValue, { deprecatedKeys: [["color"]], prunePaths: [["bar"]] }); } _getScopedBarSolidFillValue(scope) { return !!this._getScopedValue(scope, ["bar", "solid_fill"]); } _getEffectiveScopedBarSolidFillValue(scope) { if ((scope == null ? void 0 : scope.type) !== "entity") { return this._getScopedBarSolidFillValue(scope); } const localValue = this._getScopedValue(scope, ["bar", "solid_fill"]); if (localValue !== void 0) { return !!localValue; } return this._getScopedBarSolidFillValue({ type: "card" }); } _setScopedBarSolidFill(scope, value) { if (!value) { return this._removeCanonicalScopedValue(scope, ["bar", "solid_fill"], { prunePaths: [["bar"]] }); } return this._setCanonicalScopedValue(scope, ["bar", "solid_fill"], true, { prunePaths: [["bar"]] }); } _clearEntityBarAppearance(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["bar", "fill_style"]); nextTarget = this._deletePathValue(nextTarget, ["bar", "color"]); nextTarget = this._deletePathValue(nextTarget, ["bar", "solid_fill"]); nextTarget = this._deletePathValue(nextTarget, ["color_mode"]); nextTarget = this._deletePathValue(nextTarget, ["color"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }, { rerender: true }); } _hasEntityBarAppearanceOverride(scope) { var _a; const barValue = (_a = this._getScopedValue(scope, ["bar"])) != null ? _a : {}; if (this._isObject(barValue) && (Object.prototype.hasOwnProperty.call(barValue, "fill_style") || Object.prototype.hasOwnProperty.call(barValue, "color") || Object.prototype.hasOwnProperty.call(barValue, "solid_fill"))) { return true; } return this._getScopedValue(scope, ["color_mode"]) !== void 0 || this._getScopedValue(scope, ["color"]) !== void 0; } _getScopedNeedleConfig(scope) { var _a; const rawNeedle = this._getScopedValue(scope, ["bar", "needle"]); const defaultColor = "#ffffff"; let mode = (scope == null ? void 0 : scope.type) === "entity" ? "inherit" : "disabled"; let color = ""; if (typeof rawNeedle === "boolean") { mode = rawNeedle ? "enabled" : "disabled"; } else if (this._isObject(rawNeedle)) { if (rawNeedle.show === true) { mode = "enabled"; } else if (rawNeedle.show === false) { mode = "disabled"; } else if ((scope == null ? void 0 : scope.type) !== "entity") { mode = "disabled"; } color = (_a = rawNeedle.color) != null ? _a : ""; } if (color === defaultColor) { color = ""; } return { mode, color }; } _hasNeedleOverride(scope) { return this._getScopedValue(scope, ["bar", "needle"]) !== void 0; } _getEffectiveScopedNeedleConfig(scope) { const localNeedle = this._getScopedNeedleConfig(scope); if ((scope == null ? void 0 : scope.type) !== "entity") { return localNeedle; } if (!this._hasNeedleOverride(scope)) { return this._getScopedNeedleConfig({ type: "card" }); } const inheritedNeedle = this._getScopedNeedleConfig({ type: "card" }); return { mode: localNeedle.mode === "inherit" ? inheritedNeedle.mode : localNeedle.mode, color: localNeedle.color || inheritedNeedle.color }; } _setScopedNeedleMode(scope, mode) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const existingNeedle = this._getPathValue(nextTarget, ["bar", "needle"]); const existingColor = this._isObject(existingNeedle) ? existingNeedle.color : void 0; nextTarget = this._deletePathValue(nextTarget, ["bar", "needle"]); if ((scope == null ? void 0 : scope.type) === "entity" && mode === "inherit") { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; } if (mode === "disabled") { if ((scope == null ? void 0 : scope.type) === "entity") { nextTarget = this._setPathValue(nextTarget, ["bar", "needle"], { show: false }); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; } const nextNeedle = { show: true }; if (existingColor && existingColor !== "#ffffff") { nextNeedle.color = existingColor; } nextTarget = this._setPathValue(nextTarget, ["bar", "needle"], nextNeedle); const baselineEnabled = this._getPathValue(nextTarget, ["baseline", "enabled"]); const baselineParts = this._getResolvablePartsFromTarget(nextTarget != null ? nextTarget : {}, "baseline", { canonicalBasePath: ["baseline", "at"], legacyFixedPath: ["baseline"], legacyEntityPath: ["baseline", "at", "entity"] }); const baselineActive = baselineEnabled === true || baselineEnabled !== false && this._hasResolvableOverride(baselineParts); if (baselineActive) { nextTarget = this._deletePathValue(nextTarget, ["baseline"]); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }); } _setScopedNeedleColor(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const current = this._getScopedNeedleConfig(scope); const hasCustomColor = normalizedValue && this._normalizeColorComparisonValue(normalizedValue) !== this._normalizeColorComparisonValue("#ffffff"); nextTarget = this._deletePathValue(nextTarget, ["bar", "needle", "color"]); if ((scope == null ? void 0 : scope.type) !== "entity" && current.mode === "disabled") { nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar", "needle"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; } const showValue = current.mode === "enabled" ? true : current.mode === "disabled" ? false : void 0; const nextNeedle = {}; if (showValue !== void 0) { nextNeedle.show = showValue; } if (hasCustomColor) { nextNeedle.color = normalizedValue; } if (Object.keys(nextNeedle).length) { nextTarget = this._setPathValue(nextTarget, ["bar", "needle"], nextNeedle); } else { nextTarget = this._deletePathValue(nextTarget, ["bar", "needle"]); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar", "needle"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }); } _getNeedleValue() { return this._getScopedNeedleConfig({ type: "card" }).mode === "enabled"; } _getPeakShowValue() { return this._getScopedPeakConfig({ type: "card" }).mode === "enabled"; } _getScaleFixedValue(key, fallbackKey) { return this._getResolvableScopedValue({ type: "card" }, key).fixed; } _getScaleEntityValue(key) { return this._getResolvableScopedValue({ type: "card" }, key).entity; } _getTargetResolvableValue(scope) { return this._getResolvableScopedValue(scope, "target", { canonicalBasePath: ["target", "at"], legacyFixedPath: ["target"], legacyEntityPath: ["target_entity"] }); } _getEffectiveTargetResolvableValue(scope) { return this._getEffectiveResolvableScopedValue(scope, "target", { canonicalBasePath: ["target", "at"], legacyFixedPath: ["target"], legacyEntityPath: ["target_entity"] }); } _getTargetMode(scope) { const enabled = this._getScopedValue(scope, ["target", "enabled"]); if ((scope == null ? void 0 : scope.type) === "entity") { if (enabled === false) return "disabled"; if (enabled === true || this._hasTargetOverride(scope)) return "enabled"; return "inherit"; } if (enabled === true) return "enabled"; if (enabled === false) return "disabled"; return "auto"; } _getEffectiveTargetMode(scope) { const mode = this._getTargetMode(scope); if ((scope == null ? void 0 : scope.type) !== "entity" || mode !== "inherit") { return mode; } const cardMode = this._getTargetMode({ type: "card" }); if (cardMode === "disabled") return "disabled"; if (cardMode === "enabled") return "enabled"; const cardTarget = this._getTargetResolvableValue({ type: "card" }); return this._hasResolvableOverride(cardTarget) || this._hasCustomTargetColor({ type: "card" }) || this._getTargetLabelShowValue({ type: "card" }) || !!this._getTargetAboveFillColorValue({ type: "card" }) ? "enabled" : "disabled"; } _setTargetMode(scope, mode) { if ((scope == null ? void 0 : scope.type) === "entity" && mode === "inherit") { return this._clearTargetOverride(scope); } if (mode === "auto") { return this._removeCanonicalScopedValue(scope, ["target", "enabled"], { prunePaths: [["target"]] }); } return this._setCanonicalScopedValue(scope, ["target", "enabled"], mode === "enabled", { prunePaths: [["target"]] }); } _setTargetResolvablePart(scope, part, rawValue) { return this._setCanonicalResolvablePart(scope, "target", part, rawValue, { canonicalBasePath: ["target", "at"], legacyFixedPath: ["target"], legacyEntityPath: ["target_entity"], prunePaths: [["target", "at"], ["target"]] }); } _clearTargetOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const rawTarget = this._getPathValue(nextTarget, ["target"]); if (this._isObject(rawTarget)) { nextTarget = this._deletePathValue(nextTarget, ["target", "enabled"]); nextTarget = this._deletePathValue(nextTarget, ["target", "at"]); nextTarget = this._deletePathValue(nextTarget, ["target", "color"]); nextTarget = this._deletePathValue(nextTarget, ["target", "label", "show"]); nextTarget = this._deletePathValue(nextTarget, ["target", "when_exceeded", "fill_color"]); } else { nextTarget = this._deletePathValue(nextTarget, ["target"]); } nextTarget = this._deletePathValue(nextTarget, ["target_entity"]); nextTarget = this._deletePathValue(nextTarget, ["target_color"]); nextTarget = this._deletePathValue(nextTarget, ["show_target_label"]); nextTarget = this._deletePathValue(nextTarget, ["above_target_color"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["target", "label"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["target", "when_exceeded"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["target"]); return nextTarget; }, { rerender: true }); } _getTargetColorValue(scope) { var _a, _b; return (_b = (_a = this._getScopedValue(scope, ["target", "color"])) != null ? _a : this._getScopedValue(scope, ["target_color"])) != null ? _b : ""; } _getEffectiveTargetColorValue(scope) { return this._getEffectiveScopedDisplayValue(scope, ["target", "color"], [["target_color"]]); } _hasCustomTargetColor(scope) { const color = this._getTargetColorValue(scope); return !!color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#888"); } _setTargetColor(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue || this._normalizeColorComparisonValue(normalizedValue) === this._normalizeColorComparisonValue("#888")) { return this._removeCanonicalScopedValue(scope, ["target", "color"], { deprecatedKeys: [["target_color"]], prunePaths: [["target"]] }); } return this._setCanonicalScopedTextOverride(scope, ["target", "color"], normalizedValue, { deprecatedKeys: [["target_color"]], prunePaths: [["target"]] }); } _getTargetLabelShowValue(scope) { const structuredValue = this._getScopedValue(scope, ["target", "label", "show"]); if (structuredValue !== void 0) { return !!structuredValue; } return !!this._getScopedValue(scope, ["show_target_label"]); } _getEffectiveTargetLabelShowValue(scope) { const structuredValue = this._getScopedValue(scope, ["target", "label", "show"]); if (structuredValue !== void 0) { return !!structuredValue; } const legacyValue = this._getScopedValue(scope, ["show_target_label"]); if (legacyValue !== void 0) { return !!legacyValue; } if ((scope == null ? void 0 : scope.type) === "entity") { return this._getTargetLabelShowValue({ type: "card" }); } return false; } _setTargetLabelShow(scope, value) { if (!value) { return this._removeCanonicalScopedValue(scope, ["target", "label", "show"], { deprecatedKeys: [["show_target_label"]], prunePaths: [["target", "label"], ["target"]] }); } return this._setCanonicalScopedValue(scope, ["target", "label", "show"], true, { deprecatedKeys: [["show_target_label"]], prunePaths: [["target", "label"], ["target"]] }); } _getTargetAboveFillColorValue(scope) { var _a, _b; return (_b = (_a = this._getScopedValue(scope, ["target", "when_exceeded", "fill_color"])) != null ? _a : this._getScopedValue(scope, ["above_target_color"])) != null ? _b : ""; } _getTargetAboveFillDraftKey(scope = { type: "card" }) { return (scope == null ? void 0 : scope.type) === "entity" ? `entity:${scope.index}` : "card"; } _setTargetAboveFillDraft(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); const key = this._getTargetAboveFillDraftKey(scope); if (normalizedValue) { this._targetAboveFillDrafts.set(key, normalizedValue); } else { this._targetAboveFillDrafts.delete(key); } } _getTargetAboveFillDraft(scope) { var _a; return (_a = this._targetAboveFillDrafts.get(this._getTargetAboveFillDraftKey(scope))) != null ? _a : ""; } _getBaselineColorDraftKey(scope = { type: "card" }, direction = "above") { const scopeKey = (scope == null ? void 0 : scope.type) === "entity" ? `entity:${scope.index}` : "card"; return `${scopeKey}:${direction}`; } _setBaselineColorDraft(scope, direction, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); const key = this._getBaselineColorDraftKey(scope, direction); if (normalizedValue) { this._baselineColorDrafts.set(key, normalizedValue); } else { this._baselineColorDrafts.delete(key); } } _getBaselineColorDraft(scope, direction) { var _a; return (_a = this._baselineColorDrafts.get(this._getBaselineColorDraftKey(scope, direction))) != null ? _a : ""; } _getEffectiveTargetAboveFillColorValue(scope) { return this._getEffectiveScopedDisplayValue(scope, ["target", "when_exceeded", "fill_color"], [["above_target_color"]]); } _setTargetAboveFillColor(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); this._setTargetAboveFillDraft(scope, normalizedValue); if (!this._isTargetAboveFillEnabled(scope)) { return false; } if (!normalizedValue) { return this._removeCanonicalScopedValue(scope, ["target", "when_exceeded", "fill_color"], { deprecatedKeys: [["above_target_color"]], prunePaths: [["target", "when_exceeded"], ["target"]] }); } return this._setCanonicalScopedTextOverride(scope, ["target", "when_exceeded", "fill_color"], normalizedValue, { deprecatedKeys: [["above_target_color"]], prunePaths: [["target", "when_exceeded"], ["target"]] }); } _isTargetAboveFillEnabled(scope) { return !!this._normalizeTextValue(this._getTargetAboveFillColorValue(scope)).trim(); } _setTargetAboveFillEnabled(scope, value) { const currentValue = this._normalizeTextValue(this._getTargetAboveFillColorValue(scope)).trim(); if (!value) { if (currentValue) { this._setTargetAboveFillDraft(scope, currentValue); } return this._removeCanonicalScopedValue(scope, ["target", "when_exceeded", "fill_color"], { deprecatedKeys: [["above_target_color"]], prunePaths: [["target", "when_exceeded"], ["target"]] }); } const nextValue = this._getTargetAboveFillDraft(scope) || this._normalizeTextValue(this._getEffectiveTargetAboveFillColorValue(scope)).trim() || currentValue || "#000000"; return this._setCanonicalScopedTextOverride(scope, ["target", "when_exceeded", "fill_color"], nextValue, { deprecatedKeys: [["above_target_color"]], prunePaths: [["target", "when_exceeded"], ["target"]] }); } _isBaselineDirectionalColorEnabled(scope, direction) { return !!this._normalizeTextValue(this._getBaselineDirectionalColorValue(scope, direction)).trim(); } _setBaselineDirectionalColorEnabled(scope, direction, value) { const currentValue = this._normalizeTextValue(this._getBaselineDirectionalColorValue(scope, direction)).trim(); if (!value) { if (currentValue) { this._setBaselineColorDraft(scope, direction, currentValue); } return this._removeCanonicalScopedValue(scope, ["baseline", direction, "color"], { prunePaths: [["baseline", direction], ["baseline"]] }); } const nextValue = this._getBaselineColorDraft(scope, direction) || this._normalizeTextValue(this._getEffectiveBaselineDirectionalColorValue(scope, direction)).trim() || currentValue || "#000000"; return this._setCanonicalScopedTextOverride(scope, ["baseline", direction, "color"], nextValue, { prunePaths: [["baseline", direction], ["baseline"]] }); } _hasTargetOverride(scope) { const targetValue = this._getScopedValue(scope, ["target"]); if (this._isObject(targetValue) && Object.keys(targetValue).length) { return true; } if (!this._isObject(targetValue) && targetValue !== void 0 && targetValue !== null && targetValue !== "") { return true; } return ["target_entity", "target_color", "show_target_label", "above_target_color"].some((key) => { const value = this._getScopedValue(scope, [key]); return value !== void 0 && value !== null && value !== "" && value !== false; }); } _getBaselineResolvableValue(scope) { return this._getResolvableScopedValue(scope, "baseline", { canonicalBasePath: ["baseline", "at"], legacyFixedPath: ["baseline"], legacyEntityPath: ["baseline", "at", "entity"] }); } _getEffectiveBaselineResolvableValue(scope) { return this._getEffectiveResolvableScopedValue(scope, "baseline", { canonicalBasePath: ["baseline", "at"], legacyFixedPath: ["baseline"], legacyEntityPath: ["baseline", "at", "entity"] }); } _getBaselineMode(scope) { const enabled = this._getScopedValue(scope, ["baseline", "enabled"]); if ((scope == null ? void 0 : scope.type) === "entity") { if (enabled === false) return "disabled"; if (enabled === true || this._hasBaselineOverride(scope)) return "enabled"; return "inherit"; } if (enabled === true) return "enabled"; if (enabled === false) return "disabled"; return "auto"; } _getEffectiveBaselineMode(scope) { const mode = this._getBaselineMode(scope); if ((scope == null ? void 0 : scope.type) !== "entity" || mode !== "inherit") { return mode; } const cardMode = this._getBaselineMode({ type: "card" }); if (cardMode === "disabled") return "disabled"; if (cardMode === "enabled") return "enabled"; const cardBaseline = this._getBaselineResolvableValue({ type: "card" }); return this._hasResolvableOverride(cardBaseline) || !!this._getBaselineDirectionalColorValue({ type: "card" }, "above") || !!this._getBaselineDirectionalColorValue({ type: "card" }, "below") ? "enabled" : "disabled"; } _setBaselineMode(scope, mode) { if ((scope == null ? void 0 : scope.type) === "entity" && mode === "inherit") { return this._clearBaselineOverride(scope); } return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); if (mode === "auto") { nextTarget = this._deletePathValue(nextTarget, ["baseline", "enabled"]); } else { nextTarget = this._setPathValue(nextTarget, ["baseline", "enabled"], mode === "enabled"); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline"]); return nextTarget; }); } _setBaselineResolvablePart(scope, part, rawValue) { const normalizedValue = part === "fixed" ? this._normalizeNumberValue(rawValue) : this._normalizeTextValue(rawValue).trim(); return this._applyScopedMutation(scope, (target) => { const currentParts = this._getResolvablePartsFromTarget(target != null ? target : {}, "baseline", { canonicalBasePath: ["baseline", "at"], legacyFixedPath: ["baseline"], legacyEntityPath: ["baseline", "at", "entity"] }); const nextParts = { ...currentParts }; if (part === "fixed") { if (rawValue === "" || rawValue === null || rawValue === void 0 || normalizedValue === null) { delete nextParts.fixed; } else { nextParts.fixed = normalizedValue; } } else if (!normalizedValue) { delete nextParts.entity; } else { nextParts.entity = normalizedValue; } let nextTarget = this._cloneDeep(target); nextTarget = this._deletePathValue(nextTarget, ["baseline", "at"]); const hasFixed = nextParts.fixed !== void 0 && nextParts.fixed !== null && nextParts.fixed !== ""; const hasEntity = nextParts.entity !== void 0 && nextParts.entity !== null && nextParts.entity !== ""; if (hasFixed || hasEntity) { const nextValue = {}; if (hasFixed) nextValue.fixed = nextParts.fixed; if (hasEntity) nextValue.entity = nextParts.entity; nextTarget = this._setPathValue(nextTarget, ["baseline", "at"], nextValue); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline", "at"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline"]); return nextTarget; }); } _removeScopedNeedle(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._deletePathValue(target, ["bar", "needle"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["bar"]); return nextTarget; }); } _setBaselineDirectionalColor(scope, direction, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); this._setBaselineColorDraft(scope, direction, normalizedValue); const path = ["baseline", direction, "color"]; if (!normalizedValue) { return this._removeCanonicalScopedValue(scope, path, { prunePaths: [["baseline", direction], ["baseline"]] }); } if (!this._isBaselineDirectionalColorEnabled(scope, direction)) { return this._setBaselineDirectionalColorEnabled(scope, direction, true); } return this._applyScopedMutation(scope, (target) => { return this._setPathValue(target, path, normalizedValue); }); } _getBaselineDirectionalColorValue(scope, direction) { var _a; return (_a = this._getScopedValue(scope, ["baseline", direction, "color"])) != null ? _a : ""; } _getEffectiveBaselineDirectionalColorValue(scope, direction) { return this._getEffectiveScopedDisplayValue(scope, ["baseline", direction, "color"]); } _clearBaselineOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const rawBaseline = this._getPathValue(nextTarget, ["baseline"]); if (this._isObject(rawBaseline)) { nextTarget = this._deletePathValue(nextTarget, ["baseline", "enabled"]); nextTarget = this._deletePathValue(nextTarget, ["baseline", "at"]); nextTarget = this._deletePathValue(nextTarget, ["baseline", "above", "color"]); nextTarget = this._deletePathValue(nextTarget, ["baseline", "below", "color"]); } else { nextTarget = this._deletePathValue(nextTarget, ["baseline"]); } nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline", "above"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline", "below"]); nextTarget = this._pruneEmptyObjectsInTarget(nextTarget, ["baseline"]); return nextTarget; }, { rerender: true }); } _hasBaselineOverride(scope) { const baselineValue = this._getScopedValue(scope, ["baseline"]); if (this._isObject(baselineValue) && Object.keys(baselineValue).length) { return true; } return !this._isObject(baselineValue) && baselineValue !== void 0 && baselineValue !== null && baselineValue !== ""; } _isEntityOverrideExpanded(index) { return this._expandedEntityOverrides.has(index); } _toggleEntityOverrideExpanded(index) { if (this._expandedEntityOverrides.has(index)) { this._expandedEntityOverrides.delete(index); } else { this._expandedEntityOverrides.add(index); } this._render(); } _syncExpandedEntityOverrides(entityCount) { const nextExpanded = /* @__PURE__ */ new Set(); this._expandedEntityOverrides.forEach((index) => { if (index < entityCount) nextExpanded.add(index); }); this._expandedEntityOverrides = nextExpanded; const nextGroups = /* @__PURE__ */ new Set(); this._expandedOverrideGroups.forEach((key) => { const [indexText, group] = String(key).split(":"); const index = Number(indexText); if (Number.isInteger(index) && index < entityCount && group) { nextGroups.add(`${index}:${group}`); } }); this._expandedOverrideGroups = nextGroups; } _isCardGroupExpanded(group) { return this._expandedCardGroups.has(group); } _toggleCardGroupExpanded(group) { if (this._expandedCardGroups.has(group)) { this._expandedCardGroups.delete(group); } else { this._expandedCardGroups.add(group); } this._render(); } _getOverrideGroupKey(index, group) { return `${index}:${group}`; } _isOverrideGroupExpanded(index, group) { return this._expandedOverrideGroups.has(this._getOverrideGroupKey(index, group)); } _toggleOverrideGroupExpanded(index, group) { const key = this._getOverrideGroupKey(index, group); if (this._expandedOverrideGroups.has(key)) { this._expandedOverrideGroups.delete(key); } else { this._expandedOverrideGroups.add(key); } this._render(); } _hasExplicitOverrideValue(value) { return value !== "" && value !== void 0 && value !== null; } _hasResolvableOverride(parts) { return this._hasExplicitOverrideValue(parts == null ? void 0 : parts.fixed) || this._hasExplicitOverrideValue(parts == null ? void 0 : parts.entity); } _getScaleOverrideSummary(scope) { const parts = []; const min = this._getResolvableScopedValue(scope, "min"); const max = this._getResolvableScopedValue(scope, "max"); if (min.entity) parts.push("Min entity"); else if (min.fixed !== "" && min.fixed !== void 0) parts.push(`Min ${min.fixed}`); if (max.entity) parts.push("Max entity"); else if (max.fixed !== "" && max.fixed !== void 0) parts.push(`Max ${max.fixed}`); return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _getLayoutSummary(scope) { const parts = []; const height = this._getScopedLayoutValue(scope, "height"); const position = this._getScopedLayoutValue(scope, "position"); const width = this._getScopedLayoutValue(scope, "width"); if (height !== "") parts.push(`Height ${height}`); if (position !== "") parts.push(`${position}`); if (width !== "") parts.push(`Width ${width}`); return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _getTargetOverrideSummary(scope) { const mode = this._getTargetMode(scope); if (mode === "disabled") return "Disabled"; const parts = []; const target = this._getTargetResolvableValue(scope); if (target.fixed !== "" && target.fixed !== void 0) parts.push(`Target ${target.fixed}`); if (target.entity) parts.push("Entity"); if (this._hasCustomTargetColor(scope)) parts.push("Custom color"); if (this._getTargetLabelShowValue(scope)) parts.push("Label"); if (this._getTargetAboveFillColorValue(scope)) parts.push("Above"); return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _getBaselineOverrideSummary(scope) { const mode = this._getBaselineMode(scope); if (mode === "disabled") return "Disabled"; const parts = []; const baseline = this._getBaselineResolvableValue(scope); if (baseline.fixed !== "" && baseline.fixed !== void 0) parts.push(`Baseline ${baseline.fixed}`); if (baseline.entity) parts.push("Entity"); if (this._getBaselineDirectionalColorValue(scope, "above")) parts.push("Above"); if (this._getBaselineDirectionalColorValue(scope, "below")) parts.push("Below"); return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _getBarAppearanceSummary(scope) { var _a; const parts = []; const fillStyle = this._getScopedFillStyleValue(scope); const color = (_a = this._getScopedValue(scope, ["bar", "color"])) != null ? _a : this._getScopedValue(scope, ["color"]); if (fillStyle && fillStyle !== "bands") parts.push(fillStyle.replace(/_/g, " ")); if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#4a9eff")) { parts.push("Custom color"); } return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _getScopedSegmentsValue(scope) { const uiRows = this._getSegmentsUiRows(scope); if (uiRows !== null) { return this._cloneDeep(uiRows); } const storedSegments = this._getStoredScopedSegments(scope); if (storedSegments !== null) { return this._sortSegmentsForEditor(storedSegments); } return this._sortSegmentsForEditor(this._getFallbackSegments(scope)); } _hasSegmentsOverride(scope) { return this._getStoredScopedSegments(scope) !== null; } _getSegmentsSummary(scope) { const segments = this._getScopedSegmentsValue(scope); if (!Array.isArray(segments) || segments.length === 0) { return "Inherited"; } if ((scope == null ? void 0 : scope.type) !== "entity" && !this._hasSegmentsOverride(scope) && this._isSegmentFillStyle(this._getEffectiveFillStyleValue(scope))) { return "Default bands"; } return `${segments.length} segments`; } _getEffectiveFillStyleValue(scope) { if ((scope == null ? void 0 : scope.type) === "entity") { const hasEntityFillStyle = this._getScopedValue(scope, ["bar", "fill_style"]) !== void 0 || this._getScopedValue(scope, ["bar", "color_mode"]) !== void 0 || this._getScopedValue(scope, ["color_mode"]) !== void 0; if (hasEntityFillStyle) { return this._getScopedFillStyleValue(scope); } return this._getFillStyleValue(); } return this._getScopedFillStyleValue(scope); } _getScopedGradientStopsValue(scope) { const localRows = this._getGradientStopsUiRows(scope); if (Array.isArray(localRows)) { return localRows; } const storedStops = this._getStoredScopedGradientStops(scope); if (storedStops !== null) { return this._sanitizeGradientStopsForEmit(storedStops); } return this._cloneDeep(this._getFallbackGradientStops(scope)); } _hasGradientStopsOverride(scope) { if (this._getStoredScopedGradientStops(scope) !== null) { return true; } const localRows = this._getGradientStopsUiRows(scope); if (!Array.isArray(localRows)) { return false; } return this._serializeConfig(this._sanitizeGradientStopsForEmit(localRows)) !== this._serializeConfig(this._sanitizeGradientStopsForEmit(this._getFallbackGradientStops(scope))); } _getGradientStopsSummary(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasGradientStopsOverride(scope)) { return "Inherited"; } const gradientStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); if (this._getEffectiveFillStyleValue(scope) !== "gradient") { return "Inactive fill style"; } if (!gradientStops.length) { return (scope == null ? void 0 : scope.type) === "entity" ? "Inherited" : "Default gradient"; } if (this._isDefaultGradientStops(gradientStops)) { return "Default gradient"; } return `${gradientStops.length} stops`; } _buildGradientPreviewEffectiveStops(scope = { type: "card" }) { const committedStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); const draftStop = this._getValidGradientDraftStop(scope); const previewStops = [...committedStops]; if (draftStop && !this._hasGradientStopDuplicate(scope, draftStop.pos)) { previewStops.push(draftStop); } return previewStops.sort((left, right) => left.pos - right.pos); } _buildEditorGradientPreviewStyle(stops) { if (!Array.isArray(stops) || !stops.length) { return ""; } const cssStops = stops.map((stop) => { var _a; const color = this._normalizeTextValue(stop.color).trim(); const pos = this._normalizeGradientStopPosValue((_a = stop.p) != null ? _a : stop.pos); if (!color || pos === null) { return null; } return `${color} ${pos}%`; }).filter(Boolean); if (!cssStops.length) { return ""; } return `background:linear-gradient(to right,${cssStops.join(",")});background-repeat:no-repeat;`; } _getGradientPreviewStyle(scope = { type: "card" }) { const previewStops = this._buildGradientPreviewEffectiveStops(scope); const resolvedStops = previewStops.length >= 2 ? previewStops.map((stop) => ({ p: stop.pos, color: stop.color })) : this._getDefaultGradientStops().map((stop) => ({ p: stop.pos, color: stop.color })); return this._buildEditorGradientPreviewStyle(resolvedStops); } _renderGradientPreview(scope = { type: "card" }, options = {}) { var _a, _b, _c; const previewId = (_a = options.previewId) != null ? _a : "gradient-preview"; const trackId = (_b = options.trackId) != null ? _b : `${previewId}-track`; const effectiveStops = this._buildGradientPreviewEffectiveStops(scope); const markerStops = effectiveStops.length ? effectiveStops : this._getDefaultGradientStops(); return `
${markerStops.map((stop, index) => ` `).join("")}
`; } _getNeedleSummary(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasNeedleOverride(scope)) return "Inherited"; const needle = this._getScopedNeedleConfig(scope); if (needle.mode === "disabled") return needle.color ? "Disabled \u2022 Custom color" : "Disabled"; if (needle.mode === "enabled") return needle.color ? "Enabled \u2022 Custom color" : "Enabled"; if (needle.color) return "Custom color"; return "Inherited"; } _getFormattingSummary(scope) { const parts = []; const unit = this._getScopedFormattingValue(scope, "unit"); const decimal = this._getScopedFormattingValue(scope, "decimal"); if (unit !== "") parts.push(`Unit ${unit}`); if (decimal !== "") parts.push(`${decimal} ${Number(decimal) === 1 ? "decimal" : "decimals"}`); return parts.length ? parts.join(" \u2022 ") : "Inherited"; } _renderOverrideGroup({ index, group, title, summary, content }) { const expanded = this._isOverrideGroupExpanded(index, group); return `
${content}
`; } _renderCardGroup({ group, title, summary, content, inactive = false }) { const expanded = this._isCardGroupExpanded(group); return `
${content}
`; } _renderEntityInput(entry, index) { if (customElements.get("ha-entity-picker")) { return ``; } return ``; } _renderEntitySourceInput(kind, index, value, placeholder = "sensor.example") { if (customElements.get("ha-entity-picker")) { return ``; } return ``; } _escapeAttribute(value) { return this._normalizeTextValue(value).replace(/&/g, "&").replace(/"/g, """).replace(//g, ">"); } _isHexColorValue(value) { return typeof value === "string" && /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value.trim()); } _expandHexColor(value) { if (!this._isHexColorValue(value)) { return null; } const normalized = value.trim().toLowerCase(); if (normalized.length === 7) { return normalized; } return `#${normalized.slice(1).split("").map((char) => char + char).join("")}`; } _normalizeColorComparisonValue(value) { var _a; const normalizedText = this._normalizeTextValue(value).trim().toLowerCase(); if (!normalizedText) { return ""; } return (_a = this._expandHexColor(normalizedText)) != null ? _a : normalizedText; } _getColorPickerValue(value, fallbackHex = "#000000") { var _a, _b; return (_b = (_a = this._expandHexColor(value)) != null ? _a : this._expandHexColor(fallbackHex)) != null ? _b : "#000000"; } _renderColorInput({ id, field = null, kind = null, index = null, value = "", fallbackHex = "#000000", placeholder = "", extraDataset = {} }) { const controlValue = this._normalizeTextValue(value).trim(); const pickerValue = this._getColorPickerValue(controlValue, fallbackHex); const extraAttrs = Object.entries(extraDataset).map(([key, entry]) => `data-${key}="${this._escapeAttribute(entry)}"`).join(" "); const baseAttrs = field ? `data-field="${field}"${extraAttrs ? ` ${extraAttrs}` : ""}` : `data-kind="${kind}" data-index="${index}"${extraAttrs ? ` ${extraAttrs}` : ""}`; const fallbackAttrs = field ? `data-field="${field}-text-fallback"${extraAttrs ? ` ${extraAttrs}` : ""}` : `data-kind="${kind}-text-fallback" data-index="${index}"${extraAttrs ? ` ${extraAttrs}` : ""}`; return `
${controlValue && !this._isHexColorValue(controlValue) ? `` : ""}
`; } _renderListRows(items, renderItem) { return items.map((item, index) => renderItem(item, index)).join(""); } _render() { var _a; if (!this.shadowRoot || this._isRendering) return; this._isRendering = true; try { const entities = this._getEntitiesValue(); const fillStyle = this._getFillStyleValue(); const layoutLabelPosition = this._getScopedLayoutValue({ type: "card" }, "position") || "left"; const layoutHeroSize = this._getScopedLayoutValue({ type: "card" }, "hero_size") || "medium"; const layoutHeroValueSize = this._getScopedLayoutValue({ type: "card" }, "value_size"); const layoutHeight = this._getScopedLayoutValue({ type: "card" }, "height"); const layoutLabelWidth = this._getScopedLayoutValue({ type: "card" }, "width"); const barColor = this._getScopedBarColorValue({ type: "card" }); const barSolidFill = this._getScopedBarSolidFillValue({ type: "card" }); const cardNeedle = this._getScopedNeedleConfig({ type: "card" }); const gradientStops = this._getGradientStopsValue(); const gradientDraft = this._getGradientStopsDraftState({ type: "card" }); const gradientDraftMessage = this._getGradientDraftValidationMessage({ type: "card" }); const segments = this._getSegmentsValue(); const baseline = this._getBaselineResolvableValue({ type: "card" }); const baselineMode = this._getBaselineMode({ type: "card" }); const baselineAboveColor = this._getBaselineDirectionalColorValue({ type: "card" }, "above"); const baselineBelowColor = this._getBaselineDirectionalColorValue({ type: "card" }, "below"); const target = this._getTargetResolvableValue({ type: "card" }); const targetMode = this._getTargetMode({ type: "card" }); const targetColor = this._getTargetColorValue({ type: "card" }); const targetLabelShow = this._getTargetLabelShowValue({ type: "card" }); const targetAboveFillColor = this._getTargetAboveFillColorValue({ type: "card" }); const formattingUnit = this._getScopedFormattingValue({ type: "card" }, "unit"); const formattingDecimal = this._getScopedFormattingValue({ type: "card" }, "decimal"); const cardPeak = this._getScopedPeakConfig({ type: "card" }); const scaleMin = this._getScaleFixedValue("min", "min"); const scaleMax = this._getScaleFixedValue("max", "max"); const scaleMinEntity = this._getScaleEntityValue("min"); const scaleMaxEntity = this._getScaleEntityValue("max"); const gradientStopsSummary = this._getGradientStopsSummary({ type: "card" }); const gradientStopsInactive = this._getEffectiveFillStyleValue({ type: "card" }) !== "gradient"; const defaultSegmentsVisible = !this._hasSegmentsOverride({ type: "card" }) && this._isSegmentFillStyle(this._getEffectiveFillStyleValue({ type: "card" })); this._syncExpandedEntityOverrides(entities.length); this.shadowRoot.innerHTML = `

Basics

Entities

Overrides replace card defaults only for this entity.
${this._renderListRows(entities, (entry, index) => { var _a2, _b; return `
Entity ${index + 1}
${this._escapeAttribute(entry.entity || "Configure entity")}
${this._renderEntityInput(entry, index)}
Overrides replace card defaults only for this entity.
${(() => { const scope = { type: "entity", index }; const minParts = this._getEffectiveResolvableScopedValue(scope, "min"); const maxParts = this._getEffectiveResolvableScopedValue(scope, "max"); const barAppearanceInherited = !this._hasEntityBarAppearanceOverride(scope); const needleInherited = !this._hasNeedleOverride(scope); const entityNeedle = this._getEffectiveScopedNeedleConfig(scope); const baselineInherited = !this._hasBaselineOverride(scope); const baselineParts = this._getEffectiveBaselineResolvableValue(scope); const baselineMode2 = this._getEffectiveBaselineMode(scope); const targetInherited = !this._hasTargetOverride(scope); const targetParts = this._getEffectiveTargetResolvableValue(scope); const targetMode2 = this._getEffectiveTargetMode(scope); const formattingInherited = !this._hasFormattingOverride(scope); const layoutInherited = !this._hasLayoutOverride(scope); const peakInherited = !this._hasPeakOverride(scope); const gradientStopsInherited = !this._hasGradientStopsOverride(scope); const segmentsInherited = !this._hasSegmentsOverride(scope); const scaleInherited = !this._hasResolvableOverride(this._getResolvableScopedValue(scope, "min")) && !this._hasResolvableOverride(this._getResolvableScopedValue(scope, "max")); const entityPeak = this._getEffectiveScopedPeakConfig(scope); const entityGradientStops = this._getScopedGradientStopsValue(scope); const entityGradientDraft = this._getGradientStopsDraftState(scope); const entityGradientDraftMessage = this._getGradientDraftValidationMessage(scope); const entitySegments = this._getScopedSegmentsValue(scope); const scaleGroup = this._renderOverrideGroup({ index, group: "scale", title: "Scale", summary: this._getScaleOverrideSummary(scope), content: `
Fixed values are used as fallback when entity values are unavailable.
${this._renderEntitySourceInput("entity-override-min-entity-source", index, minParts.entity, "inherit card default")}
${this._renderEntitySourceInput("entity-override-max-entity-source", index, maxParts.entity, "inherit card default")}
` }); const layoutGroup = this._renderOverrideGroup({ index, group: "layout", title: "Layout", summary: this._getLayoutSummary(scope), content: `
${(this._getEffectiveScopedLayoutValue(scope, "position") || "") === "hero" ? `
The hero value may render smaller when needed to fit. A custom value overrides the Hero size preset.
` : ""}
` }); const barGroup = this._renderOverrideGroup({ index, group: "bar", title: "Bar Appearance", summary: this._getBarAppearanceSummary(scope), content: `
${this._renderColorInput({ id: `entity-${index}-bar-color`, kind: "entity-bar-color", index, value: this._getEffectiveScopedBarColorValue(scope), fallbackHex: "#4a9eff", placeholder: "inherit card default" })}
` }); const needleGroup = this._renderOverrideGroup({ index, group: "needle", title: "Needle", summary: this._getNeedleSummary(scope), content: `
${this._renderColorInput({ id: `entity-${index}-needle-color`, kind: "entity-needle-color", index, value: entityNeedle.color, fallbackHex: "#ffffff", placeholder: "#ffffff" })}
` }); const formattingGroup = this._renderOverrideGroup({ index, group: "formatting", title: "Formatting", summary: this._getFormattingSummary(scope), content: `
` }); const peakGroup = this._renderOverrideGroup({ index, group: "peak", title: "Peak", summary: this._getPeakSummary(scope), content: `
${this._renderColorInput({ id: `entity-${index}-peak-color`, kind: "entity-peak-color", index, value: entityPeak.color, fallbackHex: "#888", placeholder: "inherit card default" })}
` }); const segmentsGroup = this._renderOverrideGroup({ index, group: "segments", title: "Segments", summary: this._getSegmentsSummary(scope), content: `
${this._isSegmentFillStyle(this._getEffectiveFillStyleValue(scope)) ? "" : '
Only used with segment-based fill styles.
'} ${this._renderSegmentPreview(scope)}
${this._renderListRows(entitySegments, (segment, segmentIndex) => { var _a3; return `
`; })}
` }); const gradientStopsGroup = this._renderOverrideGroup({ index, group: "gradient-stops", title: "Gradient Stops", summary: this._getGradientStopsSummary(scope), content: `
${this._getEffectiveFillStyleValue(scope) !== "gradient" ? '
Only used with Gradient fill style
' : ""} ${this._renderGradientPreview(scope, { previewId: `entity-${index}-gradient-preview`, trackId: `entity-${index}-gradient-preview-track` })}
${this._renderListRows(entityGradientStops, (stop, stopIndex) => { var _a3, _b2; return `
${this._renderColorInput({ id: `entity-${index}-gradient-color-${stopIndex}`, kind: "entity-gradient-color", index, value: (_b2 = stop == null ? void 0 : stop.color) != null ? _b2 : "#4a9eff", fallbackHex: "#4CAF50", placeholder: "CSS color value", extraDataset: { "stop-index": stopIndex } })}
`; })}
${this._renderColorInput({ id: `entity-${index}-gradient-draft-color`, kind: "entity-gradient-draft-color", index, value: entityGradientDraft.color, fallbackHex: "#4CAF50", placeholder: "CSS color value" })}
${entityGradientDraftMessage ? `
${this._escapeAttribute(entityGradientDraftMessage)}
` : ""}
` }); const baselineGroup = this._renderOverrideGroup({ index, group: "baseline", title: "Baseline", summary: this._getBaselineOverrideSummary(scope), content: `
${this._renderEntitySourceInput("entity-baseline-entity-source", index, baselineParts.entity, "inherit card default")}
${this._renderColorInput({ id: `entity-${index}-baseline-above-color`, kind: "entity-baseline-above-color", index, value: this._getEffectiveBaselineDirectionalColorValue(scope, "above"), fallbackHex: "#000000", placeholder: "inherit card default" })}
${this._renderColorInput({ id: `entity-${index}-baseline-below-color`, kind: "entity-baseline-below-color", index, value: this._getEffectiveBaselineDirectionalColorValue(scope, "below"), fallbackHex: "#000000", placeholder: "inherit card default" })}
` }); const targetGroup = this._renderOverrideGroup({ index, group: "target", title: "Target", summary: this._getTargetOverrideSummary(scope), content: `
${this._renderEntitySourceInput("entity-target-entity-source", index, targetParts.entity, "inherit card default")}
${this._renderColorInput({ id: `entity-${index}-target-color`, kind: "entity-target-color", index, value: this._getEffectiveTargetColorValue(scope), fallbackHex: "#888", placeholder: "inherit card default" })}
${this._renderColorInput({ id: `entity-${index}-target-above-fill`, kind: "entity-target-above-fill-color", index, value: this._getEffectiveTargetAboveFillColorValue(scope), fallbackHex: "#000000", placeholder: "inherit card default" })}
` }); return ` ${scaleGroup} ${targetGroup} ${baselineGroup} ${needleGroup} ${peakGroup} ${barGroup} ${segmentsGroup} ${gradientStopsGroup} ${layoutGroup} ${formattingGroup} `; })()}
`; })}

Scale

Entity values take precedence. Fixed values are used as fallback.
${this._renderEntitySourceInput("scale-min-entity-source", "card", scaleMinEntity)}
${this._renderEntitySourceInput("scale-max-entity-source", "card", scaleMaxEntity)}

Markers

Target, baseline, and peak markers help compare the current value against reference points.
${this._renderEntitySourceInput("target-entity-source", "card", target.entity)}
${this._renderColorInput({ id: "target-color", field: "target-color", value: targetColor, fallbackHex: "#888", placeholder: "#888" })}
${this._renderColorInput({ id: "target-above-fill-color", field: "target-above-fill-color", value: targetAboveFillColor, fallbackHex: "#000000" })}
Auto shows the baseline when a baseline value is configured.
${this._renderEntitySourceInput("baseline-entity-source", "card", baseline.entity)}
${this._renderColorInput({ id: "baseline-above-color", field: "baseline-above-color", value: baselineAboveColor, fallbackHex: "#000000" })}
${this._renderColorInput({ id: "baseline-below-color", field: "baseline-below-color", value: baselineBelowColor, fallbackHex: "#000000" })}
${this._renderColorInput({ id: "peak-color", field: "peak-color", value: cardPeak.color, fallbackHex: "#888", placeholder: "#888" })}

Bar Appearance

Choose the bar rendering mode and base bar colors.
${this._renderColorInput({ id: "bar-color", field: "bar-color", value: barColor, fallbackHex: "#4a9eff", placeholder: "#4a9eff" })}
${this._renderColorInput({ id: "bar-needle-color", field: "bar-needle-color", value: cardNeedle.color, fallbackHex: "#ffffff", placeholder: "#ffffff" })}

Segments

Segments define colored value ranges.
${this._renderCardGroup({ group: "segments", title: "Segments", summary: this._getSegmentsSummary({ type: "card" }), inactive: !this._isSegmentFillStyle(fillStyle), content: ` ${this._isSegmentFillStyle(fillStyle) ? "" : '
Only used with segment-based fill styles.
'} ${this._renderSegmentPreview({ type: "card" })}
${defaultSegmentsVisible ? '
Default bands
' : ""} ${this._renderListRows(segments, (segment, index) => { var _a2; return `
`; })}
` })}

Gradient Stops

Gradient stops define a smooth color transition from 0 to 100%.
${this._renderCardGroup({ group: "gradient-stops", title: "Gradient Stops", summary: gradientStopsSummary, inactive: gradientStopsInactive, content: ` ${gradientStopsInactive ? '
Only used with Gradient fill style
' : ""} ${this._renderGradientPreview({ type: "card" }, { previewId: "card-gradient-preview", trackId: "card-gradient-preview-track" })}
${this._renderListRows(gradientStops, (stop, index) => { var _a2, _b; return `
${this._renderColorInput({ id: `gradient-color-${index}`, kind: "gradient-color", index, value: (_b = stop == null ? void 0 : stop.color) != null ? _b : "#4a9eff", fallbackHex: "#4CAF50", placeholder: "CSS color value" })}
`; })}
${this._renderColorInput({ id: "gradient-draft-color", kind: "gradient-draft-color", index: "card", value: gradientDraft.color, fallbackHex: "#4CAF50", placeholder: "CSS color value" })}
${gradientDraftMessage ? `
${this._escapeAttribute(gradientDraftMessage)}
` : ""}
` })}

Layout

${layoutLabelPosition === "hero" ? `
The hero value may render smaller when needed to fit. A custom value overrides the Hero size preset.
` : ""}

Formatting

`; this._bindShadowListeners(); this._syncEntityPickers(); this._lastRenderedConfigJson = this._serializeConfig(this._draftConfig); this._applyPendingFocus(); } finally { this._isRendering = false; } } _bindShadowListeners() { if (!this.shadowRoot || this._shadowListenersAttached) return; this.shadowRoot.addEventListener("click", this._boundHandleClick); this.shadowRoot.addEventListener("change", this._boundHandleChange); this.shadowRoot.addEventListener("input", this._boundHandleInput); this.shadowRoot.addEventListener("value-changed", this._boundHandleValueChanged); this.shadowRoot.addEventListener("keydown", this._boundHandleKeydown); this._shadowListenersAttached = true; } _syncEntityPickers() { if (!this.shadowRoot) return; const entities = this._getEntitiesValue(); const syncPicker = (picker) => { var _a; const kind = picker.dataset.kind; const indexValue = picker.dataset.index; const index = Number(indexValue); picker.hass = this._hass; picker.allowCustomEntity = true; if (kind === "entity-picker") { const entry = entities[index]; picker.value = (_a = entry == null ? void 0 : entry.entity) != null ? _a : ""; picker.label = `Entity ${index + 1}`; return; } if (kind === "scale-min-entity-source") { picker.value = this._getScaleEntityValue("min"); picker.label = "Min entity"; return; } if (kind === "scale-max-entity-source") { picker.value = this._getScaleEntityValue("max"); picker.label = "Max entity"; return; } if (kind === "baseline-entity-source") { picker.value = this._getBaselineResolvableValue({ type: "card" }).entity; picker.label = "Baseline entity"; return; } if (kind === "target-entity-source") { picker.value = this._getTargetResolvableValue({ type: "card" }).entity; picker.label = "Target entity"; return; } if (kind === "entity-override-min-entity-source") { picker.value = this._getEffectiveResolvableScopedValue({ type: "entity", index }, "min").entity; picker.label = `Entity ${index + 1} min entity`; return; } if (kind === "entity-override-max-entity-source") { picker.value = this._getEffectiveResolvableScopedValue({ type: "entity", index }, "max").entity; picker.label = `Entity ${index + 1} max entity`; return; } if (kind === "entity-baseline-entity-source") { picker.value = this._getEffectiveBaselineResolvableValue({ type: "entity", index }).entity; picker.label = `Entity ${index + 1} baseline entity`; return; } if (kind === "entity-target-entity-source") { picker.value = this._getEffectiveTargetResolvableValue({ type: "entity", index }).entity; picker.label = `Entity ${index + 1} target entity`; } }; [ 'ha-entity-picker[data-kind="entity-picker"]', 'ha-entity-picker[data-kind="scale-min-entity-source"]', 'ha-entity-picker[data-kind="scale-max-entity-source"]', 'ha-entity-picker[data-kind="baseline-entity-source"]', 'ha-entity-picker[data-kind="target-entity-source"]', 'ha-entity-picker[data-kind="entity-override-min-entity-source"]', 'ha-entity-picker[data-kind="entity-override-max-entity-source"]', 'ha-entity-picker[data-kind="entity-baseline-entity-source"]', 'ha-entity-picker[data-kind="entity-target-entity-source"]' ].forEach((selector) => { this.shadowRoot.querySelectorAll(selector).forEach(syncPicker); }); if (customElements.whenDefined) { customElements.whenDefined("ha-entity-picker").then(() => { [ 'ha-entity-picker[data-kind="entity-picker"]', 'ha-entity-picker[data-kind="scale-min-entity-source"]', 'ha-entity-picker[data-kind="scale-max-entity-source"]', 'ha-entity-picker[data-kind="baseline-entity-source"]', 'ha-entity-picker[data-kind="target-entity-source"]', 'ha-entity-picker[data-kind="entity-override-min-entity-source"]', 'ha-entity-picker[data-kind="entity-override-max-entity-source"]', 'ha-entity-picker[data-kind="entity-baseline-entity-source"]', 'ha-entity-picker[data-kind="entity-target-entity-source"]' ].forEach((selector) => { var _a; (_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll(selector).forEach(syncPicker); }); }).catch(() => { }); } } _handleClick(event) { var _a, _b, _c, _d, _e, _f; const target = (_c = (_b = (_a = event.target) == null ? void 0 : _a.closest) == null ? void 0 : _b.call(_a, "[data-action]")) != null ? _c : event.target; const action = (_d = target == null ? void 0 : target.dataset) == null ? void 0 : _d.action; if (!action) return; if (target == null ? void 0 : target.disabled) return; if (action === "add-entity") { const nextEntities = [...this._getEntitiesValue(), { entity: "" }]; const nextEntries = this._buildEntityConfigEntries(nextEntities); this._queuePostRenderFocus(`[data-kind="entity-picker"][data-index="${nextEntities.length - 1}"], [data-kind="entity-input"][data-index="${nextEntities.length - 1}"]`); if (Array.isArray(this._draftConfig.entities) || nextEntries.length > 1 || !this._draftConfig.entity) { let nextConfig = this._setPathValue(this._draftConfig, ["entities"], nextEntries); if (!Array.isArray(this._draftConfig.entities) && this._draftConfig.entity !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["entity"]); if (this._draftConfig.name !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["name"]); } if (this._draftConfig.icon !== void 0) { nextConfig = this._deletePathValue(nextConfig, ["icon"]); } } this._applyUserConfig(nextConfig, { rerender: true }); } else { this._setValueAtPath(["entity"], (_f = (_e = nextEntities[0]) == null ? void 0 : _e.entity) != null ? _f : "", { rerender: true }); } return; } if (action === "move-entity-up") { this._moveEntityRow(Number(target.dataset.index), -1); return; } if (action === "move-entity-down") { this._moveEntityRow(Number(target.dataset.index), 1); return; } if (action === "duplicate-entity") { const sourceIndex = Number(target.dataset.index); this._queuePostRenderFocus(`[data-kind="entity-name"][data-index="${sourceIndex + 1}"], [data-kind="entity-picker"][data-index="${sourceIndex + 1}"], [data-kind="entity-input"][data-index="${sourceIndex + 1}"]`); this._duplicateEntityRow(sourceIndex); return; } if (action === "toggle-entity-overrides") { this._toggleEntityOverrideExpanded(Number(target.dataset.index)); return; } if (action === "toggle-override-group") { this._toggleOverrideGroupExpanded(Number(target.dataset.index), target.dataset.group); return; } if (action === "toggle-card-group") { this._toggleCardGroupExpanded(target.dataset.group); return; } if (action === "remove-entity") { this._removeEntityRow(Number(target.dataset.index)); return; } if (action === "add-gradient-stop") { this._queuePostRenderFocus("#gradient-draft-pos"); this._commitGradientStopDraft({ type: "card" }); return; } if (action === "remove-gradient-stop") { const index = Number(target.dataset.index); this._setGradientStops(this._getGradientStopsValue().filter((_, stopIndex) => stopIndex !== index), { rerender: true }); return; } if (action === "add-entity-gradient-stop") { const entityIndex = Number(target.dataset.index); this._queuePostRenderFocus(`#entity-${entityIndex}-gradient-draft-pos`); this._commitGradientStopDraft({ type: "entity", index: entityIndex }); return; } if (action === "remove-entity-gradient-stop") { const scope = { type: "entity", index: Number(target.dataset.index) }; const stopIndex = Number(target.dataset.stopIndex); this._setScopedGradientStops(scope, this._getScopedGradientStopsValue(scope).filter((_, index) => index !== stopIndex), { rerender: true }); return; } if (action === "add-segment") { this._queuePostRenderFocus("#segment-draft-from"); this._commitSegmentDraft({ type: "card" }); return; } if (action === "remove-segment") { const index = Number(target.dataset.index); this._setSegments(this._getSegmentsValue().filter((_, segmentIndex) => segmentIndex !== index), { rerender: true, sort: true }); return; } if (action === "add-entity-segment") { const entityIndex = Number(target.dataset.index); this._queuePostRenderFocus(`#entity-${entityIndex}-segment-draft-from`); this._commitSegmentDraft({ type: "entity", index: entityIndex }); return; } if (action === "remove-entity-segment") { const scope = { type: "entity", index: Number(target.dataset.index) }; const segmentIndex = Number(target.dataset.segmentIndex); this._setScopedSegments(scope, this._getScopedSegmentsValue(scope).filter((_, index) => index !== segmentIndex), { rerender: true, sort: true }); return; } } _handleChange(event) { var _a, _b; const kind = (_b = (_a = event.target) == null ? void 0 : _a.dataset) == null ? void 0 : _b.kind; if (kind === "gradient-pos") { const stopIndex = Number(event.target.dataset.index); this._commitGradientStopPosEdit({ type: "card" }, stopIndex, event.target.value, event.target); return; } if (kind === "entity-gradient-pos") { const scope = { type: "entity", index: Number(event.target.dataset.index) }; const stopIndex = Number(event.target.dataset.stopIndex); this._commitGradientStopPosEdit(scope, stopIndex, event.target.value, event.target); return; } if (kind === "segment-from" || kind === "segment-to") { this._commitSegmentBoundaryEdit({ type: "card" }, Number(event.target.dataset.index), kind === "segment-from" ? "from" : "to", event.target.value, event.target); return; } if (kind === "entity-segment-from" || kind === "entity-segment-to") { this._commitSegmentBoundaryEdit({ type: "entity", index: Number(event.target.dataset.index) }, Number(event.target.dataset.segmentIndex), kind === "entity-segment-from" ? "from" : "to", event.target.value, event.target); return; } this._handleFieldEvent(event); } _handleInput(event) { var _a; const target = event.target; if (!target) return; if (target.tagName === "HA-ENTITY-PICKER") return; if (target.tagName === "INPUT" && target.type === "checkbox") return; const kind = (_a = target.dataset) == null ? void 0 : _a.kind; if (kind === "gradient-pos") { this._setGradientStopPosText({ type: "card" }, Number(target.dataset.index), target.value); return; } if (kind === "entity-gradient-pos") { this._setGradientStopPosText({ type: "entity", index: Number(target.dataset.index) }, Number(target.dataset.stopIndex), target.value); return; } if (kind === "segment-from" || kind === "segment-to") { this._setSegmentBoundaryText({ type: "card" }, Number(target.dataset.index), kind === "segment-from" ? "from" : "to", target.value); this._refreshSegmentUi({ type: "card" }); return; } if (kind === "entity-segment-from" || kind === "entity-segment-to") { const scope = { type: "entity", index: Number(target.dataset.index) }; this._setSegmentBoundaryText(scope, Number(target.dataset.segmentIndex), kind === "entity-segment-from" ? "from" : "to", target.value); this._refreshSegmentUi(scope); return; } this._handleFieldEvent(event); } _handleValueChanged(event) { var _a; if (((_a = event.target) == null ? void 0 : _a.tagName) === "HA-ENTITY-PICKER") { this._handleFieldEvent(event); } } _handleKeydown(event) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p; const kind = (_b = (_a = event.target) == null ? void 0 : _a.dataset) == null ? void 0 : _b.kind; if (event.key === "Escape") { if (kind === "gradient-draft-pos" || kind === "gradient-draft-color") { (_c = event.preventDefault) == null ? void 0 : _c.call(event); this._gradientStopsDrafts.set(this._getGradientStopsDraftKey({ type: "card" }), this._createGradientStopDraftState({ type: "card" })); this._render(); return; } if (kind === "entity-gradient-draft-pos" || kind === "entity-gradient-draft-color") { (_d = event.preventDefault) == null ? void 0 : _d.call(event); const scope = { type: "entity", index: Number(event.target.dataset.index) }; this._gradientStopsDrafts.set(this._getGradientStopsDraftKey(scope), this._createGradientStopDraftState(scope)); this._render(); } if (kind === "segment-draft-from" || kind === "segment-draft-to" || kind === "segment-draft-color") { (_e = event.preventDefault) == null ? void 0 : _e.call(event); this._segmentDrafts.set(this._getSegmentsScopeKey({ type: "card" }), this._createSegmentDraftState({ type: "card" })); this._render(); return; } if (kind === "entity-segment-draft-from" || kind === "entity-segment-draft-to" || kind === "entity-segment-draft-color") { (_f = event.preventDefault) == null ? void 0 : _f.call(event); const scope = { type: "entity", index: Number(event.target.dataset.index) }; this._segmentDrafts.set(this._getSegmentsScopeKey(scope), this._createSegmentDraftState(scope)); this._render(); return; } return; } if (event.key !== "Enter") { return; } if (kind === "gradient-pos") { (_g = event.preventDefault) == null ? void 0 : _g.call(event); const stopIndex = Number(event.target.dataset.index); this._commitGradientStopPosEdit({ type: "card" }, stopIndex, event.target.value, event.target); return; } if (kind === "entity-gradient-pos") { (_h = event.preventDefault) == null ? void 0 : _h.call(event); const scope = { type: "entity", index: Number(event.target.dataset.index) }; const stopIndex = Number(event.target.dataset.stopIndex); this._commitGradientStopPosEdit(scope, stopIndex, event.target.value, event.target); return; } if (kind === "gradient-draft-pos") { (_i = event.preventDefault) == null ? void 0 : _i.call(event); this._commitGradientStopDraft({ type: "card" }); return; } if (kind === "gradient-draft-color") { (_j = event.preventDefault) == null ? void 0 : _j.call(event); this._commitGradientStopDraft({ type: "card" }); return; } if (kind === "entity-gradient-draft-pos") { (_k = event.preventDefault) == null ? void 0 : _k.call(event); this._commitGradientStopDraft({ type: "entity", index: Number(event.target.dataset.index) }); return; } if (kind === "entity-gradient-draft-color") { (_l = event.preventDefault) == null ? void 0 : _l.call(event); this._commitGradientStopDraft({ type: "entity", index: Number(event.target.dataset.index) }); return; } if (kind === "segment-from" || kind === "segment-to") { (_m = event.preventDefault) == null ? void 0 : _m.call(event); this._commitSegmentBoundaryEdit({ type: "card" }, Number(event.target.dataset.index), kind === "segment-from" ? "from" : "to", event.target.value, event.target); return; } if (kind === "entity-segment-from" || kind === "entity-segment-to") { (_n = event.preventDefault) == null ? void 0 : _n.call(event); this._commitSegmentBoundaryEdit({ type: "entity", index: Number(event.target.dataset.index) }, Number(event.target.dataset.segmentIndex), kind === "entity-segment-from" ? "from" : "to", event.target.value, event.target); return; } if (kind === "segment-draft-from" || kind === "segment-draft-to" || kind === "segment-draft-color") { (_o = event.preventDefault) == null ? void 0 : _o.call(event); this._commitSegmentDraft({ type: "card" }); return; } if (kind === "entity-segment-draft-from" || kind === "entity-segment-draft-to" || kind === "entity-segment-draft-color") { (_p = event.preventDefault) == null ? void 0 : _p.call(event); this._commitSegmentDraft({ type: "entity", index: Number(event.target.dataset.index) }); } } _handleFieldEvent(event) { var _a, _b, _c, _d, _e, _f, _g; const target = event.target; const rawField = (_a = target == null ? void 0 : target.dataset) == null ? void 0 : _a.field; const rawKind = (_b = target == null ? void 0 : target.dataset) == null ? void 0 : _b.kind; const field = (rawField == null ? void 0 : rawField.endsWith("-text-fallback")) ? rawField.slice(0, -14) : rawField; const kind = (rawKind == null ? void 0 : rawKind.endsWith("-text-fallback")) ? rawKind.slice(0, -14) : rawKind; const detailValue = (_c = event.detail) == null ? void 0 : _c.value; const value = detailValue != null ? detailValue : (target == null ? void 0 : target.type) === "checkbox" ? target.checked : target == null ? void 0 : target.value; if (field === "title") return void this._setTitle(value); if (field === "formatting-unit") return void this._setScopedFormattingUnit({ type: "card" }, value); if (field === "formatting-decimal") return void this._setScopedFormattingDecimal({ type: "card" }, value); if (field === "layout-label-position") return void this._setLayoutLabelPosition(value); if (field === "layout-label-hero-size") return void this._setLayoutHeroSize(value); if (field === "layout-hero-value-size") return void this._setLayoutHeroValueSize(value); if (field === "layout-height") return void this._setLayoutHeight(value); if (field === "layout-label-width") return void this._setScopedLayoutLabelWidth({ type: "card" }, value); if (field === "scale-min") return void this._setScaleBound("min", value); if (field === "scale-max") return void this._setScaleBound("max", value); if (field === "bar-fill-style") return void this._setBarFillStyle(value); if (field === "bar-color") return void this._setBarColor(value); if (field === "bar-solid-fill") return void this._setScopedBarSolidFill({ type: "card" }, value); if (field === "bar-needle-mode") return void this._setScopedNeedleMode({ type: "card" }, value); if (field === "bar-needle-color") return void this._setScopedNeedleColor({ type: "card" }, value); if (field === "baseline-mode") return void this._setBaselineMode({ type: "card" }, value); if (field === "baseline-value") { return void this._setBaselineResolvablePart({ type: "card" }, "fixed", value); } if (field === "baseline-above-color") return void this._setBaselineDirectionalColor({ type: "card" }, "above", value); if (field === "baseline-below-color") return void this._setBaselineDirectionalColor({ type: "card" }, "below", value); if (field === "baseline-above-color-enabled") return void this._setBaselineDirectionalColorEnabled({ type: "card" }, "above", value); if (field === "baseline-below-color-enabled") return void this._setBaselineDirectionalColorEnabled({ type: "card" }, "below", value); if (field === "target-mode") return void this._setTargetMode({ type: "card" }, value); if (field === "target-value") { return void this._setTargetResolvablePart({ type: "card" }, "fixed", value); } if (field === "target-color") return void this._setTargetColor({ type: "card" }, value); if (field === "target-label-show") return void this._setTargetLabelShow({ type: "card" }, value); if (field === "target-above-fill-enabled") return void this._setTargetAboveFillEnabled({ type: "card" }, value); if (field === "target-above-fill-color") return void this._setTargetAboveFillColor({ type: "card" }, value); if (field === "peak-show") return void this._setPeakShow(value); if (field === "peak-color") return void this._setScopedPeakColor({ type: "card" }, value); if (kind === "entity-picker" || kind === "entity-input") { const index = Number(target.dataset.index); const nextEntities = this._getEntitiesValue().map((entry, entryIndex) => entryIndex === index ? { ...entry, entity: this._normalizeTextValue(value) } : entry); const nextEntries = this._buildEntityConfigEntries(nextEntities); if (Array.isArray(this._draftConfig.entities) || nextEntries.length > 1 || !this._draftConfig.entity) { this._setValueAtPath(["entities"], nextEntries); } else { this._setValueAtPath(["entity"], (_e = (_d = nextEntities[0]) == null ? void 0 : _d.entity) != null ? _e : ""); } return; } if (kind === "entity-name") { return void this._setEntityField(Number(target.dataset.index), "name", value); } if (kind === "entity-icon") { return void this._setEntityField(Number(target.dataset.index), "icon", value); } if (kind === "scale-min-entity-source") { return void this._setCanonicalResolvablePart({ type: "card" }, "min", "entity", value); } if (kind === "scale-max-entity-source") { return void this._setCanonicalResolvablePart({ type: "card" }, "max", "entity", value); } if (kind === "baseline-entity-source") { return void this._setBaselineResolvablePart({ type: "card" }, "entity", value); } if (kind === "target-entity-source") { return void this._setTargetResolvablePart({ type: "card" }, "entity", value); } if (kind === "entity-scale-inherit") { if (value) { return void this._clearScaleOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-override-min") { return void this._setCanonicalResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "min", "fixed", value); } if (kind === "entity-override-max") { return void this._setCanonicalResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "max", "fixed", value); } if (kind === "entity-override-min-entity-source") { return void this._setCanonicalResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "min", "entity", value); } if (kind === "entity-override-max-entity-source") { return void this._setCanonicalResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "max", "entity", value); } if (kind === "entity-override-height") { return void this._setScopedLayoutHeight({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-layout-inherit") { if (value) { return void this._clearLayoutOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-layout-label-position") { return void this._setScopedLayoutLabelPosition({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-layout-label-hero-size") { return void this._setScopedLayoutHeroSize({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-layout-hero-value-size") { return void this._setScopedLayoutHeroValueSize({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-layout-label-width") { return void this._setScopedLayoutLabelWidth({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-formatting-inherit") { if (value) { return void this._clearFormattingOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-formatting-unit") { return void this._setScopedFormattingUnit({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-formatting-decimal") { return void this._setScopedFormattingDecimal({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-peak-inherit") { if (value) { return void this._clearPeakOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-peak-enabled") { return void this._setScopedPeakEnabled({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-peak-color") { return void this._setScopedPeakColor({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-segments-inherit") { if (value) { return void this._clearSegmentsOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-gradient-stops-inherit") { if (value) { return void this._clearGradientStopsOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-bar-inherit") { if (value) { return void this._clearEntityBarAppearance({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-needle-inherit") { if (value) { return void this._removeScopedNeedle({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-bar-fill-style") { return void this._setScopedBarFillStyle({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-bar-color") { return void this._setScopedBarColor({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-bar-solid-fill") { return void this._setScopedBarSolidFill({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-needle-mode") { return void this._setScopedNeedleMode({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-needle-color") { return void this._setScopedNeedleColor({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-baseline-mode") { return void this._setBaselineMode({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-baseline-inherit") { if (value) { return void this._clearBaselineOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-baseline-value") { return void this._setBaselineResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "fixed", value); } if (kind === "entity-baseline-entity-source") { return void this._setBaselineResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "entity", value); } if (kind === "entity-baseline-above-color") { return void this._setBaselineDirectionalColor({ type: "entity", index: Number(target.dataset.index) }, "above", value); } if (kind === "entity-baseline-below-color") { return void this._setBaselineDirectionalColor({ type: "entity", index: Number(target.dataset.index) }, "below", value); } if (kind === "entity-baseline-above-color-enabled") { return void this._setBaselineDirectionalColorEnabled({ type: "entity", index: Number(target.dataset.index) }, "above", value); } if (kind === "entity-baseline-below-color-enabled") { return void this._setBaselineDirectionalColorEnabled({ type: "entity", index: Number(target.dataset.index) }, "below", value); } if (kind === "entity-target-mode") { return void this._setTargetMode({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-target-inherit") { if (value) { return void this._clearTargetOverride({ type: "entity", index: Number(target.dataset.index) }); } return; } if (kind === "entity-target-value") { return void this._setTargetResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "fixed", value); } if (kind === "entity-target-entity-source") { return void this._setTargetResolvablePart({ type: "entity", index: Number(target.dataset.index) }, "entity", value); } if (kind === "entity-target-color") { return void this._setTargetColor({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-target-label-show") { return void this._setTargetLabelShow({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-target-above-fill-enabled") { return void this._setTargetAboveFillEnabled({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-target-above-fill-color") { return void this._setTargetAboveFillColor({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "gradient-draft-pos") { this._setGradientStopsDraftField({ type: "card" }, "pos", value); return; } if (kind === "gradient-draft-color") { this._setGradientStopsDraftField({ type: "card" }, "color", value); return; } if (kind === "entity-gradient-draft-pos") { this._setGradientStopsDraftField({ type: "entity", index: Number(target.dataset.index) }, "pos", value); return; } if (kind === "entity-gradient-draft-color") { this._setGradientStopsDraftField({ type: "entity", index: Number(target.dataset.index) }, "color", value); return; } if (kind === "segment-draft-from") { this._setSegmentDraftField({ type: "card" }, "from", value); return; } if (kind === "segment-draft-to") { this._setSegmentDraftField({ type: "card" }, "to", value); return; } if (kind === "segment-draft-color") { this._setSegmentDraftField({ type: "card" }, "color", value); return; } if (kind === "entity-segment-draft-from") { this._setSegmentDraftField({ type: "entity", index: Number(target.dataset.index) }, "from", value); return; } if (kind === "entity-segment-draft-to") { this._setSegmentDraftField({ type: "entity", index: Number(target.dataset.index) }, "to", value); return; } if (kind === "entity-segment-draft-color") { this._setSegmentDraftField({ type: "entity", index: Number(target.dataset.index) }, "color", value); return; } if (kind == null ? void 0 : kind.startsWith("gradient-")) { const index = Number(target.dataset.index); const currentStops = this._sanitizeGradientStopsForEmit(this._getGradientStopsValue()); const nextStops = this._getGradientStopsValue().map((stop, stopIndex) => { var _a2; if (stopIndex !== index) return stop; const nextPos = this._normalizeGradientStopPosValue(stop == null ? void 0 : stop.pos); return { ...stop, pos: nextPos != null ? nextPos : 0, color: kind === "gradient-color" ? value : (_a2 = stop == null ? void 0 : stop.color) != null ? _a2 : "#4a9eff" }; }); if (this._serializeConfig(nextStops) !== this._serializeConfig(currentStops)) { this._setGradientStops(nextStops); } return; } if (kind == null ? void 0 : kind.startsWith("entity-gradient-")) { const scope = { type: "entity", index: Number(target.dataset.index) }; const stopIndex = Number(target.dataset.stopIndex); const currentStops = this._sanitizeGradientStopsForEmit(this._getScopedGradientStopsValue(scope)); const nextStops = this._getScopedGradientStopsValue(scope).map((stop, currentStopIndex) => { var _a2; if (currentStopIndex !== stopIndex) return stop; const nextPos = this._normalizeGradientStopPosValue(stop == null ? void 0 : stop.pos); return { ...stop, pos: nextPos != null ? nextPos : 0, color: kind === "entity-gradient-color" ? value : (_a2 = stop == null ? void 0 : stop.color) != null ? _a2 : "#4a9eff" }; }); if (this._serializeConfig(nextStops) !== this._serializeConfig(currentStops)) { this._setScopedGradientStops(scope, nextStops); } return; } if (kind === "segment-color") { const index = Number(target.dataset.index); const nextSegments = ((_f = this._getSegmentsUiRows({ type: "card" })) != null ? _f : this._getSegmentsValue()).map((segment, segmentIndex) => { if (segmentIndex !== index) return segment; return { ...segment, color: value }; }); this._setSegments(nextSegments, { sort: false }); return; } if (kind === "entity-segment-color") { const scope = { type: "entity", index: Number(target.dataset.index) }; const segmentIndex = Number(target.dataset.segmentIndex); const nextSegments = ((_g = this._getSegmentsUiRows(scope)) != null ? _g : this._getScopedSegmentsValue(scope)).map((segment, currentSegmentIndex) => { if (currentSegmentIndex !== segmentIndex) return segment; return { ...segment, color: value }; }); this._setScopedSegments(scope, nextSegments, { sort: false }); return; } } }; } }); // src/sensor-bar-card-plus.js var require_sensor_bar_card_plus = __commonJS({ "src/sensor-bar-card-plus.js"() { init_SensorBarCard(); init_SensorBarCardPlusEditor(); customElements.define("sensor-bar-card-plus", SensorBarCard); customElements.define("sensor-bar-card-plus-editor", SensorBarCardPlusEditor); window.customCards = window.customCards || []; window.customCards.push({ type: "sensor-bar-card-plus", name: "Sensor Bar Card Plus", description: "Animated, colour-coded horizontal bar card for Home Assistant with extended target and layout features." }); } }); require_sensor_bar_card_plus(); })();