@kipk/ha-better-history 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ import { LitElement, type PropertyValues, type TemplateResult } from "lit";
2
+ import type { AttributeUnitMap, BetterHistoryConfig, BetterHistoryLineMode } from "./types/config.js";
3
+ import type { HomeAssistant } from "./types/ha.js";
4
+ export declare class HaBetterHistory extends LitElement {
5
+ static styles: import("lit").CSSResult;
6
+ hass?: HomeAssistant;
7
+ config?: BetterHistoryConfig;
8
+ entities?: string[];
9
+ attributeUnits?: AttributeUnitMap;
10
+ hours: number;
11
+ startDate?: Date;
12
+ endDate?: Date;
13
+ showDatePicker: boolean;
14
+ showEntityPicker: boolean;
15
+ showImportButton: boolean;
16
+ showLegend: boolean;
17
+ showTooltip: boolean;
18
+ showControls: boolean;
19
+ width?: string;
20
+ height?: string;
21
+ lineMode?: BetterHistoryLineMode;
22
+ lineWidth?: string;
23
+ backgroundColor?: string;
24
+ graphTitle?: string;
25
+ titleFontFamily?: string;
26
+ titleFontSize?: string;
27
+ titleColor?: string;
28
+ language?: string;
29
+ debugPerformance: boolean;
30
+ toolsOpen: boolean;
31
+ private _resolved?;
32
+ private _hiddenSeriesIds;
33
+ private _rangeStart?;
34
+ private _rangeEnd?;
35
+ private _viewStart?;
36
+ private _viewEnd?;
37
+ private _liveNow;
38
+ private _datePickerReady;
39
+ private _entityComponentsReady;
40
+ private _runtimeLineMode?;
41
+ private _attributeMenuOpen;
42
+ private _attributeSearch;
43
+ private _selectedEntityId?;
44
+ private _path;
45
+ private _selectedSources;
46
+ private _customEntityIds;
47
+ private _entityPickerOpen;
48
+ private _draggingSourceId?;
49
+ private readonly _data;
50
+ private readonly _tooltip;
51
+ private _chartRenderCache?;
52
+ private _graphGroupRenderCache?;
53
+ private _prevClipX;
54
+ private _prevStartTime;
55
+ private _prevEndTime;
56
+ private _prevContainerWidth;
57
+ private _wasLoading;
58
+ private _suppressLineAnimation;
59
+ private _pendingAddedSources;
60
+ private _sourceAddBatchTimer?;
61
+ private _liveNowTimer?;
62
+ private _dragStartSourceIds?;
63
+ private _dragDropCommitted;
64
+ private _lastPickerOverlayOpen;
65
+ private _importedSeriesMeta;
66
+ private _importedDataActive;
67
+ private _containerWidth;
68
+ private _resizeObserver?;
69
+ connectedCallback(): void;
70
+ disconnectedCallback(): void;
71
+ private _maxXTicks;
72
+ private _effectiveStartDate;
73
+ private _effectiveEndDate;
74
+ private _requestedEndDate;
75
+ private _rangeExtendsFuture;
76
+ private _syncLiveClock;
77
+ private _stopLiveClock;
78
+ private _effectiveLineMode;
79
+ private _effectiveViewRange;
80
+ private _pickerEntities;
81
+ private _fetchSources;
82
+ private _isDefaultSource;
83
+ private _resolvedTemperatureUnit;
84
+ private _lastFetchKey;
85
+ private _lastFetchSources;
86
+ private _lastHassResolveTime;
87
+ protected willUpdate(changed: PropertyValues): void;
88
+ protected updated(changed: PropertyValues): void;
89
+ private _emitPickerOverlayState;
90
+ private _onDateRangeChanged;
91
+ private _pickScaleGroup;
92
+ private _defaultLineMode;
93
+ private _defaultLineWidth;
94
+ private _showImportButton;
95
+ private _buildRenderSeries;
96
+ private _chartSourceKey;
97
+ private _chartData;
98
+ private _graphGroups;
99
+ private _renderGraphGroup;
100
+ private _animateClipPaths;
101
+ private _renderChartBody;
102
+ private readonly _getEntityPickerItems;
103
+ private readonly _getAdditionalEntityPickerItems;
104
+ private _renderEntityPickerUI;
105
+ private _rangePercent;
106
+ private _loadedRangeMs;
107
+ private _minViewSpanMs;
108
+ private _setViewRangeMs;
109
+ private _dateFromRangePercent;
110
+ private _formatRangeDate;
111
+ private _setViewRangePart;
112
+ private _onRangeSelectionPointerDown;
113
+ private _resetViewRange;
114
+ private _setRuntimeLineMode;
115
+ private _exportData;
116
+ private _importData;
117
+ private _applyImportedData;
118
+ private _isExportPayload;
119
+ private _parseImportedSeries;
120
+ private _parseImportedPoint;
121
+ private _parseDate;
122
+ private _renderToolsPanel;
123
+ render(): TemplateResult;
124
+ private _toggleSeries;
125
+ private _renderDatePicker;
126
+ private _positionEntityMenu;
127
+ private _closeAttributeMenu;
128
+ private _onEntitySelected;
129
+ private _onEntityPickerOpened;
130
+ private _onEntityPickerClosed;
131
+ private _handleDocumentPointerDown;
132
+ private _handleDocumentClick;
133
+ private _isEventInsideAttributeOverlay;
134
+ private _sourceWithAttributeUnit;
135
+ private _addSource;
136
+ private _flushPendingAddedSources;
137
+ private _removeSource;
138
+ private _onSourceDragStart;
139
+ private _onSourceDragEnd;
140
+ private _onSourceDragOver;
141
+ private _onSourceDrop;
142
+ private _previewSourceOrder;
143
+ }
@@ -0,0 +1,5 @@
1
+ export { HaBetterHistory } from "./ha-better-history.js";
2
+ export { type BetterHistoryConfig, type BetterHistoryLineMode, type SeriesConfig, type ResolvedConfig, type ResolvedSeries, type AttributeUnitMap } from "./types/config.js";
3
+ export { type HistorySource, type HistorySeries, type HistoryPoint, type HistoryValueType } from "./data/history.js";
4
+ export { type HomeAssistant, type HassEntity } from "./types/ha.js";
5
+ export { type TooltipValue, type TooltipState } from "./controllers/tooltip-controller.js";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./ha-better-history-BY4eqV1H.js";
2
+ export { e as HaBetterHistory };
@@ -0,0 +1,2 @@
1
+ export declare function ensureHaComponents(): Promise<void>;
2
+ export declare function ensureDateRangePicker(): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { HomeAssistant } from "../types/ha.js";
2
+ export declare function localize(hass: HomeAssistant | undefined, key: string): string;
@@ -0,0 +1,109 @@
1
+ import { type NumericScale } from "./scales.js";
2
+ import { type HeatingAreaRenderData } from "./climate-overlay.js";
3
+ import type { HistoryPoint } from "../data/history.js";
4
+ import type { HistoryValueType } from "../data/value-type.js";
5
+ import type { BetterHistoryLineMode } from "../types/config.js";
6
+ export declare const CHART_WIDTH = 720;
7
+ export declare const PLOT_LEFT = 40;
8
+ export declare const PLOT_RIGHT = 680;
9
+ export declare const PLOT_WIDTH: number;
10
+ export declare const PLOT_TOP = 18;
11
+ export declare const SEGMENT_ROW_HEIGHT = 14;
12
+ export declare const SEGMENT_HEIGHT = 9;
13
+ export interface RenderableSeries {
14
+ id: string;
15
+ label: string;
16
+ color: string;
17
+ unit?: string;
18
+ scaleGroupKey: string;
19
+ scaleMode: "auto" | "manual";
20
+ scaleMin?: number;
21
+ scaleMax?: number;
22
+ lineMode: BetterHistoryLineMode;
23
+ lineWidth: string;
24
+ valueType: HistoryValueType;
25
+ points: HistoryPoint[];
26
+ }
27
+ export interface NumericLineRenderData {
28
+ id: string;
29
+ color: string;
30
+ points: string;
31
+ pathLength: number;
32
+ lineWidth: string;
33
+ }
34
+ export interface NumericColumnRenderData {
35
+ id: string;
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ fill: string;
41
+ }
42
+ export interface SegmentRenderData {
43
+ id: string;
44
+ x: number;
45
+ y: number;
46
+ width: number;
47
+ fill: string;
48
+ }
49
+ export interface YAxisLabelRenderData {
50
+ y: number;
51
+ value: string;
52
+ }
53
+ export interface XAxisLabelRenderData {
54
+ x: number;
55
+ label: string;
56
+ bold?: boolean;
57
+ }
58
+ export interface ChartRenderData {
59
+ allSeries: RenderableSeries[];
60
+ visibleSeries: RenderableSeries[];
61
+ timeBounds: {
62
+ start: number;
63
+ end: number;
64
+ };
65
+ extendStairToEnd: boolean;
66
+ numericScales: NumericScale[];
67
+ plotBottom: number;
68
+ chartHeight: number;
69
+ numericLines: NumericLineRenderData[];
70
+ numericColumns: NumericColumnRenderData[];
71
+ segments: SegmentRenderData[];
72
+ heatingAreas: HeatingAreaRenderData[];
73
+ yAxisLabels: YAxisLabelRenderData[];
74
+ xAxisLabels: XAxisLabelRenderData[];
75
+ }
76
+ export interface GraphGroup {
77
+ series: RenderableSeries[];
78
+ allSeries: RenderableSeries[];
79
+ scale?: NumericScale;
80
+ scales: NumericScale[];
81
+ svgHeight: number;
82
+ canvasHeight: number;
83
+ lines: NumericLineRenderData[];
84
+ columns: NumericColumnRenderData[];
85
+ segments: SegmentRenderData[];
86
+ yLabels: YAxisLabelRenderData[];
87
+ rightYLabels: YAxisLabelRenderData[];
88
+ xLabels: XAxisLabelRenderData[];
89
+ heatingAreas: HeatingAreaRenderData[];
90
+ }
91
+ export declare function xFor(time: number, bounds: {
92
+ start: number;
93
+ end: number;
94
+ }): number;
95
+ export declare function yFor(value: number, scale: NumericScale): number;
96
+ export declare function scaleFor(series: RenderableSeries, scales: NumericScale[]): NumericScale | undefined;
97
+ export declare function stateRanges(series: RenderableSeries, bounds: {
98
+ start: number;
99
+ end: number;
100
+ }): Array<{
101
+ start: number;
102
+ end: number;
103
+ value: number | string | boolean;
104
+ }>;
105
+ export declare function buildChartData(allSeries: RenderableSeries[], visibleSeries: RenderableSeries[], timeBounds: {
106
+ start: number;
107
+ end: number;
108
+ }, disableClimateOverlay?: boolean, maxXTicks?: number, extendStairToEnd?: boolean): ChartRenderData;
109
+ export declare function buildGraphGroups(data: ChartRenderData, maxXTicks?: number): GraphGroup[];
@@ -0,0 +1,10 @@
1
+ import { type RenderableSeries } from "./chart.js";
2
+ import { type NumericScale } from "./scales.js";
3
+ export interface HeatingAreaRenderData {
4
+ id: string;
5
+ points: string;
6
+ }
7
+ export declare function buildClimateHeatingAreas(visibleSeries: RenderableSeries[], scales: NumericScale[], bounds: {
8
+ start: number;
9
+ end: number;
10
+ }): HeatingAreaRenderData[];
@@ -0,0 +1,5 @@
1
+ export declare const PALETTE: string[];
2
+ export declare const CLIMATE_ATTR_COLORS: Record<string, string>;
3
+ export declare function paletteColor(index: number): string;
4
+ export declare function graphColor(preferred: string, used: Set<string>, index: number): string;
5
+ export declare function graphColorKey(color: string): string;
@@ -0,0 +1,8 @@
1
+ import type { HistoryPoint } from "../data/history.js";
2
+ export declare function displayNumericPoints(points: HistoryPoint[], bounds: {
3
+ start: number;
4
+ end: number;
5
+ }, plotLeft: number, plotWidth: number): Array<{
6
+ time: number;
7
+ value: number;
8
+ }>;
@@ -0,0 +1,40 @@
1
+ import type { HistoryPoint } from "../data/history.js";
2
+ import type { HistoryValueType } from "../data/value-type.js";
3
+ export interface NumericScale {
4
+ ids: Set<string>;
5
+ graphKey: string;
6
+ axis: "left" | "right";
7
+ min: number;
8
+ max: number;
9
+ precision: number;
10
+ top: number;
11
+ height: number;
12
+ ticks: number[];
13
+ }
14
+ interface ScaleInput {
15
+ id: string;
16
+ unit?: string;
17
+ scaleGroupKey: string;
18
+ scaleMode: "auto" | "manual";
19
+ scaleMin?: number;
20
+ scaleMax?: number;
21
+ valueType: HistoryValueType;
22
+ points: HistoryPoint[];
23
+ }
24
+ export declare const GRAPH_TOP = 28;
25
+ export declare const GRAPH_HEIGHT = 180;
26
+ export declare const GRAPH_GAP = 34;
27
+ export declare const GRAPH_STEP: number;
28
+ export declare const GRAPH_BOTTOM_PADDING = 18;
29
+ export declare const PLOT_PADDING = 5;
30
+ export declare function valuePrecision(value: number): number;
31
+ export declare function roundToPrecision(value: number, precision: number): number;
32
+ export declare function computeNiceTicks(min: number, max: number, desiredCount?: number): number[];
33
+ export declare function tickPrecision(ticks: number[]): number;
34
+ export declare function paddedRange(min: number, max: number, precision: number): {
35
+ min: number;
36
+ max: number;
37
+ };
38
+ export declare function plotBottomFor(numericScaleCount: number): number;
39
+ export declare function numericScalesFor(series: ScaleInput[]): NumericScale[];
40
+ export {};
@@ -0,0 +1 @@
1
+ export declare const chartStyles: import("lit").CSSResult;
@@ -0,0 +1,73 @@
1
+ import type { HistoryValueType } from "../data/value-type.js";
2
+ export type AttributeUnitMap = Record<string, string>;
3
+ export type BetterHistoryLineMode = "stair" | "line" | "column";
4
+ export interface SeriesConfig {
5
+ entity: string;
6
+ attribute?: string | string[];
7
+ label?: string;
8
+ color?: string;
9
+ unit?: string;
10
+ scaleGroup?: string;
11
+ scaleMode?: "auto" | "manual";
12
+ scaleMin?: number;
13
+ scaleMax?: number;
14
+ lineMode?: BetterHistoryLineMode;
15
+ lineWidth?: number | string;
16
+ }
17
+ export interface BetterHistoryConfig {
18
+ hours?: number;
19
+ startDate?: Date;
20
+ endDate?: Date;
21
+ showDatePicker?: boolean;
22
+ showEntityPicker?: boolean;
23
+ showImportButton?: boolean;
24
+ showLegend?: boolean;
25
+ showTooltip?: boolean;
26
+ width?: string;
27
+ height?: string;
28
+ lineMode?: BetterHistoryLineMode;
29
+ lineWidth?: number | string;
30
+ backgroundColor?: string;
31
+ title?: string;
32
+ titleFontFamily?: string;
33
+ titleFontSize?: string;
34
+ titleColor?: string;
35
+ series?: SeriesConfig[];
36
+ defaultEntities?: string[];
37
+ disableClimateOverlay?: boolean;
38
+ debugPerformance?: boolean;
39
+ attributeUnits?: AttributeUnitMap;
40
+ }
41
+ export interface ResolvedSeries {
42
+ id: string;
43
+ entity: string;
44
+ attribute?: string[];
45
+ label: string;
46
+ color: string;
47
+ unit?: string;
48
+ scaleGroupKey: string;
49
+ scaleMode: "auto" | "manual";
50
+ scaleMin?: number;
51
+ scaleMax?: number;
52
+ lineMode: BetterHistoryLineMode;
53
+ lineWidth: string;
54
+ valueType: HistoryValueType;
55
+ }
56
+ export interface ResolvedConfig {
57
+ startDate: Date;
58
+ endDate: Date;
59
+ showDatePicker: boolean;
60
+ showEntityPicker: boolean;
61
+ showLegend: boolean;
62
+ showTooltip: boolean;
63
+ width: string;
64
+ height: string | undefined;
65
+ backgroundColor: string | undefined;
66
+ title: string | undefined;
67
+ titleFontFamily: string | undefined;
68
+ titleFontSize: string | undefined;
69
+ titleColor: string | undefined;
70
+ language: string | undefined;
71
+ series: ResolvedSeries[];
72
+ disableClimateOverlay: boolean;
73
+ }
@@ -0,0 +1,18 @@
1
+ export interface HassEntity {
2
+ entity_id: string;
3
+ state: string;
4
+ attributes: Record<string, unknown>;
5
+ last_changed?: string;
6
+ last_updated?: string;
7
+ }
8
+ export interface HomeAssistant {
9
+ states: Record<string, HassEntity | undefined>;
10
+ language?: string;
11
+ locale?: {
12
+ language?: string;
13
+ };
14
+ localize?(key: string): string;
15
+ callApi?<T>(method: string, path: string, parameters?: Record<string, unknown>): Promise<T>;
16
+ callWS?<T>(message: Record<string, unknown>): Promise<T>;
17
+ callService(domain: string, service: string, serviceData?: Record<string, unknown>): Promise<unknown>;
18
+ }
@@ -0,0 +1,5 @@
1
+ import { type TemplateResult } from "lit";
2
+ import type { HomeAssistant } from "../types/ha.js";
3
+ export declare function datePickerAvailable(): boolean;
4
+ export declare function preloadDatePicker(): Promise<void>;
5
+ export declare function renderDatePicker(hass: HomeAssistant | undefined, startDate: Date, endDate: Date, onChange: (startDate: Date, endDate: Date) => void): TemplateResult;
@@ -0,0 +1,35 @@
1
+ import { type TemplateResult } from "lit";
2
+ import { type HistorySource } from "../data/history.js";
3
+ import type { HassEntity, HomeAssistant } from "../types/ha.js";
4
+ import type { ResolvedConfig } from "../types/config.js";
5
+ export declare function entityLabel(entity: HassEntity): string;
6
+ export declare function preloadEntityPickerComponents(): Promise<void>;
7
+ interface EntityPickerRenderOpts {
8
+ hass?: HomeAssistant;
9
+ menuOpen: boolean;
10
+ entityPickerOpen: boolean;
11
+ selectedEntityId?: string;
12
+ path: string[];
13
+ selectedSources: HistorySource[];
14
+ draggingSourceId?: string;
15
+ resolved?: ResolvedConfig;
16
+ loading: boolean;
17
+ attributeSearch: string;
18
+ getItems: () => unknown[];
19
+ getAdditionalItems: (search?: string) => unknown[];
20
+ onEntityPickerOpened(): void;
21
+ onEntityPickerClosed(): void;
22
+ onEntitySelected(entityId: string): void;
23
+ onAttributeSearchChanged(value: string): void;
24
+ onSourceAdded(source: HistorySource): void;
25
+ onSourceRemoved(sourceId: string): void;
26
+ onSourceDragStart(sourceId: string, event: DragEvent): void;
27
+ onSourceDragOver(sourceId: string | undefined, event: DragEvent): void;
28
+ onSourceDragEnd(): void;
29
+ onSourceDrop(sourceId: string | undefined, event: DragEvent): void;
30
+ onBreadcrumbClick(path: string[]): void;
31
+ onCloseMenu(): void;
32
+ }
33
+ export declare function entityPickerAvailable(): boolean;
34
+ export declare function renderEntityPicker(opts: EntityPickerRenderOpts): TemplateResult;
35
+ export {};
@@ -0,0 +1,3 @@
1
+ export type PerformanceDetails = Record<string, number | string | boolean | undefined>;
2
+ export declare function performanceNow(): number;
3
+ export declare function logPerformance(enabled: boolean, event: string, details: PerformanceDetails): void;
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@kipk/ha-better-history",
3
+ "version": "0.1.0",
4
+ "description": "Standalone web component for Home Assistant history charts.",
5
+ "type": "module",
6
+ "author": "@KipK",
7
+ "keywords": [
8
+ "home-assistant",
9
+ "lovelace",
10
+ "web-component",
11
+ "history",
12
+ "chart",
13
+ "lit"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/KipK/ha-better-history.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/KipK/ha-better-history/issues"
21
+ },
22
+ "homepage": "https://github.com/KipK/ha-better-history#readme",
23
+ "main": "dist/index.js",
24
+ "module": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "import": "./dist/index.js",
29
+ "types": "./dist/index.d.ts"
30
+ },
31
+ "./define": {
32
+ "import": "./dist/define.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "sideEffects": [
42
+ "dist/define.js"
43
+ ],
44
+ "scripts": {
45
+ "build": "vite build && tsc -p tsconfig.build.json",
46
+ "prepare": "npm run build",
47
+ "typecheck": "tsc --noEmit",
48
+ "dev": "vite --config vite.config.dev.ts"
49
+ },
50
+ "dependencies": {
51
+ "@kipk/load-ha-components": "^1.0.3",
52
+ "lit": "^3.3.2"
53
+ },
54
+ "devDependencies": {
55
+ "typescript": "^5.6.3",
56
+ "vite": "^8.0.10"
57
+ }
58
+ }