11import type { ReactiveElement } from "lit" ;
2+ import type { HomeAssistant } from "../types" ;
3+ import {
4+ setupMediaQueryListeners ,
5+ setupTimeListeners ,
6+ } from "../common/condition/listeners" ;
27
38type Constructor < T > = abstract new ( ...args : any [ ] ) => T ;
49
@@ -10,13 +15,14 @@ type Constructor<T> = abstract new (...args: any[]) => T;
1015 *
1116 * Usage:
1217 * 1. Extend your component with ConditionalListenerMixin(ReactiveElement)
13- * 2. Override setupConditionalListeners() to setup your listeners
14- * 3. Use addConditionalListener () to register unsubscribe functions
15- * 4. Call clearConditionalListeners () and setupConditionalListeners() when config changes
18+ * 2. Ensure component has config.visibility or _config.visibility property with conditions
19+ * 3. Ensure component has _updateVisibility () or _updateElement() method
20+ * 4. Override setupConditionalListeners () if custom behavior needed (e.g., filter conditions)
1621 *
1722 * The mixin automatically:
1823 * - Sets up listeners when component connects to DOM
1924 * - Cleans up listeners when component disconnects from DOM
25+ * - Handles both media query and time-based conditional visibility
2026 */
2127export const ConditionalListenerMixin = <
2228 T extends Constructor < ReactiveElement > ,
@@ -26,6 +32,9 @@ export const ConditionalListenerMixin = <
2632 abstract class ConditionalListenerClass extends superClass {
2733 private __listeners : ( ( ) => void ) [ ] = [ ] ;
2834
35+ // Type hint for hass property (should be provided by subclass)
36+ abstract hass ?: HomeAssistant ;
37+
2938 public connectedCallback ( ) {
3039 super . connectedCallback ( ) ;
3140 this . setupConditionalListeners ( ) ;
@@ -45,8 +54,52 @@ export const ConditionalListenerMixin = <
4554 this . __listeners . push ( unsubscribe ) ;
4655 }
4756
48- protected setupConditionalListeners ( ) : void {
49- // Override in subclass
57+ /**
58+ * Setup conditional listeners for visibility control
59+ *
60+ * Default implementation:
61+ * - Checks config.visibility or _config.visibility for conditions (if not provided)
62+ * - Sets up media query listeners
63+ * - Sets up time-based listeners
64+ * - Calls _updateVisibility() or _updateElement() when conditions change
65+ *
66+ * Override this method to customize behavior (e.g., filter conditions first)
67+ * and call super.setupConditionalListeners(customConditions) to reuse the base implementation
68+ *
69+ * @param conditions - Optional conditions array. If not provided, will check config.visibility or _config.visibility
70+ */
71+ protected setupConditionalListeners ( conditions ?: any [ ] ) : void {
72+ const component = this as any ;
73+ const finalConditions =
74+ conditions ||
75+ component . config ?. visibility ||
76+ component . _config ?. visibility ;
77+
78+ if ( ! finalConditions || ! this . hass ) {
79+ return ;
80+ }
81+
82+ const onUpdate = ( conditionsMet : boolean ) => {
83+ if ( component . _updateVisibility ) {
84+ component . _updateVisibility ( conditionsMet ) ;
85+ } else if ( component . _updateElement ) {
86+ component . _updateElement ( conditionsMet ) ;
87+ }
88+ } ;
89+
90+ setupMediaQueryListeners (
91+ finalConditions ,
92+ this . hass ,
93+ ( unsub ) => this . addConditionalListener ( unsub ) ,
94+ onUpdate
95+ ) ;
96+
97+ setupTimeListeners (
98+ finalConditions ,
99+ this . hass ,
100+ ( unsub ) => this . addConditionalListener ( unsub ) ,
101+ onUpdate
102+ ) ;
50103 }
51104 }
52105 return ConditionalListenerClass ;
0 commit comments