(() => { 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/utils/extrema.js function getLocalBoundaryTimestamp(date, unit) { if (!(date instanceof Date) || Number.isNaN(date.getTime())) return null; const year = date.getFullYear(); const month = date.getMonth(); const day = date.getDate(); const hour = date.getHours(); if (unit === "quarterly") { return new Date(year, month, day, hour, Math.floor(date.getMinutes() / 15) * 15, 0, 0).getTime(); } if (unit === "hourly") { return new Date(year, month, day, hour, 0, 0, 0).getTime(); } if (unit === "daily") { return new Date(year, month, day, 0, 0, 0, 0).getTime(); } if (unit === "weekly") { const daysSinceMonday = (date.getDay() + 6) % 7; return new Date(year, month, day - daysSinceMonday, 0, 0, 0, 0).getTime(); } if (unit === "monthly") { return new Date(year, month, 1, 0, 0, 0, 0).getTime(); } if (unit === "yearly") { return new Date(year, 0, 1, 0, 0, 0, 0).getTime(); } return null; } function normalizeReset(value) { if (value === void 0) value = "never"; if (typeof value !== "string") return { kind: "never" }; const normalized = value.trim().toLowerCase(); if (normalized === "never") return { kind: "never" }; if (CALENDAR_RESETS.has(normalized)) { return { kind: "calendar", unit: normalized }; } const durationMatch = normalized.match(/^(\d+)(m|h)$/); if (!durationMatch) return { kind: "never" }; const amount = Number(durationMatch[1]); const unit = durationMatch[2]; if (!Number.isInteger(amount) || amount < 1 || unit === "m" && amount > 59 || unit === "h" && amount > 23) { return { kind: "never" }; } return unit === "m" ? { kind: "duration", minutes: amount } : { kind: "duration", hours: amount }; } function isValidReset(value) { if (typeof value !== "string") return false; const normalized = value.trim().toLowerCase(); if (normalized === "never" || CALENDAR_RESETS.has(normalized)) return true; const match = normalized.match(/^(\d+)(m|h)$/); if (!match) return false; const amount = Number(match[1]); return Number.isInteger(amount) && amount >= 1 && (match[2] === "m" ? amount <= 59 : amount <= 23); } function getResetWindowKey(reset, timestamp) { if ((reset == null ? void 0 : reset.kind) !== "calendar") return null; const boundary = getLocalBoundaryTimestamp(new Date(timestamp), reset.unit); return Number.isFinite(boundary) ? String(boundary) : null; } function getDurationMs(reset) { if ((reset == null ? void 0 : reset.kind) !== "duration") return null; if (Number.isInteger(reset.minutes)) return reset.minutes * 60 * 1e3; if (Number.isInteger(reset.hours)) return reset.hours * 60 * 60 * 1e3; return null; } function initializeExtremum(sample, reset, timestamp) { if ((reset == null ? void 0 : reset.kind) === "duration") { return { value: sample, startedAtMs: Number.isFinite(timestamp) ? timestamp : null, windowKey: null }; } if ((reset == null ? void 0 : reset.kind) === "calendar") { return { value: sample, startedAtMs: null, windowKey: getResetWindowKey(reset, timestamp) }; } return { value: sample, startedAtMs: null, windowKey: null }; } function updateExtremum(previous, sample, reset, direction, timestamp) { if (!Number.isFinite(sample)) return previous != null ? previous : null; const durationMs = getDurationMs(reset); if (!previous) return initializeExtremum(sample, reset, timestamp); if (durationMs !== null && Number.isFinite(previous.startedAtMs) && Number.isFinite(timestamp) && timestamp - previous.startedAtMs >= durationMs) { return initializeExtremum(sample, reset, timestamp); } if ((reset == null ? void 0 : reset.kind) === "calendar") { const windowKey = getResetWindowKey(reset, timestamp); if (windowKey !== null && windowKey !== previous.windowKey) { return initializeExtremum(sample, reset, timestamp); } } const shouldReplace = direction === "min" ? sample < previous.value : sample > previous.value; return shouldReplace ? { ...previous, value: sample } : previous; } var CALENDAR_RESETS; var init_extrema = __esm({ "src/utils/extrema.js"() { CALENDAR_RESETS = /* @__PURE__ */ new Set([ "quarterly", "hourly", "daily", "weekly", "monthly", "yearly" ]); } }); // 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 hasConfiguredMarkerSource(source) { var _a; return !!source && (getFiniteNumber((_a = source.fixed) != null ? _a : source.value) !== null || Number.isFinite(source.percent) || !!source.entity); } function applyGenericMarkerCapacity(markers, config) { var _a, _b, _c, _d; const occupied = { above: ((_a = config == null ? void 0 : config.peak_marker) == null ? void 0 : _a.show) === true ? 1 : 0, below: (((_b = config == null ? void 0 : config.floor_marker) == null ? void 0 : _b.show) === true ? 1 : 0) + (((_c = config == null ? void 0 : config.target_marker) == null ? void 0 : _c.enabled) !== false && hasConfiguredMarkerSource((_d = config == null ? void 0 : config.target_marker) == null ? void 0 : _d.source) ? 1 : 0) }; return markers.map((marker) => { const accepted = marker.valid && occupied[marker.lane] < 4; if (accepted) occupied[marker.lane] += 1; return { ...marker, accepted }; }); } function normalizeGenericMarkerList(input, capacityConfig = null) { if (!Array.isArray(input)) { return { markers: [], invalidList: input !== void 0 }; } const markers = input.map((rawMarker, index) => { var _a; if (!rawMarker || typeof rawMarker !== "object" || Array.isArray(rawMarker)) { return { id: `generic-${index}`, index, valid: false, accepted: false, malformed: true }; } const rawAt = rawMarker.at; const hasUnsupportedPercentField = rawAt && typeof rawAt === "object" && Object.prototype.hasOwnProperty.call(rawAt, "percent"); const atInput = typeof rawAt === "string" ? rawAt.trim() : rawAt; const source = normalizeStructuredResolvableValue(atInput, null, null, { allowPercent: true }); const explicitEntity = rawAt && typeof rawAt === "object" && rawAt.entity !== void 0 ? rawAt.entity : typeof atInput === "string" && looksLikeEntityId(atInput) ? atInput : null; const invalidEntity = explicitEntity !== null && explicitEntity !== void 0 && explicitEntity !== "" && !looksLikeEntityId(explicitEntity); const invalidFixed = rawAt && typeof rawAt === "object" && rawAt.fixed !== void 0 && rawAt.fixed !== null && getFiniteNumber(rawAt.fixed) === null; const hasSource = !!source.entity || getFiniteNumber(source.fixed) !== null || Number.isFinite(source.percent); const invalidPercentage = Number.isFinite(source.percent) && (source.percent < 0 || source.percent > 100); const validSource = rawAt !== void 0 && rawAt !== null && !hasUnsupportedPercentField && !invalidEntity && !invalidFixed && hasSource && !invalidPercentage; const lane = rawMarker.lane === void 0 ? "below" : rawMarker.lane; const validLane = lane === "above" || lane === "below"; const supportedShapes = ["circle", "diamond", "triangle", "chevron", "arrow", "pin"]; const validShape = rawMarker.shape === void 0 || supportedShapes.includes(rawMarker.shape); const direction = normalizeMarkerDirection(rawMarker.direction); const invalidDirection = rawMarker.direction !== void 0 && !["inward", "outward"].includes( typeof rawMarker.direction === "string" ? rawMarker.direction.trim().toLowerCase() : "" ); const label = rawMarker.label && typeof rawMarker.label === "object" && !Array.isArray(rawMarker.label) ? rawMarker.label : {}; const labelConfig = normalizeMarkerLabelConfig(label); const labelEntityInput = label.entity; const labelEntity = typeof labelEntityInput === "string" ? labelEntityInput.trim() : ""; const invalidLabelEntity = labelEntityInput !== void 0 && labelEntityInput !== null && labelEntityInput !== "" && !looksLikeEntityId(labelEntity); const validLabelEntity = labelEntity && looksLikeEntityId(labelEntity) ? labelEntity : null; const showMarker = typeof rawMarker.show_marker === "boolean" ? rawMarker.show_marker : true; return { id: `generic-${index}`, index, source: { ...source, entity: typeof source.entity === "string" ? source.entity.trim() : source.entity }, lane: validLane ? lane : null, shape: validShape ? (_a = rawMarker.shape) != null ? _a : "circle" : "circle", direction, invalidDirection, showMarker, invalidShowMarker: rawMarker.show_marker !== void 0 && typeof rawMarker.show_marker !== "boolean", color: typeof rawMarker.color === "string" && rawMarker.color.trim() ? rawMarker.color : "#888888", label: { show: label.show === true, text: labelConfig.label_text, entity: validLabelEntity, showValue: labelConfig.label_show_value, showUnit: labelConfig.label_show_unit, precision: labelConfig.label_precision, invalidShow: labelConfig.label_invalid_show, invalidText: labelConfig.label_invalid_text, invalidShowValue: labelConfig.label_invalid_show_value, invalidShowUnit: labelConfig.label_invalid_show_unit, invalidPrecision: labelConfig.label_invalid_precision, invalidPrecisionKey: labelConfig.label_precision_key, unsupportedUnit: labelConfig.label_unsupported_unit, invalidEntity: invalidLabelEntity }, valid: validSource && validLane, invalidSource: !validSource, invalidPercentage, unsupportedPercentField: hasUnsupportedPercentField, invalidLane: !validLane, invalidShape: !validShape, accepted: false }; }); return { markers: applyGenericMarkerCapacity(markers, capacityConfig), invalidList: false }; } 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 normalizeSegmentBoundary(input, legacySegmentSpace = null) { var _a; if (input === void 0) return { value: null, issue: null }; if (input === null) return { value: null, issue: "malformed" }; if (input && typeof input === "object" && !Array.isArray(input)) { if (input.entity !== void 0 && input.entity !== null && input.entity !== "") { return { value: null, issue: "entity" }; } if (Object.prototype.hasOwnProperty.call(input, "percent")) { const percent = getFiniteNumber(input.percent); return Number.isFinite(percent) ? { value: normalizeResolvableValue(null, null, percent), issue: null } : { value: null, issue: "malformed" }; } const fixed = getFiniteNumber((_a = input.fixed) != null ? _a : input.value); return Number.isFinite(fixed) ? { value: normalizeResolvableValue(fixed, null), issue: null } : { value: null, issue: "malformed" }; } if (typeof input === "string") { const trimmed = input.trim(); if (looksLikeEntityId(trimmed)) return { value: null, issue: "entity" }; if (trimmed.includes("%")) { const percent = parsePercentLiteral(trimmed); return Number.isFinite(percent) ? { value: normalizeResolvableValue(null, null, percent), issue: null } : { value: null, issue: "malformed_percent" }; } } const numeric = getFiniteNumber(input); if (!Number.isFinite(numeric)) return { value: null, issue: "malformed" }; return legacySegmentSpace === "percent" ? { value: normalizeResolvableValue(null, null, numeric), issue: null } : { value: normalizeResolvableValue(numeric, null), issue: null }; } function normalizeGaugeSegments(input, options = {}) { if (!Array.isArray(input)) return null; const { legacySegmentSpace = null } = options; const segments = input.map((segment) => { var _a, _b; const from = (segment == null ? void 0 : segment.from) === void 0 ? { value: null, issue: "malformed" } : normalizeSegmentBoundary(segment.from, legacySegmentSpace); const to = (segment == null ? void 0 : segment.to) === void 0 ? { value: null, issue: null } : segment.to === null ? { value: null, issue: null } : normalizeSegmentBoundary(segment.to, legacySegmentSpace); if (!(segment == null ? void 0 : segment.color)) { return null; } return { from: from.value, to: to.value, invalidBoundary: (_a = from.issue) != null ? _a : to.issue, color: segment.color, label: (_b = segment.label) != null ? _b : null }; }).filter(Boolean); return segments.map((segment, index) => { var _a; const nextValid = segments.slice(index + 1).find((candidate) => !candidate.invalidBoundary); return { from: segment.from ? { ...segment.from } : null, to: segment.to ? { ...segment.to } : (nextValid == null ? void 0 : nextValid.from) ? { ...nextValid.from } : null, ...segment.invalidBoundary ? { invalidBoundary: segment.invalidBoundary } : {}, 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, _i, _j; 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 ); const inheritedFixedExplicit = cardBound ? cardBound.fixed_explicit !== false && cardBound.fixed !== null && cardBound.fixed !== void 0 : (cardConfig == null ? void 0 : cardConfig[key]) !== null && (cardConfig == null ? void 0 : cardConfig[key]) !== void 0; const withFixedExplicit = (bound, explicit) => { Object.defineProperty(bound, "fixed_explicit", { value: explicit }); return bound; }; if ((entityScale == null ? void 0 : entityScale[key]) !== void 0) { const input = entityScale[key]; const fixedExplicit = looksLikeEntityId(input) ? inheritedFixedExplicit : typeof input === "object" && input !== null ? ((_f = input.fixed) != null ? _f : input.value) !== null && ((_g = input.fixed) != null ? _g : input.value) !== void 0 : input !== null; return withFixedExplicit(normalizeStructuredResolvableValue( entityScale[key], inherited, defaultValue ), fixedExplicit); } const entityOverride = entityConfig[entityKey]; const hasEntityOverride = entityOverride !== void 0 && entityOverride !== null; const value = (_i = (_h = entityConfig[key]) != null ? _h : hasEntityOverride ? null : inherited.fixed) != null ? _i : inherited.entity ? null : defaultValue; const entity = (_j = entityOverride != null ? entityOverride : inherited.entity) != null ? _j : null; return withFixedExplicit( normalizeResolvableValue(value, entity), entityConfig[key] !== null && entityConfig[key] !== void 0 || !hasEntityOverride && inheritedFixedExplicit ); } 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 hasOwnConfigValue(config, key) { return config !== null && config !== void 0 && Object.prototype.hasOwnProperty.call(config, key); } function hasExplicitColor(config) { const values = [ hasOwnConfigValue(config, "color") ? config.color : void 0, hasOwnConfigValue(config == null ? void 0 : config.bar, "color") ? config.bar.color : void 0 ]; return values.some((value) => value !== void 0 && value !== null); } function getPaintExplicitness(config) { const bar = config == null ? void 0 : config.bar; const explicitPaintKeys = [ [config, "color_mode"], [bar, "color_mode"], [bar, "fill_style"], [config, "severity"], [config, "segments"], [bar, "segments"], [config, "gradient_stops"], [bar, "gradient_stops"], [bar, "solid_fill"] ]; return { color: hasExplicitColor(config), paint: explicitPaintKeys.some(([source, key]) => hasOwnConfigValue(source, key)) }; } 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, { scopeExplicitness = null, inheritedExplicitness = null, isCardScope = false } = {}) { const colorOnlyScope = (scopeExplicitness == null ? void 0 : scopeExplicitness.color) === true && scopeExplicitness.paint !== true; const inheritedPaintIsExplicit = (inheritedExplicitness == null ? void 0 : inheritedExplicitness.paint) === true; if (colorOnlyScope && (isCardScope || !inheritedPaintIsExplicit)) { return normalizeBarModeConfig({ fill_style: "solid" }, null); } 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, 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; const scopeExplicitness = (_a = options.scopeExplicitness) != null ? _a : getPaintExplicitness(entityConfig); const inheritedExplicitness = (_c = (_b = options.inheritedExplicitness) != null ? _b : cardConfig == null ? void 0 : cardConfig[PAINT_EXPLICITNESS]) != null ? _c : getPaintExplicitness(cardConfig); const isCardScope = (_d = options.isCardScope) != null ? _d : cardConfig == null; const cardBar = cardConfig == null ? void 0 : cardConfig.bar; const entityBar = entityConfig == null ? void 0 : entityConfig.bar; const inheritedSegmentSpace = hasOwnConfigValue(cardBar, EXPLICIT_SEGMENT_SPACE) ? cardBar[EXPLICIT_SEGMENT_SPACE] : ["percent", "scale"].includes(cardBar == null ? void 0 : cardBar.segment_space) ? cardBar.segment_space : null; const explicitSegmentSpace = ["percent", "scale"].includes(entityBar == null ? void 0 : entityBar.segment_space) ? entityBar.segment_space : inheritedSegmentSpace; const entityStructuredSegments = entityBar == null ? void 0 : entityBar.segments; const entityTopLevelSegments = entityConfig.segments; const entityLegacySeverity = entityConfig.severity; const cardStructuredSegments = (_e = cardBar == null ? void 0 : cardBar.segments) != null ? _e : null; const cardTopLevelSegments = (_f = cardConfig == null ? void 0 : cardConfig.segments) != null ? _f : null; const cardLegacySeverity = (_g = cardConfig == null ? void 0 : cardConfig.severity) != null ? _g : null; let segments = null; let segment_space = (cardBar == null ? void 0 : cardBar.segment_space) === "percent" || (cardBar == null ? void 0 : cardBar.segment_space) === "scale" ? cardBar.segment_space : null; if (entityStructuredSegments !== void 0 && entityStructuredSegments !== null) { segment_space = explicitSegmentSpace; segments = normalizeGaugeSegments(entityStructuredSegments, { legacySegmentSpace: segment_space }); } else if (entityTopLevelSegments !== void 0 && entityTopLevelSegments !== null) { segments = normalizeGaugeSegments(entityTopLevelSegments); } 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 })); } else if (cardTopLevelSegments !== null && cardTopLevelSegments !== void 0) { segments = normalizeGaugeSegments(cardTopLevelSegments); } 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) ? (_h = entityConfig.target.when_exceeded) == null ? void 0 : _h.fill_color : void 0; const inheritedStructuredAboveTargetColor = (cardConfig == null ? void 0 : cardConfig.target) && typeof cardConfig.target === "object" && !Array.isArray(cardConfig.target) ? (_i = cardConfig.target.when_exceeded) == null ? void 0 : _i.fill_color : void 0; const normalizedMode = resolveNormalizedBarMode( entityBar, entityConfig, cardBar, cardConfig, { scopeExplicitness, inheritedExplicitness, isCardScope } ); const normalizedBar = { 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: (_k = (_j = entityBar == null ? void 0 : entityBar.solid_fill) != null ? _j : cardBar == null ? void 0 : cardBar.solid_fill) != null ? _k : false, color: (_o = (_n = (_m = (_l = entityBar == null ? void 0 : entityBar.color) != null ? _l : entityConfig.color) != null ? _m : cardBar == null ? void 0 : cardBar.color) != null ? _n : cardConfig == null ? void 0 : cardConfig.color) != null ? _o : "#4a9eff", gradient_stops: normalizeGradientStops( (_s = (_r = (_q = (_p = entityBar == null ? void 0 : entityBar.gradient_stops) != null ? _p : entityConfig.gradient_stops) != null ? _q : cardBar == null ? void 0 : cardBar.gradient_stops) != null ? _r : cardConfig == null ? void 0 : cardConfig.gradient_stops) != null ? _s : null ), severity: segments, segments, segment_space, animated: (_w = (_v = (_u = (_t = entityBar == null ? void 0 : entityBar.animated) != null ? _t : entityConfig.animated) != null ? _u : cardBar == null ? void 0 : cardBar.animated) != null ? _v : cardConfig == null ? void 0 : cardConfig.animated) != null ? _w : true, above_target_color: (_A = (_z = (_y = (_x = structuredAboveTargetColor != null ? structuredAboveTargetColor : entityConfig.above_target_color) != null ? _x : cardBar == null ? void 0 : cardBar.above_target_color) != null ? _y : inheritedStructuredAboveTargetColor) != null ? _z : cardConfig == null ? void 0 : cardConfig.above_target_color) != null ? _A : null }; Object.defineProperty(normalizedBar, EXPLICIT_SEGMENT_SPACE, { value: explicitSegmentSpace }); return normalizedBar; } 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 normalizeTargetMarkerShape(value) { const normalized = String(value != null ? value : "").trim().toLowerCase(); return normalized === "triangle" || normalized === "diamond" ? normalized : "diamond"; } function normalizeMarkerDirection(value) { const normalized = typeof value === "string" ? value.trim().toLowerCase() : ""; return normalized === "outward" ? "outward" : "inward"; } function normalizeMarkerLabelConfig(rawLabel, inherited = {}) { var _a, _b, _c; const label = rawLabel && typeof rawLabel === "object" && !Array.isArray(rawLabel) ? rawLabel : {}; const hasText = Object.prototype.hasOwnProperty.call(label, "text"); const textValue = hasText ? typeof label.text === "string" ? label.text.replace(/\s+/g, " ").trim() : inherited.label_text : inherited.label_text; const hasPrecision = Object.prototype.hasOwnProperty.call(label, "precision"); const hasDecimal = Object.prototype.hasOwnProperty.call(label, "decimal"); const precisionValue = hasPrecision ? label.precision : label.decimal; const precisionSet = hasPrecision || hasDecimal; const precision = precisionSet ? getFiniteNumber(precisionValue) : (_a = inherited.label_precision) != null ? _a : null; const precisionInvalid = precisionSet && precisionValue !== null && precisionValue !== "" && !(Number.isInteger(precision) && precision >= 0); return { label_text: textValue != null ? textValue : null, label_show_value: typeof label.show_value === "boolean" ? label.show_value : (_b = inherited.label_show_value) != null ? _b : true, label_show_unit: typeof label.show_unit === "boolean" ? label.show_unit : (_c = inherited.label_show_unit) != null ? _c : true, label_precision: precisionInvalid ? null : precision, label_invalid_show: label.show !== void 0 && typeof label.show !== "boolean", label_invalid_text: hasText && typeof label.text !== "string", label_invalid_show_value: label.show_value !== void 0 && typeof label.show_value !== "boolean", label_invalid_show_unit: label.show_unit !== void 0 && typeof label.show_unit !== "boolean", label_invalid_precision: precisionInvalid, label_precision_key: precisionInvalid ? hasPrecision ? "precision" : "decimal" : void 0, label_unsupported_unit: Object.prototype.hasOwnProperty.call(label, "unit") }; } function builtinMarkerLabelFields(options) { const fields = {}; if (options.label_text !== null && options.label_text !== void 0) fields.label_text = options.label_text; if (options.label_show_value === false) fields.label_show_value = false; if (options.label_show_unit === false) fields.label_show_unit = false; if (options.label_precision !== null && options.label_precision !== void 0) fields.label_precision = options.label_precision; if (options.label_invalid_text) fields.label_invalid_text = true; if (options.label_invalid_show_value) fields.label_invalid_show_value = true; if (options.label_invalid_show_unit) fields.label_invalid_show_unit = true; if (options.label_invalid_show) fields.label_invalid_show = true; if (options.label_invalid_precision) fields.label_invalid_precision = true; if (options.label_invalid_precision && options.label_precision_key) fields.label_precision_key = options.label_precision_key; if (options.label_unsupported_unit) fields.label_unsupported_unit = true; return fields; } function isInvalidMarkerDirection(value) { return value !== void 0 && !["inward", "outward"].includes( typeof value === "string" ? value.trim().toLowerCase() : "" ); } 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, _C, _D, _E, _F, _G, _H, _I; 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 ? { ...cardTarget, shape: normalizeTargetMarkerShape(cardTarget.shape), direction: normalizeMarkerDirection(cardTarget.direction) } : { 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, ...builtinMarkerLabelFields(normalizeMarkerLabelConfig((_d = cardConfig == null ? void 0 : cardConfig.target) == null ? void 0 : _d.label)), label_decimal: (_j = (_i = (_f = (_e = cardConfig == null ? void 0 : cardConfig.target) == null ? void 0 : _e.label) == null ? void 0 : _f.precision) != null ? _i : (_h = (_g = cardConfig == null ? void 0 : cardConfig.target) == null ? void 0 : _g.label) == null ? void 0 : _h.decimal) != null ? _j : null, shape: "diamond", direction: "inward" }; if (rawTarget && typeof rawTarget === "object" && !Array.isArray(rawTarget)) { const labelOptions = normalizeMarkerLabelConfig(rawTarget.label, inheritedTarget); const normalizedTarget2 = { enabled: (_l = (_k = normalizeOptionalEnabled(rawTarget.enabled)) != null ? _k : inheritedTarget.enabled) != null ? _l : null, source: normalizeStructuredResolvableValue(rawTarget.at, inheritedTarget.source, null, { allowPercent: true }), color: (_n = (_m = rawTarget.color) != null ? _m : entityConfig.target_color) != null ? _n : inheritedTarget.color, show_label: (_q = (_p = (_o = rawTarget.label) == null ? void 0 : _o.show) != null ? _p : entityConfig.show_target_label) != null ? _q : inheritedTarget.show_label, shape: Object.prototype.hasOwnProperty.call(rawTarget, "shape") ? normalizeTargetMarkerShape(rawTarget.shape) : inheritedTarget.shape, direction: Object.prototype.hasOwnProperty.call(rawTarget, "direction") ? normalizeMarkerDirection(rawTarget.direction) : inheritedTarget.direction, ...isInvalidMarkerDirection(rawTarget.direction) ? { direction_invalid: true } : {}, ...builtinMarkerLabelFields(labelOptions) }; const labelDecimal2 = labelOptions.label_precision; if (labelDecimal2 !== null && labelDecimal2 !== void 0) { normalizedTarget2.label_decimal = labelDecimal2; normalizedTarget2.label_precision = labelDecimal2; } return normalizedTarget2; } const value = (_v = (_u = (_s = entityConfig.target) != null ? _s : (_r = inheritedTarget.source) == null ? void 0 : _r.fixed) != null ? _u : (_t = inheritedTarget.source) == null ? void 0 : _t.value) != null ? _v : legacyCardTarget; const entity = (_z = (_y = (_x = entityConfig.target_entity) != null ? _x : (_w = inheritedTarget.source) == null ? void 0 : _w.entity) != null ? _y : cardConfig == null ? void 0 : cardConfig.target_entity) != null ? _z : null; const percent = entityConfig.target === void 0 && entityConfig.target_entity === void 0 ? (_B = (_A = inheritedTarget.source) == null ? void 0 : _A.percent) != null ? _B : null : null; const normalizedTarget = { enabled: (_C = inheritedTarget.enabled) != null ? _C : null, source: normalizeResolvableValue(value, entity, percent), color: (_F = (_E = (_D = entityConfig.target_color) != null ? _D : inheritedTarget.color) != null ? _E : cardConfig == null ? void 0 : cardConfig.target_color) != null ? _F : "#888", show_label: (_I = (_H = (_G = entityConfig.show_target_label) != null ? _G : inheritedTarget.show_label) != null ? _H : cardConfig == null ? void 0 : cardConfig.show_target_label) != null ? _I : false, shape: inheritedTarget.shape, direction: inheritedTarget.direction, ...builtinMarkerLabelFields(inheritedTarget) }; const labelDecimal = normalizedTarget.label_precision; if (labelDecimal !== null && labelDecimal !== void 0) { normalizedTarget.label_decimal = labelDecimal; } return normalizedTarget; } function getRawExtremumConfig(config, key) { const value = config == null ? void 0 : config[key]; if (value && typeof value === "object" && !Array.isArray(value)) return value; const markerValue = config == null ? void 0 : config[`${key}_marker`]; return markerValue && typeof markerValue === "object" && !Array.isArray(markerValue) ? markerValue : null; } function normalizeLabelConfig(rawConfig, inheritedConfig) { var _a, _b, _c; const rawLabel = rawConfig == null ? void 0 : rawConfig.label; const hasRawLabel = rawLabel && typeof rawLabel === "object" && !Array.isArray(rawLabel); const options = normalizeMarkerLabelConfig(rawLabel, inheritedConfig); return { show: hasRawLabel && typeof rawLabel.show === "boolean" ? rawLabel.show : (_a = inheritedConfig.show_label) != null ? _a : false, text: options.label_text, invalidShow: options.label_invalid_show, showValue: options.label_show_value, showUnit: options.label_show_unit, precision: options.label_invalid_precision ? null : (_c = (_b = options.label_precision) != null ? _b : inheritedConfig.label_decimal) != null ? _c : null, invalidText: options.label_invalid_text, invalidShowValue: options.label_invalid_show_value, invalidShowUnit: options.label_invalid_show_unit, invalidPrecision: options.label_invalid_precision, precisionKey: options.label_precision_key, unsupportedUnit: options.label_unsupported_unit }; } function normalizeExtremumMarkerConfig(entityConfig, cardConfig, key, options = {}) { var _a, _b, _c, _d, _e, _f, _g, _h, _i; const { legacy = false, defaultColor = "#888888" } = options; const cardMarker = cardConfig == null ? void 0 : cardConfig[`${key}_marker`]; const rawMarker = getRawExtremumConfig(entityConfig, key); const inherited = cardMarker != null ? cardMarker : { show: legacy ? (_a = cardConfig == null ? void 0 : cardConfig.show_peak) != null ? _a : false : false, color: legacy ? (_b = cardConfig == null ? void 0 : cardConfig.peak_color) != null ? _b : defaultColor : defaultColor, show_label: false, label_decimal: null, label_text: null, label_show_value: true, label_show_unit: true, label_precision: null, reset: { kind: "never" }, direction: "inward" }; const hasReset = rawMarker && Object.prototype.hasOwnProperty.call(rawMarker, "reset"); const rawReset = hasReset ? rawMarker.reset : void 0; const reset = hasReset ? normalizeReset(rawReset) : (_c = inherited.reset) != null ? _c : { kind: "never" }; const rawLabel = rawMarker == null ? void 0 : rawMarker.label; const label = normalizeLabelConfig(rawMarker, inherited); const normalized = { show: (_f = (_e = (_d = rawMarker == null ? void 0 : rawMarker.enabled) != null ? _d : legacy ? entityConfig.show_peak : void 0) != null ? _e : inherited.show) != null ? _f : false, color: (_i = (_h = (_g = rawMarker == null ? void 0 : rawMarker.color) != null ? _g : legacy ? entityConfig.peak_color : void 0) != null ? _h : inherited.color) != null ? _i : defaultColor, direction: rawMarker && Object.prototype.hasOwnProperty.call(rawMarker, "direction") ? normalizeMarkerDirection(rawMarker.direction) : normalizeMarkerDirection(inherited.direction), ...isInvalidMarkerDirection(rawMarker == null ? void 0 : rawMarker.direction) ? { direction_invalid: true } : {} }; const inheritedAdvanced = cardMarker && (Object.prototype.hasOwnProperty.call(cardMarker, "show_label") || Object.prototype.hasOwnProperty.call(cardMarker, "label_decimal") || Object.prototype.hasOwnProperty.call(cardMarker, "label_text") || Object.prototype.hasOwnProperty.call(cardMarker, "label_show_value") || Object.prototype.hasOwnProperty.call(cardMarker, "label_show_unit") || Object.prototype.hasOwnProperty.call(cardMarker, "label_precision") || Object.prototype.hasOwnProperty.call(cardMarker, "reset")); const hasAdvancedConfig = key === "floor" || hasReset || rawLabel !== void 0 || inheritedAdvanced; if (hasAdvancedConfig) { normalized.show_label = label.show; normalized.label_decimal = label.precision; normalized.reset = reset; } Object.assign(normalized, builtinMarkerLabelFields({ label_text: label.text, label_show_value: label.showValue === true ? void 0 : label.showValue, label_show_unit: label.showUnit === true ? void 0 : label.showUnit, label_precision: label.precision, label_invalid_text: label.invalidText, label_invalid_show: label.invalidShow, label_invalid_show_value: label.invalidShowValue, label_invalid_show_unit: label.invalidShowUnit, label_invalid_precision: label.invalidPrecision, label_precision_key: label.precisionKey, label_unsupported_unit: label.unsupportedUnit })); if (hasReset && !isValidReset(rawReset)) { normalized.reset_invalid = true; } return normalized; } function normalizePeakMarkerConfig(entityConfig, cardConfig) { return normalizeExtremumMarkerConfig(entityConfig, cardConfig, "peak", { legacy: true, defaultColor: "#888888" }); } function normalizeFloorMarkerConfig(entityConfig, cardConfig) { return normalizeExtremumMarkerConfig(entityConfig, cardConfig, "floor", { defaultColor: "#888888" }); } function normalizeEntityConfig(entityConfig, cardConfig) { var _a, _b, _c; 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, { scopeExplicitness: getPaintExplicitness(entityConfig), inheritedExplicitness: (_b = cardConfig == null ? void 0 : cardConfig[PAINT_EXPLICITNESS]) != null ? _b : getPaintExplicitness(cardConfig), isCardScope: false }); normalizedEntity.baseline = normalizeBaselineConfig(entityConfig, cardConfig); normalizedEntity.formatting = normalizeFormattingConfig(entityConfig, cardConfig); normalizedEntity.target_marker = normalizeTargetMarkerConfig(entityConfig, cardConfig); normalizedEntity.peak_marker = normalizePeakMarkerConfig(entityConfig, cardConfig); normalizedEntity.floor_marker = normalizeFloorMarkerConfig(entityConfig, cardConfig); const normalizedMarkers = entityConfig.markers === void 0 ? { markers: applyGenericMarkerCapacity((_c = cardConfig == null ? void 0 : cardConfig.generic_markers) != null ? _c : [], normalizedEntity), invalidList: (cardConfig == null ? void 0 : cardConfig.generic_markers_invalid) === true } : normalizeGenericMarkerList(entityConfig.markers, normalizedEntity); normalizedEntity.generic_markers = normalizedMarkers.markers; normalizedEntity.generic_markers_invalid = normalizedMarkers.invalidList; 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 cardPaintExplicitness = getPaintExplicitness(rawConfig); const baseConfig = { title: "", label_position: "left", color_mode: "severity", color: "#4a9eff", animated: true, show_peak: false, peak_color: "#888888", 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 }; Object.defineProperty(normalizedCard, PAINT_EXPLICITNESS, { value: cardPaintExplicitness, enumerable: false }); normalizedCard.layout = normalizeLayoutConfig(baseConfig, null); normalizedCard.scale = normalizeScaleConfig(rawConfig, null); normalizedCard.bar = normalizeBarConfig(baseConfig, null, { scopeExplicitness: cardPaintExplicitness, inheritedExplicitness: null, isCardScope: true }); normalizedCard.baseline = normalizeBaselineConfig(baseConfig, null); normalizedCard.formatting = normalizeFormattingConfig(baseConfig, null); normalizedCard.target_marker = normalizeTargetMarkerConfig(baseConfig, null); normalizedCard.peak_marker = normalizePeakMarkerConfig(baseConfig, null); normalizedCard.floor_marker = normalizeFloorMarkerConfig(baseConfig, null); const normalizedMarkers = normalizeGenericMarkerList(baseConfig.markers, normalizedCard); normalizedCard.generic_markers = normalizedMarkers.markers; normalizedCard.generic_markers_invalid = normalizedMarkers.invalidList; normalizedCard.entities = baseConfig.entities.map( (entityCfg) => normalizeEntityConfig(entityCfg, normalizedCard) ); return normalizedCard; } var PAINT_EXPLICITNESS, EXPLICIT_SEGMENT_SPACE; var init_normalize = __esm({ "src/config/normalize.js"() { init_extrema(); PAINT_EXPLICITNESS = /* @__PURE__ */ Symbol("sbcp.paintExplicitness"); EXPLICIT_SEGMENT_SPACE = /* @__PURE__ */ Symbol("sbcp.explicitSegmentSpace"); } }); // 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; } function getResolvedScale(hass, scale, previousScale = null) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l; const isValid = (bounds) => Number.isFinite(bounds == null ? void 0 : bounds.min) && Number.isFinite(bounds == null ? void 0 : bounds.max) && bounds.min < bounds.max; const fixed = { min: getNumericValue(null, (_c = (_a = scale == null ? void 0 : scale.min) == null ? void 0 : _a.fixed) != null ? _c : (_b = scale == null ? void 0 : scale.min) == null ? void 0 : _b.value), max: getNumericValue(null, (_f = (_d = scale == null ? void 0 : scale.max) == null ? void 0 : _d.fixed) != null ? _f : (_e = scale == null ? void 0 : scale.max) == null ? void 0 : _e.value) }; if (((_g = scale == null ? void 0 : scale.min) == null ? void 0 : _g.entity) && ((_h = scale == null ? void 0 : scale.max) == null ? void 0 : _h.entity)) { const dynamic = { min: getEntityNumericValue(hass, scale.min.entity), max: getEntityNumericValue(hass, scale.max.entity) }; if (isValid(dynamic)) return dynamic; if (Number.isFinite(dynamic.min) && Number.isFinite(dynamic.max) && isValid(previousScale)) { return previousScale; } return scale.min.fixed_explicit !== false && scale.max.fixed_explicit !== false && isValid(fixed) ? fixed : { min: 0, max: 100 }; } const resolved = { min: (_i = getNormalizedResolvableNumericValue(hass, scale == null ? void 0 : scale.min)) != null ? _i : 0, max: (_j = getNormalizedResolvableNumericValue(hass, scale == null ? void 0 : scale.max)) != null ? _j : 100 }; if (isValid(resolved)) return resolved; const fallback = { min: (_k = fixed.min) != null ? _k : 0, max: (_l = fixed.max) != null ? _l : 100 }; return isValid(fallback) ? fallback : { min: 0, max: 100 }; } 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) { var _a, _b; if (((_a = scale == null ? void 0 : scale.min) == null ? void 0 : _a.entity) && ((_b = scale == null ? void 0 : scale.max) == null ? void 0 : _b.entity)) { const hasFixed = (bound) => { var _a2, _b2; return bound.fixed_explicit !== false && ((_a2 = bound.fixed) != null ? _a2 : bound.value) !== null && ((_b2 = bound.fixed) != null ? _b2 : bound.value) !== void 0; }; if (hasFixed(scale.min) !== hasFixed(scale.max)) { addWarning( diagnostics, "scale.orphan_fixed_fallback", "Both dynamic scale bounds require a complete fixed fallback pair. The single fixed fallback will not be used if the dynamic pair becomes unavailable.", `${path}.scale`, entity ); } } 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 validateExtremumReset(diagnostics, config, path, entity = null) { var _a; for (const marker of ["peak_marker", "floor_marker"]) { if ((_a = config == null ? void 0 : config[marker]) == null ? void 0 : _a.reset_invalid) { addWarning( diagnostics, `${marker}.invalid_reset`, "Invalid marker reset; using never.", `${path}.${marker}.reset`, entity ); } } } function validateMarkerDirections(diagnostics, config, path, entity = null) { var _a; for (const marker of ["target_marker", "peak_marker", "floor_marker"]) { if ((_a = config == null ? void 0 : config[marker]) == null ? void 0 : _a.direction_invalid) { addWarning( diagnostics, `${marker}.invalid_direction`, "Invalid marker direction; using inward.", `${path}.${marker === "target_marker" ? "target" : marker.replace("_marker", "")}.direction`, entity ); } } } function validateBuiltinMarkerLabels(diagnostics, config, path, entity = null) { var _a; for (const [key, publicKey] of [["target_marker", "target"], ["peak_marker", "peak"], ["floor_marker", "floor"]]) { const marker = config == null ? void 0 : config[key]; const labelPath = `${path}.${publicKey}.label`; if (marker == null ? void 0 : marker.label_invalid_show) addWarning(diagnostics, "markers.invalid_label_show", "Marker label show must be a boolean; using the existing fallback.", `${labelPath}.show`, entity); if (marker == null ? void 0 : marker.label_invalid_text) addWarning(diagnostics, "markers.invalid_label_text", "Marker label text must be a string; ignoring it.", `${labelPath}.text`, entity); if (marker == null ? void 0 : marker.label_invalid_show_value) addWarning(diagnostics, "markers.invalid_label_show_value", "Marker label show_value must be a boolean; using the inherited or default value.", `${labelPath}.show_value`, entity); if (marker == null ? void 0 : marker.label_invalid_show_unit) addWarning(diagnostics, "markers.invalid_label_show_unit", "Marker label show_unit must be a boolean; using the inherited or default value.", `${labelPath}.show_unit`, entity); if (marker == null ? void 0 : marker.label_invalid_precision) addWarning(diagnostics, "markers.invalid_label_precision", "Marker label precision must be a non-negative integer; using the inherited or row precision.", `${labelPath}.${(_a = marker.label_precision_key) != null ? _a : "precision"}`, entity); if (marker == null ? void 0 : marker.label_unsupported_unit) addWarning(diagnostics, "markers.unsupported_label_unit", "Marker label unit is no longer supported; use show_unit instead.", `${labelPath}.unit`, entity); } } function validateGenericMarkers(diagnostics, markers, invalidList, path, entity = null) { var _a, _b, _c, _d, _e, _f, _g, _h; if (invalidList) { addWarning(diagnostics, "markers.invalid_list", "Markers must be a list; ignoring the malformed value.", path, entity); } for (const marker of markers != null ? markers : []) { const markerPath = `${path}[${marker.index}]`; if (marker.malformed) { addWarning(diagnostics, "markers.invalid_item", "Marker must be an object; ignoring this item.", markerPath, entity); continue; } if (marker.invalidSource && !marker.invalidPercentage && !marker.unsupportedPercentField) { addWarning(diagnostics, "markers.invalid_source", "Marker requires a valid fixed value, percentage, or entity source.", `${markerPath}.at`, entity); } if (marker.invalidPercentage) { addWarning(diagnostics, "markers.invalid_percentage", "Marker percentage must be between 0 and 100 inclusive.", `${markerPath}.at`, entity); } if (marker.unsupportedPercentField) { addWarning(diagnostics, "markers.invalid_source", 'Use a percentage string such as "35%" instead of an at.percent field.', `${markerPath}.at`, entity); } if (marker.invalidLane) { addWarning(diagnostics, "markers.invalid_lane", "Marker lane must be above or below; ignoring this marker.", `${markerPath}.lane`, entity); } if (marker.invalidShape) { addWarning(diagnostics, "markers.invalid_shape", "Invalid marker shape; using circle.", `${markerPath}.shape`, entity); } if (marker.invalidDirection) { addWarning(diagnostics, "markers.invalid_direction", "Invalid marker direction; using inward.", `${markerPath}.direction`, entity); } if (marker.invalidShowMarker) addWarning(diagnostics, "markers.invalid_show_marker", "Marker show_marker must be a boolean; using true.", `${markerPath}.show_marker`, entity); if ((_a = marker.label) == null ? void 0 : _a.invalidEntity) addWarning(diagnostics, "markers.invalid_label_entity", "Marker label entity must be a valid entity ID; ignoring it.", `${markerPath}.label.entity`, entity); if ((_b = marker.label) == null ? void 0 : _b.invalidShow) addWarning(diagnostics, "markers.invalid_label_show", "Marker label show must be a boolean; using the existing fallback.", `${markerPath}.label.show`, entity); if ((_c = marker.label) == null ? void 0 : _c.invalidText) addWarning(diagnostics, "markers.invalid_label_text", "Marker label text must be a string; ignoring it.", `${markerPath}.label.text`, entity); if ((_d = marker.label) == null ? void 0 : _d.invalidShowValue) addWarning(diagnostics, "markers.invalid_label_show_value", "Marker label show_value must be a boolean; using the inherited or default value.", `${markerPath}.label.show_value`, entity); if ((_e = marker.label) == null ? void 0 : _e.invalidShowUnit) addWarning(diagnostics, "markers.invalid_label_show_unit", "Marker label show_unit must be a boolean; using the inherited or default value.", `${markerPath}.label.show_unit`, entity); if ((_f = marker.label) == null ? void 0 : _f.invalidPrecision) addWarning(diagnostics, "markers.invalid_label_precision", "Marker label precision must be a non-negative integer; using the inherited or row precision.", `${markerPath}.label.${(_g = marker.label.invalidPrecisionKey) != null ? _g : "precision"}`, entity); if ((_h = marker.label) == null ? void 0 : _h.unsupportedUnit) addWarning(diagnostics, "markers.unsupported_label_unit", "Marker label unit is no longer supported; use show_unit instead.", `${markerPath}.label.unit`, entity); if (marker.valid && !marker.accepted) { addWarning(diagnostics, "markers.excess_capacity", "This marker is not rendered because its lane already has four markers.", markerPath, 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 ((segment == null ? void 0 : segment.invalidBoundary) === "entity") { addWarning(diagnostics, "segments.unsupported_entity_boundary", "Entity-backed segment boundaries are not supported; ignoring this segment.", segmentPath, entity); continue; } if ((segment == null ? void 0 : segment.invalidBoundary) === "malformed_percent") { addWarning(diagnostics, "segments.invalid_percentage", "Malformed percentage segment boundary; ignoring this segment.", segmentPath, entity); continue; } if (segment == null ? void 0 : segment.invalidBoundary) { addWarning(diagnostics, "segments.invalid_boundary", 'Segment boundary must be a numeric value or a percentage such as "35%"; ignoring this segment.', segmentPath, entity); continue; } 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); validateExtremumReset(diagnostics, config, path, entity); validateMarkerDirections(diagnostics, config, path, entity); validateBuiltinMarkerLabels(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, _b; const diagnostics = { warnings: [], errors: [] }; if (!config || typeof config !== "object") { return diagnostics; } validateConfigScope(diagnostics, config, "card"); validateGenericMarkers(diagnostics, config.generic_markers, config.generic_markers_invalid, "markers"); 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); if (Object.prototype.hasOwnProperty.call(entityConfig, "markers")) { validateGenericMarkers( diagnostics, entityConfig.generic_markers, entityConfig.generic_markers_invalid, `${path}.markers`, entityId ); } else { const inheritedOverflow = ((_b = entityConfig.generic_markers) != null ? _b : []).filter( (marker) => { var _a2, _b2; return marker.valid && !marker.accepted && ((_b2 = (_a2 = config.generic_markers) == null ? void 0 : _a2[marker.index]) == null ? void 0 : _b2.accepted) === true; } ); if (inheritedOverflow.length) { validateGenericMarkers(diagnostics, inheritedOverflow, false, `${path}.markers`, entityId); } } } return diagnostics; } var init_validate = __esm({ "src/config/validate.js"() { init_normalize(); } }); // src/utils/format.js function formatNumericDisplay(rawVal, decimal = null) { if (!Number.isFinite(rawVal)) return String(rawVal); if (decimal !== null) { return rawVal.toLocaleString(void 0, { minimumFractionDigits: decimal, maximumFractionDigits: decimal }); } 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 createNumericPresentation(value, unit, decimal = null) { const number = formatNumericDisplay(value, decimal); const cleanUnit = unit ? String(unit) : ""; return { value, number, unit: cleanUnit, text: formatDisplayWithUnit(number, cleanUnit) }; } function createMarkerLabelPresentation(value, unit, precision = null, options = {}) { const semanticText = typeof options.text === "string" ? options.text : ""; const number = options.showValue === false || value === null || value === void 0 || value === "" ? "" : Number.isFinite(value) ? formatNumericDisplay(value, precision) : String(value); const cleanUnit = options.showUnit === false ? "" : String(unit != null ? unit : "").trim(); const text = [semanticText, number, cleanUnit].filter(Boolean).join(" "); return { value: Number.isFinite(value) ? value : null, semanticText, number, unit: cleanUnit, showValue: options.showValue !== false, showUnit: options.showUnit !== false, text }; } function createTextPresentation(text) { const value = String(text); return { value: null, number: value, unit: "", text: value }; } var init_format = __esm({ "src/utils/format.js"() { } }); // src/view-model/marker-view-model.js function hasConfiguredSource(source) { if (!source) return false; return source.entity !== null && source.entity !== void 0 && source.entity !== "" || source.fixed !== null && source.fixed !== void 0 && source.fixed !== "" || Number.isFinite(source.percent); } function normalizeMarkerShape(value, fallback = "circle") { return MARKER_SHAPES.has(value) ? value : fallback; } function createMarkerModel({ id, type, value = null, position = null, lane, visible = false, color = null, label = null, labelVisible = false, shape = "circle", direction = "inward", showMarker = true }) { return { id, type, value, position, lane, visible: visible === true, color, label, labelVisible: labelVisible === true, shape: normalizeMarkerShape(shape), direction, showMarker: showMarker !== false }; } function hasMarkerLabelContent(label) { return !!(typeof (label == null ? void 0 : label.text) === "string" && label.text.trim()) || (label == null ? void 0 : label.showValue) !== false || (label == null ? void 0 : label.showUnit) !== false; } function getMarkerLaneOccupancy(entityConfig) { var _a; const targetConfig = entityConfig == null ? void 0 : entityConfig.target_marker; const peakConfig = entityConfig == null ? void 0 : entityConfig.peak_marker; const floorConfig = entityConfig == null ? void 0 : entityConfig.floor_marker; const genericMarkers = ((_a = entityConfig == null ? void 0 : entityConfig.generic_markers) != null ? _a : []).filter((marker) => marker.accepted); return { below: (targetConfig == null ? void 0 : targetConfig.enabled) !== false && hasConfiguredSource(targetConfig == null ? void 0 : targetConfig.source) || (floorConfig == null ? void 0 : floorConfig.show) === true || genericMarkers.some((marker) => marker.lane === "below"), above: (peakConfig == null ? void 0 : peakConfig.show) === true || genericMarkers.some((marker) => marker.lane === "above") }; } function getMarkerLabelLaneOccupancy(entityConfig) { var _a; const targetConfig = entityConfig == null ? void 0 : entityConfig.target_marker; const peakConfig = entityConfig == null ? void 0 : entityConfig.peak_marker; const floorConfig = entityConfig == null ? void 0 : entityConfig.floor_marker; const genericMarkers = ((_a = entityConfig == null ? void 0 : entityConfig.generic_markers) != null ? _a : []).filter((marker) => marker.accepted); return { below: (targetConfig == null ? void 0 : targetConfig.enabled) !== false && hasConfiguredSource(targetConfig == null ? void 0 : targetConfig.source) && (targetConfig == null ? void 0 : targetConfig.show_label) === true && hasMarkerLabelContent({ text: targetConfig.label_text, showValue: targetConfig.label_show_value, showUnit: targetConfig.label_show_unit }) || (floorConfig == null ? void 0 : floorConfig.show) === true && (floorConfig == null ? void 0 : floorConfig.show_label) === true && hasMarkerLabelContent({ text: floorConfig.label_text, showValue: floorConfig.label_show_value, showUnit: floorConfig.label_show_unit }) || genericMarkers.some((marker) => { var _a2; return marker.lane === "below" && ((_a2 = marker.label) == null ? void 0 : _a2.show) === true && hasMarkerLabelContent(marker.label); }), above: (peakConfig == null ? void 0 : peakConfig.show) === true && (peakConfig == null ? void 0 : peakConfig.show_label) === true && hasMarkerLabelContent({ text: peakConfig.label_text, showValue: peakConfig.label_show_value, showUnit: peakConfig.label_show_unit }) || genericMarkers.some((marker) => { var _a2; return marker.lane === "above" && ((_a2 = marker.label) == null ? void 0 : _a2.show) === true && hasMarkerLabelContent(marker.label); }) }; } function buildMarkerModels({ entityConfig, targetValue = null, targetPosition = null, targetPresentation = null, targetLabelPresentation = null, targetVisible = Number.isFinite(targetPosition), peakValue = null, peakPosition = null, peakPresentation = null, peakLabelPresentation = null, peakVisible = Number.isFinite(peakPosition), floorValue = null, floorPosition = null, floorPresentation = null, floorLabelPresentation = null, floorVisible = Number.isFinite(floorPosition), genericMarkers = [] }) { var _a, _b, _c, _d, _e, _f, _g; const targetConfig = entityConfig == null ? void 0 : entityConfig.target_marker; const peakConfig = entityConfig == null ? void 0 : entityConfig.peak_marker; const floorConfig = entityConfig == null ? void 0 : entityConfig.floor_marker; const targetEnabled = (targetConfig == null ? void 0 : targetConfig.enabled) !== false; return [ createMarkerModel({ id: "target", type: "target", value: targetValue, position: targetPosition, lane: "below", visible: targetEnabled && targetVisible, color: (_a = targetConfig == null ? void 0 : targetConfig.color) != null ? _a : null, label: targetLabelPresentation != null ? targetLabelPresentation : targetPresentation, labelVisible: targetEnabled && (targetConfig == null ? void 0 : targetConfig.show_label) === true && hasMarkerLabelContent({ text: targetConfig.label_text, showValue: targetConfig.label_show_value, showUnit: targetConfig.label_show_unit }), shape: (_b = targetConfig == null ? void 0 : targetConfig.shape) != null ? _b : "diamond", direction: (_c = targetConfig == null ? void 0 : targetConfig.direction) != null ? _c : "inward" }), createMarkerModel({ id: "floor", type: "floor", value: floorValue, position: floorPosition, lane: "below", visible: (floorConfig == null ? void 0 : floorConfig.show) === true && floorVisible, color: (_d = floorConfig == null ? void 0 : floorConfig.color) != null ? _d : null, label: floorLabelPresentation != null ? floorLabelPresentation : floorPresentation, labelVisible: (floorConfig == null ? void 0 : floorConfig.show) === true && (floorConfig == null ? void 0 : floorConfig.show_label) === true && hasMarkerLabelContent({ text: floorConfig.label_text, showValue: floorConfig.label_show_value, showUnit: floorConfig.label_show_unit }), shape: "triangle", direction: (_e = floorConfig == null ? void 0 : floorConfig.direction) != null ? _e : "inward" }), createMarkerModel({ id: "peak", type: "peak", value: peakValue, position: peakPosition, lane: "above", visible: (peakConfig == null ? void 0 : peakConfig.show) === true && peakVisible, color: (_f = peakConfig == null ? void 0 : peakConfig.color) != null ? _f : null, label: peakLabelPresentation != null ? peakLabelPresentation : peakPresentation, labelVisible: (peakConfig == null ? void 0 : peakConfig.show) === true && (peakConfig == null ? void 0 : peakConfig.show_label) === true && hasMarkerLabelContent({ text: peakConfig.label_text, showValue: peakConfig.label_show_value, showUnit: peakConfig.label_show_unit }), shape: "triangle", direction: (_g = peakConfig == null ? void 0 : peakConfig.direction) != null ? _g : "inward" }), ...genericMarkers.map((marker) => createMarkerModel({ id: marker.id, type: "generic", value: marker.value, position: marker.position, lane: marker.lane, visible: marker.visible, color: marker.color, label: marker.label, labelVisible: marker.labelVisible && hasMarkerLabelContent(marker.label), shape: marker.shape, direction: marker.direction, showMarker: marker.showMarker })) ]; } var MARKER_SHAPES; var init_marker_view_model = __esm({ "src/view-model/marker-view-model.js"() { MARKER_SHAPES = /* @__PURE__ */ new Set(["circle", "diamond", "triangle", "chevron", "arrow", "pin"]); } }); // 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 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 getExtremumState(numericValue, minValue, maxValue, tracker, direction, enabled) { if (!enabled) { return { value: null, percent: null, display: null, visible: false }; } const existingValue = getFiniteNumber(tracker == null ? void 0 : tracker.value); if (!Number.isFinite(existingValue) && !Number.isFinite(numericValue)) { return { value: null, percent: null, visible: false }; } const value = Number.isFinite(existingValue) ? Number.isFinite(numericValue) ? direction === "min" ? Math.min(existingValue, numericValue) : Math.max(existingValue, numericValue) : existingValue : numericValue; return { value, percent: toScalePct(value, 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, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha; const { hass, cardConfig, entityConfig, entityState, peaks, extrema, previousScale } = 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 configuredUnit = (_e = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _e.unit; const targetUnit = (_f = configuredUnit != null ? configuredUnit : rawUnit) != null ? _f : ""; const displayUnit = numericValue !== null ? targetUnit : ""; const { min: safeMin, max: safeMax } = getResolvedScale(hass, entityConfig == null ? void 0 : entityConfig.scale, previousScale); const percent = numericValue !== null ? toScalePct(numericValue, safeMin, safeMax) : 0; const decimal = (_h = (_g = entityConfig == null ? void 0 : entityConfig.formatting) == null ? void 0 : _g.decimal) != null ? _h : null; const primaryPresentation = numericValue === null ? createTextPresentation(rawState) : createNumericPresentation(numericValue, displayUnit, decimal); const targetValue = ((_i = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _i.enabled) === false ? null : getNormalizedResolvableNumericValue(hass, (_j = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _j.source, safeMin, safeMax); const targetPercent = targetValue !== null ? toScalePct(targetValue, safeMin, safeMax) : null; const targetVisible = targetValue !== null; const targetDecimal = (_l = (_k = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _k.label_decimal) != null ? _l : decimal; const targetPresentation = targetValue !== null ? createNumericPresentation(targetValue, targetUnit, targetDecimal) : null; const targetLabelPresentation = targetValue !== null ? createMarkerLabelPresentation(targetValue, targetUnit, (_n = (_m = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _m.label_precision) != null ? _n : targetDecimal, { text: (_o = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _o.label_text, showValue: (_p = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _p.label_show_value, showUnit: (_q = entityConfig == null ? void 0 : entityConfig.target_marker) == null ? void 0 : _q.label_show_unit }) : null; const baselineValue = ((_r = entityConfig == null ? void 0 : entityConfig.baseline) == null ? void 0 : _r.enabled) === false ? null : getNormalizedResolvableNumericValue(hass, (_s = entityConfig == null ? void 0 : entityConfig.baseline) == null ? void 0 : _s.at, safeMin, safeMax); const baselinePercent = Number.isFinite(baselineValue) ? toScalePct(baselineValue, safeMin, safeMax) : null; const baselineVisible = Number.isFinite(baselineValue); const legacyPeak = Number.isFinite(getFiniteNumber(peaks == null ? void 0 : peaks[entityId])) ? { value: getFiniteNumber(peaks == null ? void 0 : peaks[entityId]) } : null; const peakState = getExtremumState( numericValue, safeMin, safeMax, (_t = extrema == null ? void 0 : extrema.peak) != null ? _t : legacyPeak, "max", ((_u = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _u.show) === true ); const floorState = getExtremumState( numericValue, safeMin, safeMax, extrema == null ? void 0 : extrema.floor, "min", ((_v = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _v.show) === true ); const peakDecimal = (_x = (_w = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _w.label_decimal) != null ? _x : decimal; const floorDecimal = (_z = (_y = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _y.label_decimal) != null ? _z : decimal; const peakLabelPrecision = (_B = (_A = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _A.label_precision) != null ? _B : peakDecimal; const floorLabelPrecision = (_D = (_C = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _C.label_precision) != null ? _D : floorDecimal; const peakPresentation = peakState.visible ? createNumericPresentation(peakState.value, targetUnit, peakDecimal) : null; const floorPresentation = floorState.visible ? createNumericPresentation(floorState.value, targetUnit, floorDecimal) : null; const peakLabelPresentation = peakState.visible ? createMarkerLabelPresentation(peakState.value, targetUnit, peakLabelPrecision, { text: (_E = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _E.label_text, showValue: (_F = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _F.label_show_value, showUnit: (_G = entityConfig == null ? void 0 : entityConfig.peak_marker) == null ? void 0 : _G.label_show_unit }) : null; const floorLabelPresentation = floorState.visible ? createMarkerLabelPresentation(floorState.value, targetUnit, floorLabelPrecision, { text: (_H = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _H.label_text, showValue: (_I = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _I.label_show_value, showUnit: (_J = entityConfig == null ? void 0 : entityConfig.floor_marker) == null ? void 0 : _J.label_show_unit }) : null; const genericMarkers = ((_K = entityConfig == null ? void 0 : entityConfig.generic_markers) != null ? _K : []).filter((marker) => marker.accepted).map((marker) => { var _a2, _b2, _c2, _d2, _e2; const value = getNormalizedResolvableNumericValue(hass, marker.source, safeMin, safeMax); const visible = Number.isFinite(value); const markerPrecision = (_a2 = marker.label.precision) != null ? _a2 : decimal; const labelStateObj = marker.label.entity ? (_b2 = hass == null ? void 0 : hass.states) == null ? void 0 : _b2[marker.label.entity] : null; const rawLabelState = labelStateObj == null ? void 0 : labelStateObj.state; const cleanLabelState = typeof rawLabelState === "string" ? rawLabelState.trim() : ""; const usableLabelState = labelStateObj && cleanLabelState && !["unknown", "unavailable"].includes(cleanLabelState.toLowerCase()); const labelValue = marker.label.entity ? usableLabelState ? (_c2 = getFiniteNumber(cleanLabelState)) != null ? _c2 : cleanLabelState : null : value; const labelUnit = marker.label.entity ? usableLabelState ? (_e2 = (_d2 = labelStateObj == null ? void 0 : labelStateObj.attributes) == null ? void 0 : _d2.unit_of_measurement) != null ? _e2 : "" : "" : targetUnit; const label = marker.label.show ? createMarkerLabelPresentation(labelValue, labelUnit, markerPrecision, { text: marker.label.text, showValue: marker.label.showValue, showUnit: marker.label.showUnit }) : null; return { id: marker.id, value, position: visible ? toScalePct(value, safeMin, safeMax) : null, lane: marker.lane, visible, color: marker.color, shape: marker.shape, direction: marker.direction, showMarker: marker.showMarker, label, labelVisible: marker.label.show }; }); const markers = buildMarkerModels({ entityConfig, targetValue, targetPosition: targetPercent, targetPresentation, targetLabelPresentation, targetVisible, peakValue: peakState.value, peakPosition: peakState.percent, peakPresentation, peakLabelPresentation, peakVisible: peakState.visible, floorValue: floorState.value, floorPosition: floorState.percent, floorPresentation, floorLabelPresentation, floorVisible: floorState.visible, genericMarkers }); return { entityId, name: (_N = (_M = entityConfig == null ? void 0 : entityConfig.name) != null ? _M : (_L = entityState == null ? void 0 : entityState.attributes) == null ? void 0 : _L.friendly_name) != null ? _N : entityId, icon: (entityConfig == null ? void 0 : entityConfig.icon) === false ? false : (_Q = (_P = entityConfig == null ? void 0 : entityConfig.icon) != null ? _P : (_O = entityState == null ? void 0 : entityState.attributes) == null ? void 0 : _O.icon) != null ? _Q : getDefaultEntityIcon(entityState, entityId), state: rawState, numericValue, rawUnit, min: safeMin, max: safeMax, percent, displayValue: primaryPresentation.number, displayUnit: primaryPresentation.unit, primaryPresentation, unit: primaryPresentation.unit, barColor: (_S = (_R = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _R.color) != null ? _S : null, fillStyle: (_U = (_T = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _T.fill_style) != null ? _U : null, target: targetValue, targetPercent, targetDisplay: (_V = targetPresentation == null ? void 0 : targetPresentation.text) != null ? _V : null, targetPresentation, targetLabelPresentation, targetVisible, baseline: baselineValue, baselinePercent, baselineVisible, peak: peakState.value, peakPercent: peakState.percent, peakDisplay: (_W = peakPresentation == null ? void 0 : peakPresentation.number) != null ? _W : null, peakPresentation, peakLabelPresentation, peakVisible: peakState.visible, floor: floorState.value, floorPercent: floorState.percent, floorDisplay: (_X = floorPresentation == null ? void 0 : floorPresentation.number) != null ? _X : null, floorPresentation, floorLabelPresentation, floorVisible: floorState.visible, markers, markerLaneOccupancy: getMarkerLaneOccupancy(entityConfig), markerLabelLaneOccupancy: getMarkerLabelLaneOccupancy(entityConfig), segments: (_Z = (_Y = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _Y.segments) != null ? _Z : null, gradientStops: (_$ = (__ = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : __.gradient_stops) != null ? _$ : null, needle: getNeedleState(entityConfig, numericValue, safeMin, safeMax, baselinePercent), classes: { labelPosition: (_ca = (_ba = (_aa = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _aa.label) == null ? void 0 : _ba.position) != null ? _ca : "left", animated: ((_da = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _da.animated) !== false }, attributes: { entity: entityId, baseHeight: (_fa = (_ea = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _ea.height) != null ? _fa : 38, heightExplicit: ((_ga = entityConfig == null ? void 0 : entityConfig.layout) == null ? void 0 : _ga.height_explicit) === true, barAnimated: ((_ha = entityConfig == null ? void 0 : entityConfig.bar) == null ? void 0 : _ha.animated) !== false } }; } var init_row_view_model = __esm({ "src/view-model/row-view-model.js"() { init_resolve(); init_normalize(); init_format(); init_marker_view_model(); } }); // 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 function getRevealTransitionDuration(previousGeometry, nextGeometry) { if (!previousGeometry || !nextGeometry || !Number.isFinite(previousGeometry.valuePercent) || !Number.isFinite(nextGeometry.valuePercent)) { return 600; } const previousBaseline = Number.isFinite(previousGeometry.baselinePercent) ? previousGeometry.baselinePercent : 0; const nextBaseline = Number.isFinite(nextGeometry.baselinePercent) ? nextGeometry.baselinePercent : 0; const delta = Math.max( Math.abs(nextGeometry.valuePercent - previousGeometry.valuePercent), Math.abs(nextBaseline - previousBaseline) ); const ordinaryDuration = Math.round(Math.min(600, Math.max(150, 600 - 15 * Math.max(0, delta - 5)))); const crossesBaseline = Number.isFinite(previousGeometry.baselinePercent) && Number.isFinite(nextGeometry.baselinePercent) && (previousGeometry.valuePercent - previousGeometry.baselinePercent) * (nextGeometry.valuePercent - nextGeometry.baselinePercent) < 0; return crossesBaseline ? Math.min(ordinaryDuration, 300) : ordinaryDuration; } var SensorBarCard; var init_SensorBarCard = __esm({ "src/card/SensorBarCard.js"() { init_normalize(); init_resolve(); init_validate(); init_row_view_model(); init_marker_view_model(); init_dom(); init_format(); init_extrema(); 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._extrema = /* @__PURE__ */ new WeakMap(); this._rowScales = /* @__PURE__ */ new WeakMap(); this._rowGeneration = 0; this._rowPresence = []; this._leftModeResponsiveHistory = /* @__PURE__ */ new WeakMap(); this._rendered = false; this._resizeObserver = null; this._densityPassScheduled = false; this._densityPassDirty = false; this._densityPassFrame = null; this._densityPassRetries = 0; this._boundWindowResize = () => this._schedulePostLayoutDensityPass(); this._markerHover = null; this._boundMarkerPointerOver = (event) => this._handleMarkerPointerOver(event); this._boundMarkerPointerOut = (event) => this._handleMarkerPointerOut(event); this._ensureBaseDom(); } connectedCallback() { window.addEventListener("resize", this._boundWindowResize, { passive: true }); this._setupResizeObserver(); this._schedulePostLayoutDensityPass(); } disconnectedCallback() { this._rowGeneration += 1; window.removeEventListener("resize", this._boundWindowResize); this._clearMarkerHover(); this._disconnectResizeObserver(); if (this._densityPassFrame) { cancelAnimationFrame(this._densityPassFrame); this._densityPassFrame = null; } this._densityPassScheduled = false; this._densityPassDirty = false; } setConfig(config) { var _a; if (!config.entities && !config.entity) { throw new Error("You must define entities or entity"); } this._rendered = false; this._rowGeneration += 1; const previousConfig = this._config; this._config = this.normalizeCardConfig(config); this._rowScales = /* @__PURE__ */ new WeakMap(); this._reconcileRowHistory((_a = previousConfig == null ? void 0 : previousConfig.entities) != null ? _a : []); this._diagnostics = validateNormalizedConfig(this._config); this._logDiagnostics(); this._render(); } _reconcileRowHistory(previousRows) { var _a, _b, _c, _d; const canonical = (value, key = "") => { if (Array.isArray(value)) return value.map(canonical); if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().filter((name) => !["severity", "segment_space", "label_precision_key"].includes(name)).map((name) => [name, canonical(value[name], name)])); if (key === "fixed") return getNumericValue(null, value); if (/color/i.test(key) && typeof value === "string" && /^#(?:[\da-f]{3}|[\da-f]{6})$/i.test(value.trim())) { const hex = value.trim().slice(1).toLowerCase(); return `#${hex.length === 3 ? hex.split("").map((char) => char + char).join("") : hex}`; } return value; }; const signature = (row) => { var _a2; return JSON.stringify(canonical({ entity: row.entity, name: row.name, icon: (_a2 = row.icon) != null ? _a2 : null, layout: row.layout, scale: Object.fromEntries(["min", "max"].map((key) => [key, { ...row.scale[key], fixed_explicit: row.scale[key].fixed_explicit !== false }])), bar: row.bar, baseline: row.baseline, formatting: row.formatting, target_marker: row.target_marker, peak_marker: row.peak_marker, floor_marker: row.floor_marker, generic_markers: row.generic_markers })); }; const unmatchedOld = new Set(previousRows); const matches = /* @__PURE__ */ new Map(); const oldSignatures = new Map(previousRows.map((row) => [row, signature(row)])); for (const row of this._config.entities) { const key = signature(row); const previous = [...unmatchedOld].find((old) => oldSignatures.get(old) === key); if (!previous) continue; matches.set(row, previous); unmatchedOld.delete(previous); } const unmatchedNew = this._config.entities.filter((row) => !matches.has(row)); for (const row of unmatchedNew) { const old = [...unmatchedOld].filter((previous) => previous.entity === row.entity); const next = unmatchedNew.filter((current) => current.entity === row.entity); if (old.length !== 1 || next.length !== 1) continue; matches.set(row, old[0]); unmatchedOld.delete(old[0]); } const extrema = /* @__PURE__ */ new WeakMap(); const responsive = /* @__PURE__ */ new WeakMap(); for (const [row, previous] of matches) { const stored = this._extrema.get(previous); const retained = {}; for (const key of ["peak", "floor"]) { const before = previous[`${key}_marker`]; const after = row[`${key}_marker`]; if ((stored == null ? void 0 : stored[key]) && (before == null ? void 0 : before.show) === true && (after == null ? void 0 : after.show) === true && JSON.stringify(before.reset) === JSON.stringify(after.reset)) { retained[key] = { ...stored[key] }; } } if (retained.peak || retained.floor) extrema.set(row, retained); if (((_b = (_a = previous.layout) == null ? void 0 : _a.label) == null ? void 0 : _b.position) === "left" && ((_d = (_c = row.layout) == null ? void 0 : _c.label) == null ? void 0 : _d.position) === "left" && this._leftModeResponsiveHistory.has(previous)) { responsive.set(row, this._leftModeResponsiveHistory.get(previous)); } } this._extrema = extrema; this._leftModeResponsiveHistory = responsive; } _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 (!this._config.entities) return; if (!oldHass) { this._update(); return; } if (this._shouldUpdate(oldHass, hass)) { this._update(oldHass); } } // 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 }; } _getStateTimestamp(stateObj) { var _a; const rawTimestamp = (_a = stateObj == null ? void 0 : stateObj.last_updated) != null ? _a : stateObj == null ? void 0 : stateObj.last_changed; const timestamp = rawTimestamp instanceof Date ? rawTimestamp.getTime() : Date.parse(String(rawTimestamp != null ? rawTimestamp : "")); return Number.isFinite(timestamp) ? timestamp : Date.now(); } _updateExtrema(entityCfg, normalizedEntity, stateObj) { var _a, _b, _c; const sample = getFiniteNumber(stateObj == null ? void 0 : stateObj.state); if (!Number.isFinite(sample)) return; const current = (_a = this._extrema.get(entityCfg)) != null ? _a : {}; const timestamp = this._getStateTimestamp(stateObj); for (const key of ["peak", "floor"]) { const marker = normalizedEntity == null ? void 0 : normalizedEntity[`${key}_marker`]; if ((marker == null ? void 0 : marker.show) !== true) { delete current[key]; continue; } current[key] = updateExtremum( (_b = current[key]) != null ? _b : null, sample, (_c = marker.reset) != null ? _c : { kind: "never" }, key === "floor" ? "min" : "max", timestamp ); } if (current.peak || current.floor) { this._extrema.set(entityCfg, current); } else { this._extrema.delete(entityCfg); } } _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, _k; 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, ...((_i = ecfg.generic_markers) != null ? _i : []).filter((marker) => marker.accepted).flatMap((marker) => { var _a2, _b2; return [(_a2 = marker.source) == null ? void 0 : _a2.entity, (_b2 = marker.label) == null ? void 0 : _b2.entity]; }) ].filter(Boolean); for (const ent of entitiesToWatch) { const oldState = (_j = oldHass.states[ent]) != null ? _j : null; const newState = (_k = newHass.states[ent]) != null ? _k : 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); this._positionMarkerValueLabel(row, ".peak-value-label", ".peak-marker"); this._positionMarkerValueLabel(row, ".floor-value-label", ".floor-marker"); this._positionGenericMarkerLabels(row); }); } _positionGenericMarkerLabels(row) { var _a, _b; ((_b = (_a = row.querySelectorAll) == null ? void 0 : _a.call(row, ".generic-value-label[data-marker-id]")) != null ? _b : []).forEach((label) => { const id = label.dataset.markerId; this._positionMarkerValueLabel( row, `.generic-value-label[data-marker-id="${id}"]`, `.generic-marker[data-marker-id="${id}"]` ); }); } _positionTargetLabel(row) { this._positionMarkerValueLabel(row, ".target-value-label", ".target-marker"); } _getMarkerLabel(markerEl) { var _a; const row = markerEl == null ? void 0 : markerEl.closest(".row"); if (!row) return null; if (markerEl.matches(".generic-marker[data-marker-id]")) { const markerId = markerEl.dataset.markerId; return (_a = [...row.querySelectorAll(".generic-value-label[data-marker-id]")].find((label) => label.dataset.markerId === markerId)) != null ? _a : null; } const labelSelector = markerEl.matches(".target-marker") ? ".target-value-label" : markerEl.matches(".peak-marker") ? ".peak-value-label" : markerEl.matches(".floor-marker") ? ".floor-value-label" : null; return labelSelector ? row.querySelector(labelSelector) : null; } _getGenericMarkerForLabel(labelEl) { var _a, _b; const row = labelEl == null ? void 0 : labelEl.closest(".row"); const markerId = (_a = labelEl == null ? void 0 : labelEl.dataset) == null ? void 0 : _a.markerId; if (!row || !markerId) return null; return (_b = [...row.querySelectorAll(".generic-marker[data-marker-id]")].find((marker) => marker.dataset.markerId === markerId)) != null ? _b : null; } _setMarkerHover(markerEl) { var _a; const label = this._getMarkerLabel(markerEl); if (!label || markerEl.style.display === "none" || getComputedStyle(label).visibility !== "visible") { this._clearMarkerHover(markerEl); return; } if (((_a = this._markerHover) == null ? void 0 : _a.label) === label) return; this._clearMarkerHover(); label.dataset.markerHovered = "true"; this._markerHover = { marker: markerEl, label }; } _clearMarkerHover(markerEl = null) { if (!this._markerHover || markerEl && this._markerHover.marker !== markerEl) return; delete this._markerHover.label.dataset.markerHovered; this._markerHover = null; } _handleMarkerPointerOver(event) { var _a, _b, _c; if (event.pointerType === "touch") return; const target = (_b = (_a = event.target) == null ? void 0 : _a.closest) == null ? void 0 : _b.call(_a, '.generic-value-label[data-show-marker="false"], .generic-marker, .target-marker, .peak-marker, .floor-marker'); const markerEl = ((_c = target == null ? void 0 : target.matches) == null ? void 0 : _c.call(target, ".generic-value-label")) ? this._getGenericMarkerForLabel(target) : target; if (markerEl) this._setMarkerHover(markerEl); } _handleMarkerPointerOut(event) { var _a, _b; if (event.pointerType === "touch") return; const target = (_b = (_a = event.target) == null ? void 0 : _a.closest) == null ? void 0 : _b.call(_a, '.generic-value-label[data-show-marker="false"], .generic-marker, .target-marker, .peak-marker, .floor-marker'); if (!target || target.contains(event.relatedTarget)) return; const markerEl = target.matches(".generic-value-label") ? this._getGenericMarkerForLabel(target) : target; if (!markerEl) return; this._clearMarkerHover(markerEl); } _positionMarkerValueLabel(row, labelSelector, markerSelector) { const track = row.querySelector(".bar-track"); const label = row.querySelector(labelSelector); const marker = row.querySelector(markerSelector); 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 : []).filter((segment) => !(segment == null ? void 0 : segment.invalidBoundary)); 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)); } _getRevealTransitionDuration(previousGeometry, nextGeometry) { return getRevealTransitionDuration(previousGeometry, nextGeometry); } _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) { return formatNumericDisplay(rawVal, decimal); } _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.shadowRoot.addEventListener("pointerover", this._boundMarkerPointerOver); this.shadowRoot.addEventListener("pointerout", this._boundMarkerPointerOut); 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._setupResizeObserver(); this._update(); this._schedulePostLayoutDensityPass(); } _setupResizeObserver() { if (!this.isConnected || this._resizeObserver) return; const surface = this.shadowRoot.querySelector("ha-card"); const card = this.shadowRoot.querySelector(".card"); if (!surface || !card) return; const observer = new ResizeObserver(() => { if (!this.isConnected || this._resizeObserver !== observer) return; this._applyCompactTier(); this._schedulePostLayoutDensityPass(); }); this._resizeObserver = observer; this._applyCompactTier(); observer.observe(surface); observer.observe(this); } _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", naturalLabelWidth = Number.POSITIVE_INFINITY) { if (!this._isReliableWidth(width)) return currentDensity || "normal"; const densities = ["normal", "compact", "tight", "dense", "compressed"]; let density = "normal"; if (width < 170) density = "compressed"; else if (width < 210) density = "dense"; else if (width < 255) density = "tight"; else if (width < 320) density = "compact"; const currentIndex = densities.indexOf(density); const relaxBy = Number.isFinite(naturalLabelWidth) ? naturalLabelWidth <= 44 && width >= 205 ? 2 : naturalLabelWidth <= 72 && width >= 185 ? 1 : 0 : 0; return densities[Math.max(0, currentIndex - relaxBy)]; } _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; 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; } const labelText = mainLine.querySelector(".label-left-text"); const text = ((labelText == null ? void 0 : labelText.textContent) || "").trim(); const naturalLabelWidth = labelText ? this._measureTextWidthWithStyles(labelText, text) || labelText.scrollWidth : Number.POSITIVE_INFINITY; const density = this._classifyLeftDensity(width, mainLine.dataset.leftDensity, naturalLabelWidth); 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 display = this._decodeDataAttr(valueEl.dataset.display || valueEl.textContent || ""); const unit = this._decodeDataAttr(valueEl.dataset.unit || ""); valueEl.dataset.valueFit = "normal"; innerLabel.dataset.valueFit = "normal"; const fullWidth = this._measureInsideValueMarkupWidth(valueEl, display, unit, false); const numberWidth = this._measureInsideValueMarkupWidth(valueEl, display, unit, true); const rowWidth = (_b = (_a = mainLine == null ? void 0 : mainLine.getBoundingClientRect) == null ? void 0 : _a.call(mainLine).width) != null ? _b : 0; const rowDensity = this._isReliableWidth(rowWidth) ? this._classifyRowDensity(rowWidth, (_c = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _c.rowDensity) : ((_d = mainLine == null ? void 0 : mainLine.dataset) == null ? void 0 : _d.rowDensity) || "normal"; const iconWrap = (_f = (_e = mainLine == null ? void 0 : mainLine.querySelector) == null ? void 0 : _e.call(mainLine, ".icon-wrap")) != null ? _f : null; const iconReserve = iconWrap ? this._getLeftModeIconWidth(iconWrap, mainLine) + this._getLeftModeGap(mainLine) : 0; const minimum = this._getLeftModeBarMinWidth(mainLine); const withIconWidth = this._isReliableWidth(rowWidth) ? Math.max(minimum, rowWidth - iconReserve) : track.getBoundingClientRect().width; const withoutIconWidth = this._isReliableWidth(rowWidth) ? Math.max(minimum, rowWidth) : withIconWidth + iconReserve; const nameText = (nameEl.textContent || "").trim(); const nameWidth = this._measureTextWidthWithStyles(nameEl, nameText) || nameEl.scrollWidth; const candidate = (trackWidth) => { const density = rowDensity === "compressed" ? "compressed" : this._classifyInsideDensity(trackWidth, fullWidth); innerLabel.dataset.insideDensity = density; innerLabel.dataset.valueFit = "normal"; valueEl.dataset.valueFit = "normal"; const padding = this._getNumericStyleValue(innerLabel, "padding-left", 0) + this._getNumericStyleValue(innerLabel, "padding-right", 0); let cap = Math.max(0, trackWidth - padding); const hideUnit = !!unit && fullWidth > cap; let readingWidth = hideUnit ? numberWidth : fullWidth; let valueFit = "normal"; if (readingWidth > cap) { valueFit = "compact"; innerLabel.dataset.valueFit = valueFit; valueEl.dataset.valueFit = valueFit; cap = Math.max(0, trackWidth - this._getNumericStyleValue(innerLabel, "padding-left", 0) - this._getNumericStyleValue(innerLabel, "padding-right", 0)); readingWidth = this._measureInsideValueMarkupWidth(valueEl, display, unit, true); } const hideValue = readingWidth > cap; const gap = hideValue ? 0 : this._getNumericStyleValue(innerLabel, "gap", 0); const nameShare = density === "compact" ? 0.56 : density === "tight" ? 0.48 : 0.6; const availableNameWidth = Math.max( 0, Math.min(cap * nameShare, cap - (hideValue ? 0 : Math.ceil(readingWidth)) - gap) ); let hideName = density === "dense" || density === "compressed"; if (nameText && nameWidth > 0) { const usefulWidth = this._getInsideUsefulNameWidth(nameEl, nameText, nameWidth); const visibleChars = this._measureVisibleLabelCharacters(nameEl, nameText, availableNameWidth); hideName = availableNameWidth < usefulWidth || nameWidth > availableNameWidth + 1 && visibleChars < Math.min(4, nameText.length); } return { density, valueFit, hideUnit, hideValue, hideName, rank: hideValue ? 3 : valueFit === "compact" ? 2 : hideUnit ? 1 : 0 }; }; let hideIcon = rowDensity === "dense" || rowDensity === "compressed"; let chosen = candidate(hideIcon ? withoutIconWidth : withIconWidth); if (iconWrap && !hideIcon) { const withoutIcon = candidate(withoutIconWidth); if (withoutIcon.rank < chosen.rank || withoutIcon.rank === chosen.rank && chosen.hideName && !withoutIcon.hideName) { hideIcon = true; chosen = withoutIcon; } } innerLabel.dataset.insideDensity = chosen.density; innerLabel.dataset.valueFit = chosen.valueFit; innerLabel.dataset.hideName = chosen.hideName ? "true" : "false"; valueEl.dataset.valueFit = chosen.valueFit; valueEl.dataset.hideUnit = chosen.hideUnit ? "true" : "false"; valueEl.dataset.hideValue = chosen.hideValue ? "true" : "false"; if (mainLine) mainLine.dataset.hideInsideIcon = hideIcon ? "true" : "false"; }); } _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; 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 = mainIconVisible ? iconRect.width : 0; const lineGap = spacerEl ? this._getNumericStyleValue(aboveLine, "gap", 0) : 0; const labelGap = this._getNumericStyleValue(aboveLine, "--sbcp-main-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 spacerReserve = mainIconVisible && spacerWidth > 0 ? spacerWidth + lineGap : 0; const nameWidth = this._measureTextWidthWithStyles(labelText, text) || labelText.scrollWidth || 0; const withNameBudget = Math.max(0, lineWidth - spacerReserve - labelGap); const fitsWithName = (valueWidth, budget = withNameBudget) => { const visibleWidth = Math.max(0, budget - valueWidth); const visibleChars = this._measureVisibleLabelCharacters(labelText, text, visibleWidth); return !this._shouldHideLeftLabel(text, nameWidth, visibleWidth, visibleChars); }; const availableValueOnly = Math.max(0, lineWidth); let hideUnit = false; if (fullValueWidth <= withNameBudget && fitsWithName(fullValueWidth)) { hideName = false; hideSpacer = !mainIconVisible; } else if (fullValueWidth <= availableValueOnly) { hideName = !fitsWithName(fullValueWidth, lineWidth - labelGap); hideSpacer = true; } else if (valueOnlyWidth <= withNameBudget && fitsWithName(valueOnlyWidth)) { hideName = false; hideUnit = !!unit; hideSpacer = !mainIconVisible; } else if (fitsWithName(valueOnlyWidth, lineWidth - labelGap)) { hideName = false; hideSpacer = true; hideUnit = !!unit; } else { hideName = true; hideSpacer = true; hideUnit = !!unit && fullValueWidth > availableValueOnly; } 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) { for (const fit of ["tight", "minimum"]) { const readingWidth = valueWidth(fit, false); if (readingWidth <= availableWithoutLabel) { heroLine.dataset.heroValueFit = fit; if (!labelHiddenByDensity && labelEl) { const text = (labelEl.textContent || "").trim(); const nameWidth = this._measureTextWidthWithStyles(labelEl, text); const availableName = Math.max(0, availableWithLabel - readingWidth); if (!this._shouldHideLeftLabel( text, nameWidth, availableName, this._measureVisibleLabelCharacters(labelEl, text, availableName) )) { delete headerEl.dataset.priorityHideName; } } return; } } 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); clone.removeAttribute("data-hide-value"); const wrapper = document.createElement("div"); wrapper.className = "bar-inner-label"; wrapper.style.cssText = "position:static;display:block;padding:0"; wrapper.appendChild(clone); layer.replaceChildren(wrapper); return clone.getBoundingClientRect().width; } _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, _d, _e; 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 fullWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, false) + 2); const mainLine = valueEl.closest(".main-line"); let desiredWidth = fullWidth; if (mainLine == null ? void 0 : mainLine.classList.contains("off-mode")) { const barWrap = mainLine.querySelector(".bar-wrap"); const iconWrap = mainLine.querySelector(".icon-wrap"); mainLine.dataset.hideOffIcon = "false"; const gap = parseFloat(getStyle(mainLine).gap) || 0; const rowWidth = (_e = (_d = mainLine.getBoundingClientRect) == null ? void 0 : _d.call(mainLine).width) != null ? _e : 0; const minimumRail = parseFloat(getStyle(barWrap).minWidth) || 0; const iconVisible = iconWrap && getStyle(iconWrap).display !== "none"; const iconWidth = iconVisible ? this._getLeftModeIconWidth(iconWrap, mainLine) : 0; const withoutIcon = Math.max(0, rowWidth - minimumRail - gap); const withIcon = withoutIcon - (iconVisible ? iconWidth + gap : 0); const numberWidth = Math.ceil(this._measureValueMarkupWidth(valueEl, display, unit, true) + 2); const hideIcon = iconVisible && (fullWidth > withIcon && fullWidth <= withoutIcon || numberWidth > withIcon && numberWidth <= withoutIcon); mainLine.dataset.hideOffIcon = hideIcon ? "true" : "false"; const availableWidth = hideIcon ? withoutIcon : withIcon; if (availableWidth > 0) { const readableWidth = fullWidth <= availableWidth ? fullWidth : numberWidth; desiredWidth = Math.min(readableWidth, availableWidth); } } 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); } _getStableLeftLabelMetrics(row, rowWidth = null) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; const mainLine = row == null ? void 0 : row.querySelector(".main-line"); const labelWrap = row == null ? void 0 : row.querySelector(".label-left"); const labelText = row == null ? void 0 : row.querySelector(".label-left-text"); if (!mainLine || !labelWrap || !labelText) return null; const width = (_b = rowWidth != null ? rowWidth : (_a = mainLine.getBoundingClientRect) == null ? void 0 : _a.call(mainLine).width) != null ? _b : 0; const text = (labelText.textContent || "").trim(); const naturalWidth = this._measureTextWidthWithStyles(labelText, text) || labelText.scrollWidth || 0; const density = ((_c = mainLine.dataset) == null ? void 0 : _c.leftDensity) || "normal"; const labelShares = { normal: 0.25, compact: 0.22, tight: 0.19, dense: 0.16, compressed: 0.14 }; const entityConfig = (_e = (_d = this._config) == null ? void 0 : _d.entities) == null ? void 0 : _e.find((item) => { var _a2; return item.entity === ((_a2 = row.dataset) == null ? void 0 : _a2.entity); }); const configuredWidth = entityConfig ? (_i = (_h = (_g = (_f = this._resolve(entityConfig)) == null ? void 0 : _f.layout) == null ? void 0 : _g.label) == null ? void 0 : _h.width) != null ? _i : 100 : 100; const maximumWidth = width > 0 ? Math.min(configuredWidth, width * ((_j = labelShares[density]) != null ? _j : labelShares.normal)) : Math.min(naturalWidth, configuredWidth); return { text, naturalWidth, maximumWidth, labelWidth: maximumWidth, labelText }; } _estimateLeftModeWidthBudget(row) { var _a, _b, _c; 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._getStableLeftLabelMetrics(row, rowWidth); const labelWidth = (_c = labelMetrics == null ? void 0 : labelMetrics.labelWidth) != null ? _c : 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; const hasIcon = !!iconWrap; const labelGapCount = hasIcon ? 2 : 1; const labelAvailableWidth = Math.max( 0, rowWidth - (hasIcon ? iconWidth : 0) - barMinWidth - labelGapCount * gap ); const candidateLabelWidth = Math.min(labelWidth, labelAvailableWidth); const labelSacrificial = !labelMetrics || this._shouldHideLeftLabel( labelMetrics.text, labelMetrics.naturalWidth, candidateLabelWidth, this._measureVisibleLabelCharacters(labelMetrics.labelText, labelMetrics.text, candidateLabelWidth) ); const withoutIconLabelWidth = Math.min(labelWidth, Math.max(0, rowWidth - barMinWidth - gap)); const labelSacrificialWithoutIcon = !labelMetrics || this._shouldHideLeftLabel( labelMetrics.text, labelMetrics.naturalWidth, withoutIconLabelWidth, this._measureVisibleLabelCharacters(labelMetrics.labelText, labelMetrics.text, withoutIconLabelWidth) ); return { rowWidth, gap, barMinWidth, labelSacrificialWithoutIcon, 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, 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 remainingWidth = Math.max(0, effectiveBudget.rowWidth - reservedWidth); const fits = remainingWidth >= effectiveBudget.barMinWidth; const predictedBarWidth = fits ? remainingWidth : effectiveBudget.barMinWidth; return { rowWidth: effectiveBudget.rowWidth, barWidth: predictedBarWidth, share: predictedBarWidth / effectiveBudget.rowWidth, showLabel, showIcon, showInlineValue, reservedWidth, gapCount, fits }; } _getLeftModeCandidateStates(budget) { const states = []; if (budget && !budget.labelSacrificial) { states.push( { hideLabel: false, topValue: false, hideIcon: false }, { hideLabel: false, topValue: true, hideIcon: false } ); } if (budget && !budget.labelSacrificialWithoutIcon) { states.push( { hideLabel: false, topValue: false, hideIcon: true }, { hideLabel: false, topValue: true, hideIcon: true } ); } states.push( { hideLabel: true, topValue: false, hideIcon: false }, { hideLabel: true, topValue: false, hideIcon: true }, { hideLabel: true, topValue: true, hideIcon: true } ); return states; } _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, settled = true) { var _a, _b, _c, _d; const budget = this._estimateLeftModeWidthBudget(row); if (!budget) return null; const minimumBarShare = this._getMinimumBarShare(); const states = this._getLeftModeCandidateStates(budget); const entityCfg = (_b = this._config.entities) == null ? void 0 : _b[Number((_a = row == null ? void 0 : row.dataset) == null ? void 0 : _a.rowIndex)]; const previousTopValue = entityCfg && this._leftModeResponsiveHistory.has(entityCfg) ? this._leftModeResponsiveHistory.get(entityCfg) : ((_d = (_c = budget.rowStack) == null ? void 0 : _c.dataset) == null ? void 0 : _d.forceTopValue) === "true"; const topStates = states.filter((state) => state.topValue); const enableShare = this._getTopValueEnableShare(); const disableShare = this._getTopValueDisableShare(); for (const state of states) { const threshold = state.topValue || settled ? minimumBarShare : previousTopValue ? disableShare : enableShare; const predicted = this._predictLeftModeBarShareForState(row, state, budget); if ((predicted == null ? void 0 : predicted.fits) && predicted.share >= threshold) return { ...state, predicted }; } return this._chooseFallbackPredictedLeftModeState(row, topStates, budget); } _applyLeftModeResponsiveState(row, state) { var _a, _b; 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; const entityCfg = (_b = this._config.entities) == null ? void 0 : _b[Number((_a = row == null ? void 0 : row.dataset) == null ? void 0 : _a.rowIndex)]; if (entityCfg) this._leftModeResponsiveHistory.set(entityCfg, (state == null ? void 0 : state.topValue) === true); 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, leftWidths = 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 settled = !leftWidths || leftWidths.get(mainLine) === mainLine.getBoundingClientRect().width; const state = this._chooseLeftModeResponsiveState(row, settled); if (state) this._applyLeftModeResponsiveState(row, state); if (!settled) this._schedulePostLayoutDensityPass(); 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) => { var _a; const labelWrap = mainLine.querySelector(".label-left"); const labelText = mainLine.querySelector(".label-left-text"); if (!labelWrap || !labelText) return; const row = ((_a = mainLine.closest) == null ? void 0 : _a.call(mainLine, ".row")) || { dataset: {}, querySelector: (selector) => selector === ".main-line" ? mainLine : selector === ".label-left" ? labelWrap : selector === ".label-left-text" ? labelText : null }; const metrics = this._getStableLeftLabelMetrics(row); if (!metrics) return; const visibleChars = this._measureVisibleLabelCharacters(metrics.labelText, metrics.text, metrics.labelWidth); labelWrap.dataset.hidden = this._shouldHideLeftLabel( metrics.text, metrics.naturalWidth, metrics.labelWidth, visibleChars ) ? "true" : "false"; }); } _runPostLayoutPasses(rows = null) { const generation = this._rowGeneration; requestAnimationFrame(() => { var _a; if (!this.isConnected || generation !== this._rowGeneration) return; this._applyRowDensity(); this._applyLeftModeDensity(); this._applyAboveLabelDensity(); this._applyHeroValueFit(); this._applyInsideLabelDensity(); this._applyValueWidthReservation(); const leftWidths = new Map( [...((_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll(".main-line.left-mode")) || []].map((mainLine) => [mainLine, mainLine.getBoundingClientRect().width]) ); requestAnimationFrame(() => { var _a2; if (!this.isConnected || generation !== this._rowGeneration) return; this._applyAdaptiveRowHeight(); this._applyValueVisibility(); this._applyLeftLabelUsefulness(); this._applyTopRightValueLayout(); this._ensureMinimumBarShare(rows, leftWidths); this._applyTopRightValueLayout(); this._applyLeftLabelUsefulness(); const targetRows = rows || ((_a2 = this.shadowRoot) == null ? void 0 : _a2.querySelectorAll(".row[data-entity]")) || []; targetRows.forEach((row) => { this._positionTargetLabel(row); this._positionMarkerValueLabel(row, ".peak-value-label", ".peak-marker"); this._positionMarkerValueLabel(row, ".floor-value-label", ".floor-marker"); this._positionGenericMarkerLabels(row); }); }); }); } _isTightUnit(unit) { return isTightUnit(unit); } _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)}%)`; } _getEffectiveMarkerColor(marker) { var _a; return (_a = marker == null ? void 0 : marker.color) != null ? _a : "#888888"; } _getMarkerLabelColorStyle(marker) { const color = this._getEffectiveMarkerColor(marker); return `--marker-color:${color};--marker-contrast-color:${this._getMarkerContrastColor(color)};`; } _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) { return formatDisplayWithUnit(display, unit); } _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}`; } _getRowMarkerModels(rowViewModel, ecfg, peakPct, peakDisplay, targetPct, targetDisplay, peakColor, targetColor) { if (rowViewModel == null ? void 0 : rowViewModel.markers) { return rowViewModel.markers.map((marker) => { var _a, _b; if (marker.type === "target") { return { ...marker, position: targetPct === void 0 ? marker.position : targetPct, visible: targetPct !== null && targetPct !== void 0, color: targetColor || marker.color, label: (_a = marker.label) != null ? _a : targetDisplay === null ? null : { text: targetDisplay } }; } if (marker.type === "floor") { return marker; } if (marker.type !== "peak") return marker; return { ...marker, position: peakPct === void 0 ? marker.position : peakPct, visible: peakPct !== null && peakPct !== void 0 && ecfg.peak_marker.show === true, color: peakColor || marker.color, label: (_b = marker.label) != null ? _b : peakDisplay === null ? null : { text: peakDisplay } }; }); } const markers = buildMarkerModels({ entityConfig: ecfg, targetPosition: targetPct, targetPresentation: targetDisplay === null ? null : { text: targetDisplay }, targetVisible: Number.isFinite(targetPct), peakPosition: peakPct, peakPresentation: peakDisplay === null ? null : { number: peakDisplay }, peakVisible: Number.isFinite(peakPct) }); const targetMarker = this._getMarkerModel(markers, "target"); const peakMarker = this._getMarkerModel(markers, "peak"); if (targetMarker && targetColor) targetMarker.color = targetColor; if (peakMarker && peakColor) peakMarker.color = peakColor; return markers; } _getMarkerModel(markers, type) { var _a; return (_a = markers.find((marker) => marker.id === type || marker.type === type)) != null ? _a : null; } _renderMarker(marker) { var _a, _b, _c, _d, _e, _f, _g; if (!marker) return ""; const position = Number.isFinite(marker.position) ? marker.position : 0; const color = this._getEffectiveMarkerColor(marker); const contrastColor = this._getMarkerContrastColor(color); const display = marker.visible ? "" : "none"; const defaultShape = marker.type === "target" ? "diamond" : marker.type === "generic" ? "circle" : "triangle"; const shape = normalizeMarkerShape(marker.shape, defaultShape); const lane = (_a = marker.lane) != null ? _a : marker.type === "peak" ? "above" : "below"; const shapePaths = ` `; if (marker.type === "generic") { const triangleClasses = lane === "above" ? ["peak-inset", "peak-outset"] : ["target-inset", "target-outset"]; return `
`; } if (marker.type === "target" || marker.type === "floor") { const markerClass = `${marker.type}-marker`; return `
`; } return `
`; } _patchMarker(markerEl, marker) { var _a, _b, _c, _d, _e; if (!markerEl || !marker) return; if (!marker.visible) this._clearMarkerHover(markerEl); const defaultShape = marker.type === "generic" ? "circle" : marker.type === "peak" || marker.type === "floor" ? "triangle" : "diamond"; const shape = normalizeMarkerShape(marker.shape, defaultShape); this._setDatasetIfChanged(markerEl, "shape", shape); this._setDatasetIfChanged(markerEl, "lane", (_a = marker.lane) != null ? _a : marker.type === "peak" ? "above" : "below"); this._setDatasetIfChanged(markerEl, "direction", (_b = marker.direction) != null ? _b : "inward"); if (marker.type === "generic") { this._setDatasetIfChanged(markerEl, "showMarker", marker.showMarker === false ? "false" : "true"); } const shapeSvg = (_c = markerEl.querySelector) == null ? void 0 : _c.call(markerEl, ".marker-shape-svg"); if (shapeSvg) { this._setDatasetIfChanged(shapeSvg, "shape", shape); this._setDatasetIfChanged(shapeSvg, "lane", (_d = marker.lane) != null ? _d : marker.type === "peak" ? "above" : "below"); this._setDatasetIfChanged(shapeSvg, "direction", (_e = marker.direction) != null ? _e : "inward"); } this._setStyleIfChanged(markerEl, "display", marker.visible ? "" : "none"); if (marker.visible && Number.isFinite(marker.position)) { this._setStyleIfChanged(markerEl, "left", `${marker.position}%`); } const markerColor = this._getEffectiveMarkerColor(marker); this._setStyleIfChanged(markerEl, "--marker-color", markerColor); this._setStyleIfChanged(markerEl, "--marker-contrast-color", this._getMarkerContrastColor(markerColor)); } _patchMarkerLabelAppearance(labelEl, marker) { if (!labelEl || !marker) return; const markerColor = this._getEffectiveMarkerColor(marker); this._setStyleIfChanged(labelEl, "--marker-color", markerColor); this._setStyleIfChanged(labelEl, "--marker-contrast-color", this._getMarkerContrastColor(markerColor)); } _buildRowViewModel(entityCfg, ecfg, stateObj) { var _a; const rowViewModel = buildRowViewModel({ hass: this._hass, cardConfig: this._config, entityConfig: ecfg, entityState: stateObj, extrema: (_a = this._extrema.get(entityCfg)) != null ? _a : null, previousScale: this._rowScales.get(entityCfg) }); this._rowScales.set(entityCfg, { min: rowViewModel.min, max: rowViewModel.max }); return rowViewModel; } _buildRow(entityCfg, stateDisplay, unit, pct, color, peakPct, peakDisplay, targetPct, targetDisplay, peakColor, targetColor, minValue, maxValue, rowIndex = ((_b) => (_b = ((_a) => (_a = this._config.entities) == null ? void 0 : _a.indexOf(entityCfg))()) != null ? _b : -1)()) { var _a2, _b2, _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; const ecfg = this._resolve(entityCfg); const stateObj = (_c = (_b2 = (_a2 = this._hass) == null ? void 0 : _a2.states) == null ? void 0 : _b2[entityCfg.entity]) != null ? _c : null; if (stateObj) this._updateExtrema(entityCfg, ecfg, stateObj); const rowViewModel = stateObj ? this._buildRowViewModel(entityCfg, ecfg, stateObj) : null; const layout = ecfg.layout; const bar = ecfg.bar; 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 markerModels = this._getRowMarkerModels(rowViewModel, ecfg, peakPct, peakDisplay, targetPct, targetDisplay, peakColor, targetColor); const targetMarkerModel = this._getMarkerModel(markerModels, "target"); const peakMarkerModel = this._getMarkerModel(markerModels, "peak"); const floorMarkerModel = this._getMarkerModel(markerModels, "floor"); const genericMarkerModels = markerModels.filter((marker) => marker.type === "generic"); const markerLaneOccupancy = (_l = rowViewModel == null ? void 0 : rowViewModel.markerLaneOccupancy) != null ? _l : getMarkerLaneOccupancy(ecfg); const markerLabelLaneOccupancy = (_m = rowViewModel == null ? void 0 : rowViewModel.markerLabelLaneOccupancy) != null ? _m : getMarkerLabelLaneOccupancy(ecfg); const rawValue = (_n = rowViewModel == null ? void 0 : rowViewModel.numericValue) != null ? _n : this._getFiniteNumber(stateDisplay); const needleState = (_o = rowViewModel == null ? void 0 : rowViewModel.needle) != null ? _o : 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 baselineAt = (_p = ecfg.baseline) == null ? void 0 : _p.at; const baselineConfigured = ((_q = ecfg.baseline) == null ? void 0 : _q.enabled) !== false && (Number.isFinite(baselinePct) || Boolean(baselineAt == null ? void 0 : baselineAt.entity) || (baselineAt == null ? void 0 : baselineAt.fixed) !== null && (baselineAt == null ? void 0 : baselineAt.fixed) !== void 0 || Number.isFinite(baselineAt == null ? void 0 : baselineAt.percent)); const baselineIndicator = baselineConfigured ? `` : ""; const peakMarker = this._renderMarker(peakMarkerModel); const targetMarker = this._renderMarker(targetMarkerModel); const floorMarker = this._renderMarker(floorMarkerModel); const targetValueLabel = (targetMarkerModel == null ? void 0 : targetMarkerModel.labelVisible) ? `
${((_s = targetMarkerModel.label) == null ? void 0 : _s.text) ? escapeHtml(targetMarkerModel.label.text) : ""}
` : ""; const peakValueLabel = (peakMarkerModel == null ? void 0 : peakMarkerModel.labelVisible) ? `
${peakMarkerModel.visible && ((_u = peakMarkerModel.label) == null ? void 0 : _u.text) ? escapeHtml(peakMarkerModel.label.text) : ""}
` : ""; const floorValueLabel = (floorMarkerModel == null ? void 0 : floorMarkerModel.labelVisible) ? `
${floorMarkerModel.visible && ((_w = floorMarkerModel.label) == null ? void 0 : _w.text) ? escapeHtml(floorMarkerModel.label.text) : ""}
` : ""; const genericMarkers = genericMarkerModels.map((marker) => this._renderMarker(marker)).join(""); const genericValueLabels = genericMarkerModels.filter((marker) => marker.labelVisible).map((marker) => { var _a3, _b3; return `
${marker.visible && ((_b3 = marker.label) == null ? void 0 : _b3.text) ? escapeHtml(marker.label.text) : ""}
`; }).join(""); const needleMarker = ((_y = (_x = ecfg.bar) == null ? void 0 : _x.needle) == null ? void 0 : _y.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 = (_A = layout.hero.size) != null ? _A : "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}
${baselineIndicator} ${innerLabel} ${peakMarker} ${targetMarker} ${floorMarker} ${genericMarkers} ${needleMarker}
${peakValueLabel} ${targetValueLabel} ${floorValueLabel} ${genericValueLabels}
${rightValue}
`; } _patchRow(row, entityCfg, stateObj, previousHass = null) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; if (!row || !stateObj) return; const ecfg = this._resolve(entityCfg); this._updateExtrema(entityCfg, ecfg, stateObj); const previousScale = this._rowScales.get(entityCfg); const rowViewModel = this._buildRowViewModel(entityCfg, ecfg, stateObj); const safeMin = rowViewModel.min; const safeMax = rowViewModel.max; const pct = rowViewModel.percent; const color = this._getColor(pct, ecfg, safeMin, safeMax); const display = rowViewModel.primaryPresentation.number; const displayUnit = rowViewModel.primaryPresentation.unit; const fillReveal = row.querySelector(".bar-fill-reveal"); const baselineIndicator = row.querySelector(".baseline-indicator"); 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); const previousStateObj = (_b = (_a = previousHass == null ? void 0 : previousHass.states) == null ? void 0 : _a[entityCfg.entity]) != null ? _b : null; const previousViewModel = previousStateObj ? buildRowViewModel({ hass: previousHass, cardConfig: this._config, entityConfig: ecfg, entityState: previousStateObj, extrema: (_c = this._extrema.get(entityCfg)) != null ? _c : null, previousScale }) : null; const revealDuration = this._getRevealTransitionDuration( previousViewModel && Number.isFinite(previousViewModel.numericValue) ? { valuePercent: previousViewModel.percent, baselinePercent: previousViewModel.baselinePercent } : null, Number.isFinite(rowViewModel.numericValue) ? { valuePercent: pct, baselinePercent: liveBaselinePct } : null ); if (fillReveal) { this._setStyleTextIfChanged(fillReveal, `${fillState.revealStyle};--sbcp-reveal-duration:${revealDuration}ms`); this._setClassNameIfChanged(fillReveal, `bar-fill-reveal${ecfg.bar.animated ? "" : " no-anim"}`); } if (baselineIndicator) { this._setStyleIfChanged(baselineIndicator, "display", Number.isFinite(liveBaselinePct) ? "block" : "none"); if (Number.isFinite(liveBaselinePct)) { this._setStyleIfChanged(baselineIndicator, "left", `${liveBaselinePct}%`); } } 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", `${(_d = needleState.pct) != null ? _d : 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)}`; } const targetEl = row.querySelector(".target-marker"); const targetLabelEl = row.querySelector(".target-value-label"); const peakLabelEl = row.querySelector(".peak-value-label"); const floorLabelEl = row.querySelector(".floor-value-label"); const markerModels = (_e = rowViewModel.markers) != null ? _e : []; this._patchMarker(targetEl, this._getMarkerModel(markerModels, "target")); this._patchMarker(row.querySelector(".peak-marker"), this._getMarkerModel(markerModels, "peak")); this._patchMarker(row.querySelector(".floor-marker"), this._getMarkerModel(markerModels, "floor")); ((_g = (_f = row.querySelectorAll) == null ? void 0 : _f.call(row, ".generic-marker[data-marker-id]")) != null ? _g : []).forEach((markerEl) => { var _a2, _b2, _c2, _d2, _e2; const markerId = markerEl.dataset.markerId; const marker = this._getMarkerModel(markerModels, markerId); this._patchMarker(markerEl, marker); const labelEl = [...(_b2 = (_a2 = row.querySelectorAll) == null ? void 0 : _a2.call(row, ".generic-value-label[data-marker-id]")) != null ? _b2 : []].find((label) => label.dataset.markerId === markerId); if (!labelEl) return; this._setDatasetIfChanged(labelEl, "showMarker", (marker == null ? void 0 : marker.showMarker) === false ? "false" : "true"); this._patchMarkerLabelAppearance(labelEl, marker); if ((marker == null ? void 0 : marker.labelVisible) && marker.visible && ((_c2 = marker.label) == null ? void 0 : _c2.text)) { this._setTextIfChanged(labelEl, (_e2 = (_d2 = marker.label) == null ? void 0 : _d2.text) != null ? _e2 : null); this._setStyleIfChanged(labelEl, "visibility", "visible"); this._setStyleIfChanged(labelEl, "left", `${Number.isFinite(marker.position) ? marker.position : 0}%`); } else { this._setStyleIfChanged(labelEl, "visibility", "hidden"); } }); const targetMarkerModel = this._getMarkerModel(markerModels, "target"); this._patchMarkerLabelAppearance(targetLabelEl, targetMarkerModel); if (targetLabelEl) { if ((targetMarkerModel == null ? void 0 : targetMarkerModel.labelVisible) && targetMarkerModel.visible && ((_h = targetMarkerModel.label) == null ? void 0 : _h.text)) { this._setTextIfChanged(targetLabelEl, (_j = (_i = targetMarkerModel.label) == null ? void 0 : _i.text) != null ? _j : null); } else { this._setStyleIfChanged(targetLabelEl, "visibility", "hidden"); } } const patchValueLabel = (labelEl, markerType) => { var _a2, _b2, _c2; if (!labelEl) return; const marker = this._getMarkerModel(markerModels, markerType); this._patchMarkerLabelAppearance(labelEl, marker); if ((marker == null ? void 0 : marker.labelVisible) && marker.visible && ((_a2 = marker.label) == null ? void 0 : _a2.text)) { this._setTextIfChanged(labelEl, (_c2 = (_b2 = marker.label) == null ? void 0 : _b2.text) != null ? _c2 : null); this._setStyleIfChanged(labelEl, "visibility", "visible"); this._setStyleIfChanged(labelEl, "left", `${Number.isFinite(marker.position) ? marker.position : 0}%`); } else { this._setStyleIfChanged(labelEl, "visibility", "hidden"); } }; patchValueLabel(peakLabelEl, "peak"); patchValueLabel(floorLabelEl, "floor"); } _update(previousHass = null) { var _a, _b, _c, _d; if (!this._hass || !this._config) return; const rowsEl = this.shadowRoot.querySelector(".rows"); if (!rowsEl) return; const entities = this._config.entities; const presence = entities.map((entityCfg) => !!this._hass.states[entityCfg.entity]); const presenceChanged = presence.some((present, index) => present !== this._rowPresence[index]); if (!this._rendered || presenceChanged) { this._rowGeneration += 1; this._rowPresence = presence; 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); this._updateExtrema(entityCfg, ecfg, stateObj); const rowViewModel = this._buildRowViewModel(entityCfg, ecfg, stateObj); const safeMin = rowViewModel.min; const safeMax = rowViewModel.max; const pct = rowViewModel.percent; const color = this._getColor(pct, ecfg, safeMin, safeMax); const display = rowViewModel.primaryPresentation.number; const displayUnit = rowViewModel.primaryPresentation.unit; const targetPct = rowViewModel.targetPercent; const targetDisplay = (_b = (_a = rowViewModel.targetPresentation) == null ? void 0 : _a.text) != null ? _b : null; const peakPct = rowViewModel.peakPercent; const peakDisplay = (_d = (_c = rowViewModel.peakPresentation) == null ? void 0 : _c.number) != null ? _d : null; html += this._buildRow(entityCfg, display, displayUnit, pct, color, peakPct, peakDisplay, targetPct, targetDisplay, ecfg.peak_marker.color, ecfg.target_marker.color, safeMin, safeMax, entityIndex); } this._clearMarkerHover(); rowsEl.innerHTML = html; this._rendered = true; const builtRows = rowsEl.querySelectorAll(".row[data-entity]"); builtRows.forEach((row) => { const entityCfg = entities[Number(row.dataset.rowIndex)]; 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]"); for (const row of rows) { const entityCfg = entities[Number(row.dataset.rowIndex)]; if (!entityCfg) continue; const stateObj = this._hass.states[entityCfg.entity]; if (!stateObj) continue; this._patchRow(row, entityCfg, stateObj, previousHass); } this._runPostLayoutPasses(rows); } }; } }); // src/editor/SensorBarCardPlusEditor.js var SensorBarCardPlusEditor; var init_SensorBarCardPlusEditor = __esm({ "src/editor/SensorBarCardPlusEditor.js"() { init_normalize(); init_resolve(); 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._genericMarkerUiIds = /* @__PURE__ */ new Map(); this._expandedGenericMarkerUiIds = /* @__PURE__ */ new Set(); this._nextGenericMarkerUiId = 0; 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; } if (nextConfigJson === this._lastEmittedConfigJson) { this._config = nextConfig; return; } if (this._getEmittedConfigJson(nextConfig) === this._getEmittedConfigJson(this._draftConfig)) { this._config = nextConfig; return; } const shouldRender = !((_a = this.shadowRoot) == null ? void 0 : _a.innerHTML) || nextConfigJson !== this._lastRenderedConfigJson; this._lastEmittedConfigJson = null; 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(); this._genericMarkerUiIds.clear(); this._expandedGenericMarkerUiIds.clear(); 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)); } _getEmittedConfigJson(config) { return this._serializeConfig(config); } _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-marker-target-summary", this._getCardTargetMarkerSummary()); this._setElementText("card-group-marker-peak-summary", this._getMarkerResetSummary("peak")); this._setElementText("card-group-marker-floor-summary", this._getMarkerResetSummary("floor")); this._setElementText("card-group-baseline-summary", this._getCardBaselineSummary()); this._setElementText("card-group-generic-markers-summary", this._getGenericMarkersSummary({ type: "card" })); 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}-floor-inherit`, !this._hasExtremumOverride(scope, "floor")); this._setElementChecked(`entity-${index}-markers-inherit`, !this._hasMarkersOverride(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-floor-summary`, this._getFloorSummary(scope)); this._setElementText(`entity-${index}-group-markers-summary`, this._getGenericMarkersSummary(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) { if (this._isObject(value) || value === null || typeof value === "string" && this._normalizeNumberValue(value) === null) { return this._cloneDeep(value); } const fixed = this._normalizeNumberValue(value); return fixed === null ? null : { fixed }; } _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] === null) { 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, scope = { type: "card" }) { var _a; 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 label = this._cleanBuiltinMarkerLabelForEmit(nextMarker.label, scope, "target"); const fillColor = this._normalizeTextValue((_a = nextMarker.when_exceeded) == null ? void 0 : _a.fill_color).trim(); const hasShape = Object.prototype.hasOwnProperty.call(nextMarker, "shape"); const shape = hasShape ? normalizeTargetMarkerShape(nextMarker.shape) : null; const direction = Object.prototype.hasOwnProperty.call(nextMarker, "direction") ? normalizeMarkerDirection(nextMarker.direction) : null; if (typeof nextMarker.enabled !== "boolean") { delete nextMarker.enabled; } if (cleanedAt || nextMarker.at === null) { 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 (Object.keys(label).length) { nextMarker.label = label; if (label.show === true) delete nextTarget.show_target_label; } else { delete nextMarker.label; delete nextTarget.show_target_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 ((scope == null ? void 0 : scope.type) === "card" && shape === "diamond") { delete nextMarker.shape; } else if (shape) { nextMarker.shape = shape; } else { delete nextMarker.shape; } if (direction === "inward" && ((scope == null ? void 0 : scope.type) !== "entity" || direction === this._getEffectiveMarkerDirection({ type: "card" }, "target"))) { delete nextMarker.direction; } else if (direction) { nextMarker.direction = direction; } 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 === null) { 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, scope = { type: "card" }) { 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(); const direction = Object.prototype.hasOwnProperty.call(nextPeak, "direction") ? normalizeMarkerDirection(nextPeak.direction) : null; if (typeof nextPeak.enabled !== "boolean") { delete nextPeak.enabled; } if ((scope == null ? void 0 : scope.type) !== "entity" && nextPeak.reset === "never") { delete nextPeak.reset; } if (direction === "inward" && ((scope == null ? void 0 : scope.type) !== "entity" || direction === this._getEffectiveMarkerDirection({ type: "card" }, "peak"))) { delete nextPeak.direction; } else if (direction) { nextPeak.direction = direction; } if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#888")) { nextPeak.color = color; delete nextTarget.peak_color; } else { delete nextPeak.color; } nextPeak.label = this._cleanBuiltinMarkerLabelForEmit(nextPeak.label, scope, "peak"); if (!Object.keys(nextPeak.label).length) delete nextPeak.label; if (Object.keys(nextPeak).length) { nextTarget.peak = nextPeak; } else { delete nextTarget.peak; } return nextTarget; } _cleanupFloorForEmit(target, scope = { type: "card" }) { if (!this._isObject(target) || !this._isObject(target.floor)) { return target; } const nextTarget = this._cloneDeep(target); const nextFloor = this._cloneDeep(nextTarget.floor); const color = this._normalizeTextValue(nextFloor.color).trim(); const direction = Object.prototype.hasOwnProperty.call(nextFloor, "direction") ? normalizeMarkerDirection(nextFloor.direction) : null; if (typeof nextFloor.enabled !== "boolean") delete nextFloor.enabled; if (color && this._normalizeColorComparisonValue(color) !== this._normalizeColorComparisonValue("#888888")) { nextFloor.color = color; } else { delete nextFloor.color; } if (this._isObject(nextFloor.label)) { nextFloor.label = this._cleanBuiltinMarkerLabelForEmit(nextFloor.label, scope, "floor"); if (!Object.keys(nextFloor.label).length) delete nextFloor.label; } if ((scope == null ? void 0 : scope.type) !== "entity" && nextFloor.reset === "never" || nextFloor.reset === void 0 || nextFloor.reset === null || nextFloor.reset === "") { delete nextFloor.reset; } if (direction === "inward" && ((scope == null ? void 0 : scope.type) !== "entity" || direction === this._getEffectiveMarkerDirection({ type: "card" }, "floor"))) { delete nextFloor.direction; } else if (direction) { nextFloor.direction = direction; } if (Object.keys(nextFloor).length) nextTarget.floor = nextFloor; else delete nextTarget.floor; return nextTarget; } _cleanBuiltinMarkerLabelForEmit(rawLabel, scope, key) { var _a, _b, _c; const label = this._isObject(rawLabel) ? this._cloneDeep(rawLabel) : {}; const cardLabel = (scope == null ? void 0 : scope.type) === "entity" ? (_a = this._getScopedValue({ type: "card" }, [key, "label"])) != null ? _a : {} : {}; if (label.show === false && (scope == null ? void 0 : scope.type) !== "entity") delete label.show; if (label.show === false && (scope == null ? void 0 : scope.type) === "entity" && cardLabel.show !== true) delete label.show; if (label.show_value === true && ((scope == null ? void 0 : scope.type) !== "entity" || cardLabel.show_value !== false)) delete label.show_value; if (label.show_unit === true && ((scope == null ? void 0 : scope.type) !== "entity" || cardLabel.show_unit !== false)) delete label.show_unit; if (typeof label.text === "string") { label.text = label.text.replace(/\s+/g, " ").trim(); if (!label.text && (scope == null ? void 0 : scope.type) !== "entity") delete label.text; } const precision = this._normalizeDecimalValue((_b = label.precision) != null ? _b : label.decimal); delete label.decimal; if (precision === null) delete label.precision; else if ((scope == null ? void 0 : scope.type) === "entity" && precision === ((_c = cardLabel.precision) != null ? _c : cardLabel.decimal)) delete label.precision; else label.precision = precision; return label; } _cleanupBarForEmit(target, scope = { type: "card" }, cardConfig = null, inheritedSegmentSpace = null) { if (!this._isObject(target) || !this._isObject(target.bar)) { return target; } const nextTarget = this._cloneDeep(target); const nextBar = this._cloneDeep(nextTarget.bar); const scopedSegmentSpace = ["percent", "scale"].includes(nextBar.segment_space) ? nextBar.segment_space : (scope == null ? void 0 : scope.type) === "entity" && ["percent", "scale"].includes(inheritedSegmentSpace) ? inheritedSegmentSpace : null; const legacySegmentSpace = scopedSegmentSpace; if (legacySegmentSpace === "percent" && Array.isArray(nextBar.segments)) { const asLegacyPercent = (boundary) => { if (typeof boundary === "number" && Number.isFinite(boundary)) return `${boundary}%`; if (typeof boundary === "string" && boundary.trim() !== "" && !boundary.includes("%") && Number.isFinite(Number(boundary.trim()))) { return `${Number(boundary.trim())}%`; } return boundary; }; nextBar.segments = nextBar.segments.map((segment) => ({ ...segment, from: asLegacyPercent(segment == null ? void 0 : segment.from), ...Object.prototype.hasOwnProperty.call(segment != null ? segment : {}, "to") ? { to: asLegacyPercent(segment.to) } : {} })); } delete nextBar.segment_space; 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) { const withoutLocalFillStyle = this._cloneDeep(nextTarget); delete withoutLocalFillStyle.bar.fill_style; const inheritedStyle = normalizeBarConfig( withoutLocalFillStyle, (scope == null ? void 0 : scope.type) === "entity" ? cardConfig : null, { isCardScope: (scope == null ? void 0 : scope.type) !== "entity" } ).fill_style; if (fillStyle === "bands" && inheritedStyle === "bands") delete nextBar.fill_style; else 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 || legacySegmentSpace || !this._segmentsEqualForEditor(segments, this._getDefaultSegments()))) { nextBar.segments = segments; delete nextTarget.segments; delete nextTarget.severity; } else { delete nextBar.segments; } if (gradientStops && (!gradientStops.length || 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", "floor", "layout", "formatting", "bar"]; case "entities.*": return ["entity", "name", "icon", "scale", "target", "baseline", "peak", "floor", "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", "shape", "color", "label", "when_exceeded"]; case "target.label": return ["show", "decimal"]; 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", "reset", "label"]; case "floor": return ["enabled", "color", "reset", "label"]; case "peak.label": case "floor.label": return ["show", "decimal"]; 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) { var _a; if (!this._isObject(config)) { return config; } const inheritedSegmentSpace = (_a = config.bar) == null ? void 0 : _a.segment_space; let nextConfig = this._cleanupEntityIdentityForEmit(config); nextConfig = this._cleanupScaleForEmit(nextConfig); nextConfig = this._cleanupTargetForEmit(nextConfig, { type: "card" }); nextConfig = this._cleanupBaselineForEmit(nextConfig); nextConfig = this._cleanupPeakForEmit(nextConfig, { type: "card" }); nextConfig = this._cleanupFloorForEmit(nextConfig, { type: "card" }); nextConfig = this._cleanupGenericMarkersForEmit(nextConfig); nextConfig = this._cleanupLayoutForEmit(nextConfig); nextConfig = this._cleanupFormattingForEmit(nextConfig); nextConfig = this._cleanupNeedleForEmit(nextConfig, { type: "card" }); nextConfig = this._cleanupBarForEmit(nextConfig, { type: "card" }); if (Array.isArray(nextConfig.entities)) { nextConfig.entities = nextConfig.entities.map((entry, index) => { if (!this._isObject(entry)) { return entry; } let cleanedEntry = this._cleanupEntityIdentityForEmit(entry); cleanedEntry = this._cleanupScaleForEmit(cleanedEntry); cleanedEntry = this._cleanupTargetForEmit(cleanedEntry, { type: "entity", index }); cleanedEntry = this._cleanupBaselineForEmit(cleanedEntry); cleanedEntry = this._cleanupPeakForEmit(cleanedEntry, { type: "entity", index }); cleanedEntry = this._cleanupFloorForEmit(cleanedEntry, { type: "entity", index }); cleanedEntry = this._cleanupGenericMarkersForEmit(cleanedEntry); cleanedEntry = this._cleanupLayoutForEmit(cleanedEntry); cleanedEntry = this._cleanupFormattingForEmit(cleanedEntry); cleanedEntry = this._cleanupNeedleForEmit(cleanedEntry, { type: "entity" }); cleanedEntry = this._cleanupBarForEmit(cleanedEntry, { type: "entity", index }, nextConfig, inheritedSegmentSpace); return cleanedEntry; }); } const meaning = (raw) => { const normalized = normalizeCardConfig({ ...raw, ...!raw.entities && !raw.entity ? { entities: [] } : {} }); const featureKeys = ["layout", "scale", "bar", "baseline", "formatting", "target_marker", "peak_marker", "floor_marker", "generic_markers"]; const scope = (value) => ({ ...Object.fromEntries(featureKeys.map((key) => [key, value[key]])), scale: Object.fromEntries(["min", "max"].map((key) => [key, { ...value.scale[key], fixed_explicit: value.scale[key].fixed_explicit !== false }])) }); const canonical = (value, key = "") => { if (Array.isArray(value)) return value.map((entry) => canonical(entry)); if (this._isObject(value)) return Object.fromEntries(Object.entries(value).filter(([name]) => !["severity", "segment_space", "label_precision_key"].includes(name) && !/invalid/i.test(name)).map(([name, entry]) => [name, canonical(entry, name)])); if (key === "fixed") return getNumericValue(null, value); if (/color/i.test(key) && typeof value === "string") return this._normalizeColorComparisonValue(value); return value; }; return this._serializeConfig(canonical({ card: scope(normalized), entities: normalized.entities.map((row) => ({ entity: row.entity, name: row.name, icon: row.icon, ...scope(row) })) })); }; try { if (meaning(config) !== meaning(nextConfig)) nextConfig = this._cloneDeep(config); } catch (_error) { nextConfig = this._cloneDeep(config); } 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, _e, _f; 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); if (structuredValue !== void 0) { const source = normalizeStructuredResolvableValue(structuredValue, (_d = options.inheritedSource) != null ? _d : null, null, { allowPercent: ["target", "baseline"].includes(canonicalBasePath[0]) }); return { fixed: (_e = source.fixed) != null ? _e : "", entity: (_f = source.entity) != null ? _f : "", ...Number.isFinite(source.percent) ? { percent: source.percent } : {} }; } return { fixed: !this._isObject(legacyFixedValue) && legacyFixedValue !== void 0 ? legacyFixedValue : "", entity: legacyEntityValue != null ? legacyEntityValue : "" }; } _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 = {}) { var _a, _b; 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); const target = this._getEntityRawEntries()[scope.index]; if (this._getPathValue(target, (_a = options.canonicalBasePath) != null ? _a : ["scale", field]) !== void 0) { return this._getResolvablePartsFromTarget(target, field, { ...options, inheritedSource: { fixed: inheritedValue.fixed === "" ? null : inheritedValue.fixed, entity: inheritedValue.entity || null, percent: (_b = inheritedValue.percent) != null ? _b : null } }); } 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 !== ""; const hasPercent = Number.isFinite(nextParts.percent); if (hasFixed || hasEntity || hasPercent) { const nextValue = {}; if (hasFixed) nextValue.fixed = nextParts.fixed; if (hasEntity) nextValue.entity = nextParts.entity; if (hasPercent) nextValue.percent = nextParts.percent; 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 percent = parsePercentLiteral(rawValue); const numericValue = Number.isFinite(percent) ? percent : 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") || Object.prototype.hasOwnProperty.call(peakValue, "reset") || Object.prototype.hasOwnProperty.call(peakValue, "label") || Object.prototype.hasOwnProperty.call(peakValue, "direction"))) { 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") || Object.prototype.hasOwnProperty.call(peakMarkerValue, "direction"))) { 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, ["peak", "reset"]); nextTarget = this._deletePathValue(nextTarget, ["peak", "label"]); nextTarget = this._deletePathValue(nextTarget, ["peak", "direction"]); 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; }); } _getScopedMarkerExtras(scope, key) { var _a, _b, _c, _d; const raw = this._getScopedValue(scope, [key]); const marker = this._isObject(raw) ? raw : {}; const label = this._isObject(marker.label) ? marker.label : {}; return { reset: Object.prototype.hasOwnProperty.call(marker, "reset") ? this._normalizeTextValue(marker.reset).trim().toLowerCase() : null, labelShow: typeof label.show === "boolean" ? label.show : null, labelText: typeof label.text === "string" ? label.text.replace(/\s+/g, " ").trim() : null, labelShowValue: typeof label.show_value === "boolean" ? label.show_value : null, labelShowUnit: typeof label.show_unit === "boolean" ? label.show_unit : null, labelPrecision: ((_a = label.precision) != null ? _a : label.decimal) === void 0 || ((_b = label.precision) != null ? _b : label.decimal) === null || ((_c = label.precision) != null ? _c : label.decimal) === "" ? null : this._normalizeNumberValue((_d = label.precision) != null ? _d : label.decimal) }; } _hasExtremumOverride(scope, key) { const marker = this._getScopedValue(scope, [key]); if (!this._isObject(marker)) return false; return ["enabled", "color", "reset", "label", "direction"].some((field) => Object.prototype.hasOwnProperty.call(marker, field)); } _getEffectiveMarkerExtras(scope, key) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r; const local = this._getScopedMarkerExtras(scope, key); if ((scope == null ? void 0 : scope.type) !== "entity") { return { reset: (_a = local.reset) != null ? _a : "never", labelShow: (_b = local.labelShow) != null ? _b : false, labelText: local.labelText, labelShowValue: (_c = local.labelShowValue) != null ? _c : true, labelShowUnit: (_d = local.labelShowUnit) != null ? _d : true, labelPrecision: local.labelPrecision }; } const card = this._getScopedMarkerExtras({ type: "card" }, key); if (!this._hasExtremumOverride(scope, key)) { return { reset: (_e = card.reset) != null ? _e : "never", labelShow: (_f = card.labelShow) != null ? _f : false, labelText: card.labelText, labelShowValue: (_g = card.labelShowValue) != null ? _g : true, labelShowUnit: (_h = card.labelShowUnit) != null ? _h : true, labelPrecision: card.labelPrecision }; } return { reset: (_j = (_i = local.reset) != null ? _i : card.reset) != null ? _j : "never", labelShow: (_l = (_k = local.labelShow) != null ? _k : card.labelShow) != null ? _l : false, labelText: Object.prototype.hasOwnProperty.call((_m = this._getScopedValue(scope, [key, "label"])) != null ? _m : {}, "text") ? local.labelText : card.labelText, labelShowValue: (_o = (_n = local.labelShowValue) != null ? _n : card.labelShowValue) != null ? _o : true, labelShowUnit: (_q = (_p = local.labelShowUnit) != null ? _p : card.labelShowUnit) != null ? _q : true, labelPrecision: (_r = local.labelPrecision) != null ? _r : card.labelPrecision }; } _getScopedFloorConfig(scope) { const raw = this._getScopedValue(scope, ["floor"]); const marker = this._isObject(raw) ? raw : {}; let mode = (scope == null ? void 0 : scope.type) === "entity" ? "inherit" : "disabled"; if (marker.enabled === true) mode = "enabled"; if (marker.enabled === false) mode = "disabled"; const color = marker.color && this._normalizeColorComparisonValue(marker.color) !== this._normalizeColorComparisonValue("#888888") ? marker.color : ""; return { mode, color }; } _getEffectiveScopedFloorConfig(scope) { const local = this._getScopedFloorConfig(scope); const extras = this._getEffectiveMarkerExtras(scope, "floor"); if ((scope == null ? void 0 : scope.type) !== "entity") return { ...local, ...extras }; if (!this._hasExtremumOverride(scope, "floor")) { return { ...this._getScopedFloorConfig({ type: "card" }), ...extras }; } const card = this._getEffectiveScopedFloorConfig({ type: "card" }); return { mode: local.mode === "inherit" ? card.mode : local.mode, color: local.color || card.color, ...extras }; } _getFloorSummary(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasExtremumOverride(scope, "floor")) return "Inherited"; const floor = this._getEffectiveScopedFloorConfig(scope); if (floor.mode === "enabled") return floor.color ? "Enabled \u2022 Custom color" : "Enabled"; if (floor.color) return "Disabled \u2022 Custom color"; return "Disabled"; } _getMarkerResetSummary(key) { var _a; const scope = { type: "card" }; const marker = key === "peak" ? this._getScopedPeakConfig(scope) : this._getEffectiveScopedFloorConfig(scope); const enabled = marker.mode === "enabled"; const reset = (_a = this._getEffectiveMarkerExtras(scope, key).reset) != null ? _a : "never"; return `${enabled ? "Enabled" : "Disabled"} \xB7 ${reset === "never" ? "no reset" : `${reset} reset`}`; } _getCardTargetMarkerSummary() { const mode = this._getTargetMode({ type: "card" }); if (mode === "disabled") return "Disabled"; const target = this._getTargetResolvableValue({ type: "card" }); const parts = []; if (mode === "enabled") parts.push("Enabled"); const hasTargetValue = target.fixed !== "" && target.fixed !== void 0 || !!target.entity; if (target.fixed !== "" && target.fixed !== void 0) parts.push(String(target.fixed)); if (target.entity) parts.push(target.entity); if (hasTargetValue || this._hasTargetShape({ type: "card" })) { parts.push(this._getEffectiveTargetShapeValue({ type: "card" }) === "triangle" ? "Triangle" : "Diamond"); } return parts.length ? parts.join(" \xB7 ") : "Automatic"; } _setScopedExtremumEnabled(scope, key, value) { const boolValue = !!value; const defaultColor = "#888888"; return this._applyScopedMutation(scope, (target) => { var _a; let nextTarget = this._cloneDeep(target); const current = this._isObject(this._getPathValue(nextTarget, [key])) ? this._cloneDeep(this._getPathValue(nextTarget, [key])) : {}; const currentColor = (_a = current.color) != null ? _a : defaultColor; if ((scope == null ? void 0 : scope.type) === "entity" || boolValue) current.enabled = boolValue; else delete current.enabled; if (currentColor && this._normalizeColorComparisonValue(currentColor) !== this._normalizeColorComparisonValue(defaultColor)) { current.color = currentColor; } else delete current.color; if (Object.keys(current).length) nextTarget = this._setPathValue(nextTarget, [key], current); else nextTarget = this._deletePathValue(nextTarget, [key]); return nextTarget; }); } _setScopedExtremumColor(scope, key, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); const defaultColor = "#888888"; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const current = this._isObject(this._getPathValue(nextTarget, [key])) ? this._cloneDeep(this._getPathValue(nextTarget, [key])) : {}; delete current.color; if (normalizedValue && this._normalizeColorComparisonValue(normalizedValue) !== this._normalizeColorComparisonValue(defaultColor)) { current.color = normalizedValue; } const mode = this._getScopedFloorConfig(scope).mode; if (key === "floor" && ((scope == null ? void 0 : scope.type) === "entity" && mode !== "inherit" || (scope == null ? void 0 : scope.type) !== "entity" && mode === "enabled")) { current.enabled = mode === "enabled"; } if (Object.keys(current).length) nextTarget = this._setPathValue(nextTarget, [key], current); else nextTarget = this._deletePathValue(nextTarget, [key]); if (key === "peak") { nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); } return nextTarget; }); } _setScopedExtremumReset(scope, key, value) { const normalized = this._normalizeTextValue(value).trim().toLowerCase(); return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const current = this._isObject(this._getPathValue(nextTarget, [key])) ? this._cloneDeep(this._getPathValue(nextTarget, [key])) : {}; if (normalized && ((scope == null ? void 0 : scope.type) === "entity" || normalized !== "never")) current.reset = normalized; else delete current.reset; if (Object.keys(current).length) nextTarget = this._setPathValue(nextTarget, [key], current); else nextTarget = this._deletePathValue(nextTarget, [key]); if (key === "peak") { nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); } return nextTarget; }); } _setScopedExtremumLabelShow(scope, key, value) { const enabled = !!value; return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const current = this._isObject(this._getPathValue(nextTarget, [key])) ? this._cloneDeep(this._getPathValue(nextTarget, [key])) : {}; const label = this._isObject(current.label) ? this._cloneDeep(current.label) : {}; if ((scope == null ? void 0 : scope.type) === "entity" || enabled) label.show = enabled; else delete label.show; if (Object.keys(label).length) current.label = label; else delete current.label; if (Object.keys(current).length) nextTarget = this._setPathValue(nextTarget, [key], current); else nextTarget = this._deletePathValue(nextTarget, [key]); if (key === "peak") { nextTarget = this._deletePathValue(nextTarget, ["show_peak"]); nextTarget = this._deletePathValue(nextTarget, ["peak_color"]); nextTarget = this._deletePathValue(nextTarget, ["peak_marker"]); } return nextTarget; }); } _setScopedExtremumLabelDecimal(scope, key, value) { const decimal = this._normalizeNumberValue(value); return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const current = this._isObject(this._getPathValue(nextTarget, [key])) ? this._cloneDeep(this._getPathValue(nextTarget, [key])) : {}; const label = this._isObject(current.label) ? this._cloneDeep(current.label) : {}; if (decimal !== null) label.decimal = decimal; else delete label.decimal; if (Object.keys(label).length) current.label = label; else delete current.label; if (Object.keys(current).length) nextTarget = this._setPathValue(nextTarget, [key], current); else nextTarget = this._deletePathValue(nextTarget, [key]); return nextTarget; }); } _getBuiltinMarkerLabelOptions(scope, key) { var _a; const marker = this._getScopedValue(scope, [key]); const label = this._isObject(marker == null ? void 0 : marker.label) ? marker.label : {}; const cardLabel = (scope == null ? void 0 : scope.type) === "entity" ? (_a = this._getScopedValue({ type: "card" }, [key, "label"])) != null ? _a : {} : {}; const own = (name) => Object.prototype.hasOwnProperty.call(label, name); const inheritedValue = (name, fallback) => { var _a2; return own(name) ? label[name] : (_a2 = cardLabel[name]) != null ? _a2 : fallback; }; const precision = inheritedValue("precision", inheritedValue("decimal", "")); return { show: key === "target" ? this._getEffectiveTargetLabelShowValue(scope) : this._getEffectiveMarkerExtras(scope, key).labelShow, text: inheritedValue("text", ""), showValue: inheritedValue("show_value", true) !== false, showUnit: inheritedValue("show_unit", true) !== false, precision: precision === null ? "" : precision }; } _renderBuiltinMarkerLabelControls(scope, key, title) { var _a; const options = this._getBuiltinMarkerLabelOptions(scope, key); const isEntity = (scope == null ? void 0 : scope.type) === "entity"; const prefix = isEntity ? `entity-${scope.index}-${key}` : key; const attr = isEntity ? `data-kind="entity-${key}-label-` : `data-field="${key}-label-`; const suffix = isEntity ? `" data-index="${scope.index}"` : '"'; return `
`; } _setBuiltinMarkerLabelField(scope, key, field, value) { const publicField = field === "showValue" ? "show_value" : field === "showUnit" ? "show_unit" : field === "precision" ? "precision" : field; const isText = field === "text"; const normalized = isText ? this._normalizeTextValue(value).replace(/\s+/g, " ").trim() : field === "show" || field === "showValue" || field === "showUnit" ? value === true : this._normalizeDecimalValue(value); if (field === "precision" && value !== "" && normalized === null) return false; return this._applyScopedMutation(scope, (target) => { var _a, _b, _c, _d; let next = this._cloneDeep(target); if (key === "target" && field === "show") next = this._deletePathValue(next, ["show_target_label"]); const marker = this._isObject(this._getPathValue(next, [key])) ? this._cloneDeep(this._getPathValue(next, [key])) : {}; const label = this._isObject(marker.label) ? this._cloneDeep(marker.label) : {}; const inheritedLabel = (scope == null ? void 0 : scope.type) === "entity" ? (_a = this._getScopedValue({ type: "card" }, [key, "label"])) != null ? _a : {} : {}; const inheritedValue = field === "precision" ? (_c = (_b = inheritedLabel.precision) != null ? _b : inheritedLabel.decimal) != null ? _c : null : (_d = inheritedLabel[publicField]) != null ? _d : field === "show" ? false : field === "showValue" || field === "showUnit" ? true : void 0; if (normalized === null || isText && !normalized) { if (isText && (scope == null ? void 0 : scope.type) === "entity" && typeof inheritedLabel.text === "string" && inheritedLabel.text.trim()) { label[publicField] = ""; } else { delete label[publicField]; } } else if ((scope == null ? void 0 : scope.type) === "entity" && normalized === inheritedValue) { delete label[publicField]; } else if ((field === "show" || field === "showValue" || field === "showUnit") && (scope == null ? void 0 : scope.type) !== "entity" && normalized === (field === "show" ? false : true)) { delete label[publicField]; } else { label[publicField] = normalized; } if (field === "precision") delete label.decimal; if (Object.keys(label).length) marker.label = label; else delete marker.label; if (Object.keys(marker).length) next = this._setPathValue(next, [key], marker); else next = this._deletePathValue(next, [key]); return next; }); } _clearFloorOverride(scope) { return this._applyScopedMutation(scope, (target) => { let nextTarget = this._cloneDeep(target); const floor = this._isObject(this._getPathValue(nextTarget, ["floor"])) ? this._cloneDeep(this._getPathValue(nextTarget, ["floor"])) : {}; ["enabled", "color", "reset", "label", "direction"].forEach((key) => delete floor[key]); if (Object.keys(floor).length) nextTarget = this._setPathValue(nextTarget, ["floor"], floor); else nextTarget = this._deletePathValue(nextTarget, ["floor"]); nextTarget = this._deletePathValue(nextTarget, ["floor_marker"]); return nextTarget; }, { rerender: true }); } _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._getEffectiveFillStyleValue({ 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) { return this._getEffectiveFillStyleValue(scope); } _setScopedBarFillStyle(scope, rawValue) { const normalizedValue = this._normalizeTextValue(rawValue).trim(); if (!normalizedValue) { 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"; } _getTargetShapeValue(scope) { var _a; return (_a = this._getScopedValue(scope, ["target", "shape"])) != null ? _a : ""; } _getEffectiveMarkerDirection(scope, key) { const canonical = this._getScopedValue(scope, [key, "direction"]); const local = canonical !== void 0 ? canonical : this._getScopedValue(scope, [`${key}_marker`, "direction"]); if ((scope == null ? void 0 : scope.type) === "entity" && local === void 0) { return this._getEffectiveMarkerDirection({ type: "card" }, key); } return normalizeMarkerDirection(local); } _setMarkerDirection(scope, key, rawValue) { const direction = normalizeMarkerDirection(rawValue); const cardDirection = this._getEffectiveMarkerDirection({ type: "card" }, key); if ((scope == null ? void 0 : scope.type) !== "entity" && direction === "inward" || (scope == null ? void 0 : scope.type) === "entity" && direction === cardDirection) { return this._removeCanonicalScopedValue(scope, [key, "direction"], { prunePaths: [[key]] }); } return this._setCanonicalScopedTextOverride(scope, [key, "direction"], direction, { prunePaths: [[key]] }); } _hasTargetShape(scope) { const target = this._getScopedValue(scope, ["target"]); return this._isObject(target) && Object.prototype.hasOwnProperty.call(target, "shape"); } _getEffectiveTargetShapeValue(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasTargetShape(scope)) { return this._getEffectiveTargetShapeValue({ type: "card" }); } return normalizeTargetMarkerShape(this._getTargetShapeValue(scope)); } _setTargetShape(scope, rawValue) { const normalizedShape = normalizeTargetMarkerShape(rawValue); if ((scope == null ? void 0 : scope.type) !== "entity" && normalizedShape === "diamond") { return this._removeCanonicalScopedValue(scope, ["target", "shape"], { prunePaths: [["target"]] }); } return this._setCanonicalScopedTextOverride(scope, ["target", "shape"], normalizedShape, { prunePaths: [["target"]] }); } _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", "shape"]); nextTarget = this._deletePathValue(nextTarget, ["target", "direction"]); nextTarget = this._deletePathValue(nextTarget, ["target", "label", "show"]); nextTarget = this._deletePathValue(nextTarget, ["target", "label", "decimal"]); 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"]] }); } _getTargetLabelDecimalValue(scope) { var _a, _b; return (_b = (_a = this._getScopedValue(scope, ["target", "label", "precision"])) != null ? _a : this._getScopedValue(scope, ["target", "label", "decimal"])) != null ? _b : ""; } _getEffectiveTargetLabelDecimalValue(scope) { const local = this._getTargetLabelDecimalValue(scope); return local !== "" && local !== null && local !== void 0 ? local : (scope == null ? void 0 : scope.type) === "entity" ? this._getTargetLabelDecimalValue({ type: "card" }) : ""; } _setTargetLabelDecimal(scope, rawValue) { const normalizedValue = this._normalizeDecimalValue(rawValue); if (rawValue === "" || rawValue === null || rawValue === void 0) { return this._removeCanonicalScopedValue(scope, ["target", "label", "decimal"], { prunePaths: [["target", "label"], ["target"]] }); } if (normalizedValue === null) { return false; } return this._setCanonicalScopedValue(scope, ["target", "label", "decimal"], normalizedValue, { 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; }) || this._getTargetLabelDecimalValue(scope) !== ""; } _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 }); } _removeBaseline(scope) { return this._removeScopedValue(scope, ["baseline"], { 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(); } _toggleGenericMarkerExpanded(markerUiId) { if (this._expandedGenericMarkerUiIds.has(markerUiId)) { this._expandedGenericMarkerUiIds.delete(markerUiId); } else { this._expandedGenericMarkerUiIds.add(markerUiId); } 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._hasTargetShape(scope)) { parts.push(this._getEffectiveTargetShapeValue(scope) === "triangle" ? "Triangle" : "Diamond"); } if (this._hasCustomTargetColor(scope)) parts.push("Custom color"); if (this._getTargetLabelShowValue(scope)) parts.push("Label"); const labelDecimal = this._getTargetLabelDecimalValue(scope); if (labelDecimal !== "") parts.push(`Label ${labelDecimal} ${Number(labelDecimal) === 1 ? "decimal" : "decimals"}`); 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"; } _getCardBaselineSummary() { const mode = this._getBaselineMode({ type: "card" }); if (mode === "disabled") return "Disabled"; const baseline = this._getBaselineResolvableValue({ type: "card" }); const origin = baseline.entity || (baseline.fixed !== "" && baseline.fixed !== void 0 ? baseline.fixed : ""); const modeLabel = mode === "enabled" ? "Enabled" : "Auto"; return origin !== "" ? `${modeLabel} \xB7 ${origin}` : modeLabel; } _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") { return normalizeBarConfig( this._getEntityRawEntries()[scope.index], this._draftConfig, { isCardScope: false } ).fill_style; } return normalizeBarConfig(this._draftConfig, null, { isCardScope: true }).fill_style; } _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", extraDataset = {}) { const extraAttrs = Object.entries(extraDataset).map(([key, entry]) => `data-${key}="${this._escapeAttribute(entry)}"`).join(" "); if (customElements.get("ha-entity-picker")) { return ``; } return ``; } _hasMarkersOverride(scope) { return (scope == null ? void 0 : scope.type) === "entity" && this._getScopedValue(scope, ["markers"]) !== void 0; } _getGenericMarkers(scope, effective = true) { const local = this._getScopedValue(scope, ["markers"]); if ((scope == null ? void 0 : scope.type) === "entity" && local === void 0 && effective) { const cardMarkers = this._getScopedValue({ type: "card" }, ["markers"]); return Array.isArray(cardMarkers) ? this._cloneDeep(cardMarkers) : []; } return Array.isArray(local) ? this._cloneDeep(local) : []; } _getGenericMarkersSummary(scope) { if ((scope == null ? void 0 : scope.type) === "entity" && !this._hasMarkersOverride(scope)) return "Inherited"; const count = this._getGenericMarkers(scope, false).length; return count === 0 ? "No reference markers" : `${count} reference marker${count === 1 ? "" : "s"}`; } _getGenericMarkerScopeKey(scope) { return (scope == null ? void 0 : scope.type) === "entity" ? `entity:${scope.index}` : "card"; } _getGenericMarkerUiIds(scope, count) { var _a; const key = this._getGenericMarkerScopeKey(scope); const ids = (_a = this._genericMarkerUiIds.get(key)) != null ? _a : []; while (ids.length < count) { ids.push(`marker-${++this._nextGenericMarkerUiId}`); } ids.length = count; this._genericMarkerUiIds.set(key, ids); return ids; } _resetGenericMarkerUiScope(scope) { var _a; const key = this._getGenericMarkerScopeKey(scope); const ids = (_a = this._genericMarkerUiIds.get(key)) != null ? _a : []; ids.forEach((id) => this._expandedGenericMarkerUiIds.delete(id)); this._genericMarkerUiIds.delete(key); } _getGenericMarkerSummary(marker) { var _a; const source = this._getGenericMarkerSource(marker); const lane = (marker == null ? void 0 : marker.lane) === "above" ? "Above" : "Below"; const shape = (_a = marker == null ? void 0 : marker.shape) != null ? _a : "circle"; let sourceSummary; if (source.mode === "percent") { sourceSummary = source.percent === "" ? "Percentage" : `${source.percent}%`; } else if (source.mode === "entity" || source.mode === "entity-fallback") { sourceSummary = source.entity || "Entity"; } else { sourceSummary = source.fixed === "" ? "Fixed value" : String(source.fixed); } return `${lane} \xB7 ${shape.charAt(0).toUpperCase()}${shape.slice(1)} \xB7 ${sourceSummary}`; } _refreshGenericMarkerSummary(scope, markerIndex) { const markers = this._getGenericMarkers(scope); const marker = markers[markerIndex]; const uiId = this._getGenericMarkerUiIds(scope, markers.length)[markerIndex]; const summary = this._getShadowElementById(`generic-${uiId}-summary`); if (marker && summary) { const text = this._getGenericMarkerSummary(marker); summary.textContent = text; summary.setAttribute("title", text); } } _getGenericMarkerSource(marker) { var _a, _b, _c; const at = marker == null ? void 0 : marker.at; if (typeof at === "string" && /^\s*[+-]?(?:\d+(?:\.\d+)?|\.\d+)\s*%\s*$/.test(at)) { return { mode: "percent", percent: at.replace(/%/g, "").trim() }; } if (typeof at === "string" && /^[a-z0-9_]+\.[a-z0-9_]+$/i.test(at.trim())) { return { mode: "entity", entity: at.trim(), fixed: "" }; } const source = this._isObject(at) ? at : {}; if (Object.prototype.hasOwnProperty.call(source, "entity")) { return { mode: source.fixed !== void 0 && source.fixed !== null && source.fixed !== "" ? "entity-fallback" : "entity", entity: (_a = source.entity) != null ? _a : "", fixed: (_b = source.fixed) != null ? _b : "" }; } return { mode: "fixed", fixed: (_c = source.fixed) != null ? _c : "" }; } _renderGenericMarkersEditor(scope) { const scopeType = scope.type; const scopeIndex = scopeType === "entity" ? scope.index : "card"; const markers = this._getGenericMarkers(scope); const markerUiIds = this._getGenericMarkerUiIds(scope, markers.length); const override = this._hasMarkersOverride(scope); const rows = markers.map((marker, markerIndex) => { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; const source = this._getGenericMarkerSource(marker); const markerUiId = markerUiIds[markerIndex]; const rowId = `${scopeType}-${scopeIndex}-generic-${markerUiId}`; const expanded = this._expandedGenericMarkerUiIds.has(markerUiId); const entitySource = source.mode === "entity" || source.mode === "entity-fallback" ? this._renderEntitySourceInput("generic-marker-entity", scopeIndex, source.entity, "sensor.reference", { "scope-type": scopeType, "marker-index": markerIndex }) : ""; const labelEntitySource = this._renderEntitySourceInput( "generic-marker-label-entity", scopeIndex, (_b = (_a = marker == null ? void 0 : marker.label) == null ? void 0 : _a.entity) != null ? _b : "", "sensor.information", { "scope-type": scopeType, "marker-index": markerIndex } ); return `
${source.mode === "fixed" ? `
` : ""} ${source.mode === "entity" || source.mode === "entity-fallback" ? `
${entitySource}
` : ""} ${source.mode === "entity-fallback" ? `
` : ""} ${source.mode === "percent" ? `
%
` : ""}
${this._renderColorInput({ id: `${rowId}-color`, kind: "generic-marker-color", index: scopeIndex, value: (_e = marker == null ? void 0 : marker.color) != null ? _e : "#888888", fallbackHex: "#888888", placeholder: "#888888", extraDataset: { "scope-type": scopeType, "marker-index": markerIndex } })}
${labelEntitySource}
`; }).join(""); const inheritControl = scopeType === "entity" ? `
` : ""; const overrideNote = scopeType === "entity" && !override ? '
Enable the override to replace the card marker list. An empty override clears all card markers.
' : ""; return ` ${inheritControl} ${overrideNote} ${scopeType === "card" || override ? `
Up to four markers render in each lane, including Peak, Floor, and Target. Excess generic markers remain editable and show a warning. Unresolved markers still reserve a slot and lane.
${rows}
` : ""} `; } _getGenericMarkerScope(target) { var _a; return ((_a = target == null ? void 0 : target.dataset) == null ? void 0 : _a.scopeType) === "entity" ? { type: "entity", index: Number(target.dataset.index) } : { type: "card" }; } _setGenericMarkerList(scope, markers, options = {}) { return this._setScopedValue(scope, ["markers"], markers, { rerender: false, ...options }); } _updateGenericMarker(scope, markerIndex, update, options = {}) { var _a; const markers = this._getGenericMarkers(scope); if (!markers[markerIndex]) return false; const marker = this._isObject(markers[markerIndex]) ? this._cloneDeep(markers[markerIndex]) : {}; const nextMarker = (_a = update(marker)) != null ? _a : marker; markers[markerIndex] = nextMarker; const changed = this._setGenericMarkerList(scope, markers, options); if (changed) this._refreshGenericMarkerSummary(scope, markerIndex); return changed; } _setGenericMarkerSourceMode(scope, markerIndex, mode) { return this._updateGenericMarker(scope, markerIndex, (marker) => { if (mode === "percent") { marker.at = "50%"; return marker; } const oldAt = this._isObject(marker.at) ? this._cloneDeep(marker.at) : {}; if (mode === "fixed") { delete oldAt.entity; delete oldAt.percent; if (oldAt.fixed === void 0) oldAt.fixed = 50; } else { delete oldAt.percent; if (!oldAt.entity) oldAt.entity = ""; if (mode === "entity") delete oldAt.fixed; if (mode === "entity-fallback" && oldAt.fixed === void 0) oldAt.fixed = 50; } marker.at = oldAt; return marker; }, { rerender: true }); } _setGenericMarkerField(scope, markerIndex, kind, value) { var _a, _b; const atLeaf = (key, nextValue) => this._updateGenericMarker(scope, markerIndex, (marker) => { const at = this._isObject(marker.at) ? this._cloneDeep(marker.at) : {}; if (nextValue === void 0) delete at[key]; else at[key] = nextValue; marker.at = Object.keys(at).length ? at : null; return marker; }); if (kind === "generic-marker-source-mode") return this._setGenericMarkerSourceMode(scope, markerIndex, value); if (kind === "generic-marker-show-marker") { return this._updateGenericMarker(scope, markerIndex, (marker) => { if (value === false) marker.show_marker = false; else delete marker.show_marker; return marker; }); } if (kind === "generic-marker-fixed") { return atLeaf("fixed", (_a = this._normalizeNumberValue(value)) != null ? _a : void 0); } if (kind === "generic-marker-fallback") { return atLeaf("fixed", (_b = this._normalizeNumberValue(value)) != null ? _b : void 0); } if (kind === "generic-marker-entity") { return atLeaf("entity", this._normalizeTextValue(value).trim() || void 0); } if (kind === "generic-marker-percent") { const percent = this._normalizeNumberValue(value); return this._updateGenericMarker(scope, markerIndex, (marker) => { marker.at = percent === null ? null : `${percent}%`; return marker; }); } if (kind === "generic-marker-lane" || kind === "generic-marker-shape" || kind === "generic-marker-direction") { return this._updateGenericMarker(scope, markerIndex, (marker) => { const key = kind === "generic-marker-lane" ? "lane" : kind === "generic-marker-shape" ? "shape" : "direction"; marker[key] = key === "direction" ? normalizeMarkerDirection(value) : value; return marker; }); } if (kind === "generic-marker-color") { return this._updateGenericMarker(scope, markerIndex, (marker) => { marker.color = this._normalizeTextValue(value).trim(); return marker; }); } if (kind.startsWith("generic-marker-label-")) { return this._updateGenericMarker(scope, markerIndex, (marker) => { const label = this._isObject(marker.label) ? this._cloneDeep(marker.label) : {}; if (kind === "generic-marker-label-show") label.show = value === true; if (kind === "generic-marker-label-text") { const text = this._normalizeTextValue(value).replace(/\s+/g, " ").trim(); if (text) label.text = text; else delete label.text; } if (kind === "generic-marker-label-entity") { const entity = this._normalizeTextValue(value).trim(); if (entity) label.entity = entity; else delete label.entity; } if (kind === "generic-marker-label-show-value") label.show_value = value === true; if (kind === "generic-marker-label-show-unit") label.show_unit = value === true; if (kind === "generic-marker-label-precision") { const precision = this._normalizeDecimalValue(value); if (precision === null) { delete label.precision; delete label.decimal; } else { label.precision = precision; delete label.decimal; } } marker.label = label; return marker; }); } return false; } _cleanupGenericMarkersForEmit(target) { if (!this._isObject(target) || !Array.isArray(target.markers)) return target; const nextTarget = this._cloneDeep(target); nextTarget.markers = nextTarget.markers.map((rawMarker) => { var _a; if (!this._isObject(rawMarker)) return rawMarker; const marker = this._cloneDeep(rawMarker); if (marker.show_marker === true) delete marker.show_marker; if (this._isObject(marker.at)) { const at = this._cloneDeep(marker.at); const fixed = this._normalizeNumberValue(at.fixed); const entity = this._normalizeTextValue(at.entity).trim(); if (fixed !== null) at.fixed = fixed; else delete at.fixed; if (entity) at.entity = entity; else delete at.entity; if (Object.keys(at).length) marker.at = at; else delete marker.at; } if (marker.lane === "below") delete marker.lane; if (marker.shape === "circle") delete marker.shape; if (marker.direction === "inward") delete marker.direction; if (this._normalizeColorComparisonValue(marker.color) === this._normalizeColorComparisonValue("#888888")) delete marker.color; if (this._isObject(marker.label)) { const label = this._cloneDeep(marker.label); if (label.show === false) delete label.show; if (label.show_value === true) delete label.show_value; if (label.show_unit === true) delete label.show_unit; if (typeof label.text === "string") { label.text = label.text.replace(/\s+/g, " ").trim(); if (!label.text) delete label.text; } const precision = this._normalizeDecimalValue((_a = label.precision) != null ? _a : label.decimal); delete label.decimal; if (precision === null) delete label.precision; else label.precision = precision; delete label.unit; if (Object.keys(label).length) marker.label = label; else delete marker.label; } return marker; }); return nextTarget; } _renderResetOptions(value) { const selected = this._normalizeTextValue(value).trim().toLowerCase() || "never"; const options = [ "never", "quarterly", "hourly", "daily", "weekly", "monthly", "yearly", ...Array.from({ length: 59 }, (_, index) => `${index + 1}m`), ...Array.from({ length: 23 }, (_, index) => `${index + 1}h`) ]; return options.map((option) => ``).join(""); } _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 targetShape = this._getEffectiveTargetShapeValue({ type: "card" }); const targetDirection = this._getEffectiveMarkerDirection({ type: "card" }, "target"); const targetColor = this._getTargetColorValue({ type: "card" }); const targetLabelShow = this._getTargetLabelShowValue({ type: "card" }); const targetLabelDecimal = this._getTargetLabelDecimalValue({ 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 cardPeakExtras = this._getEffectiveMarkerExtras({ type: "card" }, "peak"); const cardFloor = this._getEffectiveScopedFloorConfig({ 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.
${(() => { var _a3, _b2; 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 targetShape2 = this._getEffectiveTargetShapeValue(scope); const targetDirection2 = this._getEffectiveMarkerDirection(scope, "target"); 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 entityPeakExtras = this._getEffectiveMarkerExtras(scope, "peak"); const floorInherited = !this._hasExtremumOverride(scope, "floor"); const entityFloor = this._getEffectiveScopedFloorConfig(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" })}
${this._renderBuiltinMarkerLabelControls(scope, "peak", "Peak")} ` }); const floorGroup = this._renderOverrideGroup({ index, group: "floor", title: "Floor", summary: this._getFloorSummary(scope), content: `
${this._renderColorInput({ id: `entity-${index}-floor-color`, kind: "entity-floor-color", index, value: entityFloor.color, fallbackHex: "#888888", placeholder: "inherit card default" })}
${this._renderBuiltinMarkerLabelControls(scope, "floor", "Floor")} ` }); const markersGroup = this._renderOverrideGroup({ index, group: "markers", title: "Reference markers", summary: this._getGenericMarkersSummary(scope), content: this._renderGenericMarkersEditor(scope) }); 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 _a4; 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 _a4, _b3; return `
${this._renderColorInput({ id: `entity-${index}-gradient-color-${stopIndex}`, kind: "entity-gradient-color", index, value: (_b3 = stop == null ? void 0 : stop.color) != null ? _b3 : "#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._renderBuiltinMarkerLabelControls(scope, "target", "Target")}
${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} ${peakGroup} ${floorGroup} ${markersGroup} ${barGroup} ${baselineGroup} ${needleGroup} ${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

Configure Target, Peak, Floor, and custom reference markers.
${this._renderCardGroup({ group: "marker-target", title: "Target", summary: this._getCardTargetMarkerSummary(), content: `
${this._renderEntitySourceInput("target-entity-source", "card", target.entity)}
${this._renderColorInput({ id: "target-color", field: "target-color", value: targetColor, fallbackHex: "#888", placeholder: "#888" })}
${this._renderBuiltinMarkerLabelControls({ type: "card" }, "target", "Target")}
${this._renderColorInput({ id: "target-above-fill-color", field: "target-above-fill-color", value: targetAboveFillColor, fallbackHex: "#000000" })}
` })} ${this._renderCardGroup({ group: "marker-peak", title: "Peak", summary: this._getMarkerResetSummary("peak"), content: `
${this._renderColorInput({ id: "peak-color", field: "peak-color", value: cardPeak.color, fallbackHex: "#888", placeholder: "#888" })}
${this._renderBuiltinMarkerLabelControls({ type: "card" }, "peak", "Peak")}
` })} ${this._renderCardGroup({ group: "marker-floor", title: "Floor", summary: this._getMarkerResetSummary("floor"), content: `
${this._renderColorInput({ id: "floor-color", field: "floor-color", value: cardFloor.color, fallbackHex: "#888888", placeholder: "#888888" })}
${this._renderBuiltinMarkerLabelControls({ type: "card" }, "floor", "Floor")}
` })} ${this._renderCardGroup({ group: "generic-markers", title: "Generic Reference Markers", summary: this._getGenericMarkersSummary({ type: "card" }), content: this._renderGenericMarkersEditor({ type: "card" }) })}

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._renderCardGroup({ group: "baseline", title: "Baseline", summary: this._getCardBaselineSummary(), content: `
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: "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, _b, _c, _d; 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`; return; } if (kind === "generic-marker-entity") { const scope = this._getGenericMarkerScope(picker); const marker = this._getGenericMarkers(scope)[Number(picker.dataset.markerIndex)]; picker.value = (_b = this._getGenericMarkerSource(marker).entity) != null ? _b : ""; picker.label = "Reference marker entity"; } if (kind === "generic-marker-label-entity") { const scope = this._getGenericMarkerScope(picker); const marker = this._getGenericMarkers(scope)[Number(picker.dataset.markerIndex)]; picker.value = (_d = (_c = marker == null ? void 0 : marker.label) == null ? void 0 : _c.entity) != null ? _d : ""; picker.label = "Label content 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"]', 'ha-entity-picker[data-kind="generic-marker-entity"]', 'ha-entity-picker[data-kind="generic-marker-label-entity"]' ].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"]', 'ha-entity-picker[data-kind="generic-marker-entity"]', 'ha-entity-picker[data-kind="generic-marker-label-entity"]' ].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 === "toggle-generic-marker") { this._toggleGenericMarkerExpanded(target.dataset.markerUiId); return; } if (action === "remove-entity") { this._removeEntityRow(Number(target.dataset.index)); return; } if (action === "remove-baseline") { const scope = target.dataset.scopeType === "entity" ? { type: "entity", index: Number(target.dataset.index) } : { type: "card" }; this._removeBaseline(scope); return; } if (action === "add-generic-marker") { const scope = this._getGenericMarkerScope(target); const markers = this._getGenericMarkers(scope); const markerUiIds = this._getGenericMarkerUiIds(scope, markers.length); markers.push({ at: { fixed: 50 } }); const markerUiId = `marker-${++this._nextGenericMarkerUiId}`; markerUiIds.push(markerUiId); this._expandedGenericMarkerUiIds.add(markerUiId); this._setGenericMarkerList(scope, markers, { rerender: true }); return; } if (action === "remove-generic-marker" || action === "move-generic-marker-up" || action === "move-generic-marker-down") { const scope = this._getGenericMarkerScope(target); const markerIndex = Number(target.dataset.markerIndex); const markers = this._getGenericMarkers(scope); const markerUiIds = this._getGenericMarkerUiIds(scope, markers.length); if (action === "remove-generic-marker") { markers.splice(markerIndex, 1); this._expandedGenericMarkerUiIds.delete(markerUiIds[markerIndex]); markerUiIds.splice(markerIndex, 1); } else { const nextIndex = markerIndex + (action === "move-generic-marker-up" ? -1 : 1); if (nextIndex < 0 || nextIndex >= markers.length) return; [markers[markerIndex], markers[nextIndex]] = [markers[nextIndex], markers[markerIndex]]; [markerUiIds[markerIndex], markerUiIds[nextIndex]] = [markerUiIds[nextIndex], markerUiIds[markerIndex]]; } this._setGenericMarkerList(scope, markers, { rerender: true }); 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 (kind === "entity-markers-inherit") { const scope = { type: "entity", index: Number(target.dataset.index) }; this._resetGenericMarkerUiScope(scope); if (value) this._removeScopedValue(scope, ["markers"], { rerender: true }); else this._setGenericMarkerList(scope, this._getGenericMarkers(scope), { rerender: true }); return; } if (kind == null ? void 0 : kind.startsWith("generic-marker-")) { this._setGenericMarkerField( this._getGenericMarkerScope(target), Number(target.dataset.markerIndex), kind, value ); return; } 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-shape") return void this._setTargetShape({ type: "card" }, value); if (field === "target-direction") return void this._setMarkerDirection({ type: "card" }, "target", value); if (field === "target-color") return void this._setTargetColor({ type: "card" }, value); if ((field == null ? void 0 : field.startsWith("target-label-")) || (field == null ? void 0 : field.startsWith("peak-label-")) || (field == null ? void 0 : field.startsWith("floor-label-"))) { const key = field.startsWith("target-") ? "target" : field.startsWith("peak-") ? "peak" : "floor"; const option = field.slice(`${key}-label-`.length); const scope = { type: "card" }; if (option === "show") { this._setBuiltinMarkerLabelField(scope, key, "show", value); } else { const labelField = option === "show-value" ? "showValue" : option === "show-unit" ? "showUnit" : option; this._setBuiltinMarkerLabelField(scope, key, labelField, value); } return; } 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 (field === "peak-direction") return void this._setMarkerDirection({ type: "card" }, "peak", value); if (field === "peak-reset") return void this._setScopedExtremumReset({ type: "card" }, "peak", value); if (field === "floor-show") return void this._setScopedExtremumEnabled({ type: "card" }, "floor", value); if (field === "floor-color") return void this._setScopedExtremumColor({ type: "card" }, "floor", value); if (field === "floor-direction") return void this._setMarkerDirection({ type: "card" }, "floor", value); if (field === "floor-reset") return void this._setScopedExtremumReset({ type: "card" }, "floor", 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-peak-direction") { return void this._setMarkerDirection({ type: "entity", index: Number(target.dataset.index) }, "peak", value); } if (kind === "entity-peak-reset") { return void this._setScopedExtremumReset({ type: "entity", index: Number(target.dataset.index) }, "peak", value); } const entityLabelMatch = kind == null ? void 0 : kind.match(/^entity-(target|peak|floor)-label-(show|text|show-value|show-unit|precision)$/); if (entityLabelMatch) { const [, key, option] = entityLabelMatch; const scope = { type: "entity", index: Number(target.dataset.index) }; if (option === "show") { this._setBuiltinMarkerLabelField(scope, key, "show", value); } else { this._setBuiltinMarkerLabelField(scope, key, option === "show-value" ? "showValue" : option === "show-unit" ? "showUnit" : option, value); } return; } if (kind === "entity-floor-inherit") { if (value) return void this._clearFloorOverride({ type: "entity", index: Number(target.dataset.index) }); return; } if (kind === "entity-floor-enabled") { return void this._setScopedExtremumEnabled({ type: "entity", index: Number(target.dataset.index) }, "floor", value); } if (kind === "entity-floor-color") { return void this._setScopedExtremumColor({ type: "entity", index: Number(target.dataset.index) }, "floor", value); } if (kind === "entity-floor-direction") { return void this._setMarkerDirection({ type: "entity", index: Number(target.dataset.index) }, "floor", value); } if (kind === "entity-floor-reset") { return void this._setScopedExtremumReset({ type: "entity", index: Number(target.dataset.index) }, "floor", 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-shape") { return void this._setTargetShape({ type: "entity", index: Number(target.dataset.index) }, value); } if (kind === "entity-target-direction") { return void this._setMarkerDirection({ type: "entity", index: Number(target.dataset.index) }, "target", 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-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(); })();