@@ -6,6 +6,7 @@ class WAKnob extends HTMLElement {
6
6
private _min : number = 0 ;
7
7
private _max : number = 127 ;
8
8
private _default : number = 0 ;
9
+ private _defaultExplicitlySet : boolean = false ;
9
10
10
11
static get observedAttributes ( ) {
11
12
return [ 'value' , 'min' , 'max' , 'default' ] ;
@@ -22,10 +23,9 @@ class WAKnob extends HTMLElement {
22
23
}
23
24
24
25
set value ( val : number ) {
25
- const newValue = this . constrainValue ( val ) ;
26
+ const newValue = this . _constrainValue ( val ) ;
26
27
if ( newValue !== this . _value ) {
27
28
this . _value = newValue ;
28
- this . setAttribute ( 'value' , newValue . toString ( ) ) ;
29
29
this . render ( ) ;
30
30
}
31
31
}
@@ -35,42 +35,111 @@ class WAKnob extends HTMLElement {
35
35
}
36
36
37
37
set min ( val : number ) {
38
- this . _min = val ;
39
- this . value = this . _value ; // Recheck constraints
38
+ // only set if there is a change
39
+ if ( val !== this . _min ) {
40
+ this . _min = val ;
41
+ // Update default if it wasn't explicitly set
42
+ if ( ! this . _defaultExplicitlySet ) {
43
+ this . _default = val ;
44
+ }
45
+ // Recheck value constraints
46
+ this . value = this . _value ;
47
+ this . render ( ) ;
48
+ }
40
49
}
41
50
42
51
get max ( ) {
43
52
return this . _max ;
44
53
}
45
54
46
55
set max ( val : number ) {
47
- this . _max = val ;
48
- this . value = this . _value ; // Recheck constraints
56
+ if ( val !== this . _max ) {
57
+ this . _max = val ;
58
+ // Recheck value constraints
59
+ this . value = this . _value ;
60
+ }
49
61
}
50
62
51
63
get default ( ) {
52
64
return this . _default ;
53
65
}
54
66
55
67
set default ( val : number ) {
56
- this . _default = val ;
57
- if ( this . _value === 0 ) {
58
- this . value = val ;
68
+ const newValue = this . _constrainValue ( val ) ;
69
+ if ( newValue !== this . _default ) {
70
+ this . _default = newValue ;
71
+ this . _defaultExplicitlySet = true ;
72
+ this . render ( ) ;
59
73
}
60
74
}
61
75
62
- private constrainValue ( val : number ) : number {
76
+ private _constrainValue ( val : number ) : number {
63
77
return Math . min ( this . _max , Math . max ( this . _min , val ) ) ;
64
78
}
65
79
80
+ attributeChangedCallback ( name : string , oldValue : string | null , newValue : string | null ) {
81
+ if ( oldValue === newValue ) return ;
82
+
83
+ const numValue = parseFloat ( newValue || '0' ) ;
84
+ const constrainedValue = this . _constrainValue ( numValue ) ;
85
+
86
+ switch ( name ) {
87
+ case 'value' :
88
+ if ( constrainedValue !== numValue ) {
89
+ // If the value was constrained, update the attribute
90
+ this . setAttribute ( 'value' , constrainedValue . toString ( ) ) ;
91
+ } else {
92
+ this . value = numValue ;
93
+ }
94
+ break ;
95
+ case 'min' :
96
+ this . min = numValue ;
97
+ break ;
98
+ case 'max' :
99
+ this . max = numValue ;
100
+ break ;
101
+ case 'default' :
102
+ this . default = numValue ;
103
+ break ;
104
+ }
105
+ }
106
+
107
+ connectedCallback ( ) {
108
+ // Initialize from attributes if present
109
+ if ( this . hasAttribute ( 'min' ) ) {
110
+ this . min = parseFloat ( this . getAttribute ( 'min' ) || '0' ) ;
111
+ }
112
+ if ( this . hasAttribute ( 'max' ) ) {
113
+ this . max = parseFloat ( this . getAttribute ( 'max' ) || '127' ) ;
114
+ }
115
+ if ( this . hasAttribute ( 'default' ) ) {
116
+ this . default = parseFloat ( this . getAttribute ( 'default' ) || this . _min . toString ( ) ) ;
117
+ } else {
118
+ // If no default attribute, use min
119
+ this . _default = this . _min ;
120
+ }
121
+ if ( this . hasAttribute ( 'value' ) ) {
122
+ this . value = parseFloat ( this . getAttribute ( 'value' ) || this . _default . toString ( ) ) ;
123
+ } else {
124
+ // If no value attribute, use default
125
+ this . value = this . _default ;
126
+ }
127
+
128
+ // Set initial attributes for HTML use
129
+ this . setAttribute ( 'value' , this . _value . toString ( ) ) ;
130
+ this . setAttribute ( 'min' , this . _min . toString ( ) ) ;
131
+ this . setAttribute ( 'max' , this . _max . toString ( ) ) ;
132
+ this . setAttribute ( 'default' , this . _default . toString ( ) ) ;
133
+ }
134
+
66
135
private render ( ) {
67
136
if ( ! this . shadowRoot ) return ;
68
137
69
138
// Calculate rotation angle based on value
70
139
const range = this . _max - this . _min ;
71
140
const normalizedValue = ( this . _value - this . _min ) / range ;
72
141
const angle = normalizedValue * 270 - 135 ; // -135 to +135 degrees range
73
-
142
+
74
143
this . shadowRoot . innerHTML = `
75
144
<style>
76
145
.knob-body {
@@ -115,42 +184,6 @@ class WAKnob extends HTMLElement {
115
184
</div>
116
185
` ;
117
186
}
118
-
119
- attributeChangedCallback ( name : string , oldValue : string | null , newValue : string | null ) {
120
- if ( oldValue === newValue ) return ;
121
-
122
- switch ( name ) {
123
- case 'value' : {
124
- const val = parseFloat ( newValue || '0' ) ;
125
- const constrained = this . constrainValue ( val ) ;
126
- this . _value = constrained ;
127
- this . setAttribute ( 'value' , constrained . toString ( ) ) ;
128
- this . render ( ) ;
129
- break ;
130
- }
131
- case 'min' :
132
- this . min = parseFloat ( newValue || '0' ) ;
133
- break ;
134
- case 'max' :
135
- this . max = parseFloat ( newValue || '127' ) ;
136
- break ;
137
- case 'default' :
138
- this . default = parseFloat ( newValue || '0' ) ;
139
- break ;
140
- }
141
- }
142
-
143
- connectedCallback ( ) {
144
- // Set to default value if no value was specified
145
- if ( this . _value === 0 && this . _default !== 0 ) {
146
- this . value = this . _default ;
147
- }
148
- this . setAttribute ( 'value' , this . _value . toString ( ) ) ;
149
- this . setAttribute ( 'default' , this . _default . toString ( ) ) ;
150
- this . setAttribute ( 'min' , this . _min . toString ( ) ) ;
151
- this . setAttribute ( 'max' , this . _max . toString ( ) ) ;
152
- this . render ( ) ;
153
- }
154
187
}
155
188
156
189
customElements . define ( 'wa-knob' , WAKnob ) ;
0 commit comments