@@ -12,15 +12,68 @@ type Props = {
1212const FormGroup = styled . div `
1313 display: flex;
1414 margin-bottom: 1rem;
15- width: 480px;
16- & > label {
17- width: 20%;
18- }
19- & > input {
15+ min-width: 480px;
16+ & > div {
2017 flex-grow: 1;
18+ margin-left: 0.25rem;
2119 }
2220` ;
2321
22+ class Color {
23+ public r : number ;
24+ public g : number ;
25+ public b : number ;
26+ public a : number ;
27+
28+ constructor ( r : number , g : number , b : number , a : number ) {
29+ this . r = r ;
30+ this . g = g ;
31+ this . b = b ;
32+ this . a = a ;
33+ }
34+
35+ // from #rrggbb
36+ static fromRGBCode ( rgb : string ) : Color {
37+ return new Color (
38+ parseInt ( rgb . substr ( 1 , 2 ) , 16 ) ,
39+ parseInt ( rgb . substr ( 3 , 2 ) , 16 ) ,
40+ parseInt ( rgb . substr ( 5 , 2 ) , 16 ) ,
41+ 1 ,
42+ ) ;
43+ }
44+
45+ // from rgba(r,g,b,a)
46+ static fromRGBA ( rgba : string ) : Color {
47+ const match = rgba . match ( / r g b a \( ( \d + ) , ( \d + ) , ( \d + ) , ( \d ( \. \d + ) ? ) \) / ) ;
48+ return new Color (
49+ parseInt ( match [ 1 ] ) ,
50+ parseInt ( match [ 2 ] ) ,
51+ parseInt ( match [ 3 ] ) ,
52+ parseFloat ( match [ 4 ] )
53+ ) ;
54+ }
55+
56+ toRGBA ( ) : string {
57+ const rgba = [ this . r , this . g , this . b , this . a ] ;
58+ return `rgba(${ rgba . join ( ',' ) } )` ;
59+ }
60+
61+ toRGBCode ( ) : string {
62+ function toHex ( num ) : string {
63+ let res = num . toString ( 16 ) ;
64+ if ( res . length === 1 ) {
65+ res = `0${ res } ` ;
66+ }
67+ return res ;
68+ }
69+ const r = toHex ( this . r ) ;
70+ const g = toHex ( this . g ) ;
71+ const b = toHex ( this . b ) ;
72+
73+ return `#${ r } ${ g } ${ b } ` ;
74+ }
75+ }
76+
2477class TextWidgetEditor extends Component < Props , TextWidgetProps > {
2578 constructor ( props ) {
2679 super ( props ) ;
@@ -46,6 +99,180 @@ class TextWidgetEditor extends Component<Props, TextWidgetProps> {
4699 value = { this . state . text }
47100 />
48101 </ FormGroup >
102+ < FormGroup >
103+ < TextField
104+ type = "text"
105+ label = "text size"
106+ fullWidth
107+ variant = "outlined"
108+ onChange = { ( e ) => {
109+ this . setState ( { ...this . state , fontSize : e . target . value } ) ;
110+ } }
111+ value = { this . state . fontSize }
112+ />
113+ < TextField
114+ type = "color"
115+ label = "text color"
116+ fullWidth
117+ variant = "outlined"
118+ onChange = { ( e ) => {
119+ this . setState ( { ...this . state , textColor : e . target . value } ) ;
120+ } }
121+ value = { this . state . textColor }
122+ />
123+ < TextField
124+ type = "number"
125+ label = "text edge weight"
126+ fullWidth
127+ variant = "outlined"
128+ onChange = { ( e ) => {
129+ this . setState ( { ...this . state , edgeWeight : parseFloat ( e . target . value ) } ) ;
130+ } }
131+ value = { this . state . edgeWeight }
132+ />
133+ < TextField
134+ type = "color"
135+ label = "text edge color"
136+ fullWidth
137+ variant = "outlined"
138+ onChange = { ( e ) => {
139+ this . setState ( { ...this . state , edgeColor : e . target . value } ) ;
140+ } }
141+ value = { this . state . edgeColor }
142+ />
143+ < TextField
144+ type = "color"
145+ label = "background color"
146+ fullWidth
147+ variant = "outlined"
148+ onChange = { ( e ) => {
149+ const color = Color . fromRGBA ( this . state . backgroundColor ) ;
150+ const newColor = Color . fromRGBCode ( e . target . value ) ;
151+ newColor . a = color . a ;
152+ this . setState ( { ...this . state , backgroundColor : newColor . toRGBA ( ) } ) ;
153+ } }
154+ value = { Color . fromRGBA ( this . state . backgroundColor ) . toRGBCode ( ) }
155+ />
156+ < TextField
157+ type = "number"
158+ label = "background opacity"
159+ fullWidth
160+ variant = "outlined"
161+ onChange = { ( e ) => {
162+ const color = Color . fromRGBA ( this . state . backgroundColor )
163+ color . a = parseFloat ( e . target . value ) ;
164+ this . setState ( { ...this . state , backgroundColor : color . toRGBA ( ) } ) ;
165+ } }
166+ value = { Color . fromRGBA ( this . state . backgroundColor ) . a }
167+ />
168+ </ FormGroup >
169+ < FormGroup >
170+ < TextField
171+ type = "number"
172+ label = "width"
173+ fullWidth
174+ variant = "outlined"
175+ onChange = { ( e ) => {
176+ this . setState ( { ...this . state , width : parseFloat ( e . target . value ) } ) ;
177+ } }
178+ value = { this . state . width }
179+ />
180+ < TextField
181+ type = "number"
182+ label = "height"
183+ fullWidth
184+ variant = "outlined"
185+ onChange = { ( e ) => {
186+ this . setState ( { ...this . state , height : parseFloat ( e . target . value ) } ) ;
187+ } }
188+ value = { this . state . height }
189+ />
190+
191+ < TextField
192+ type = "number"
193+ label = "position top"
194+ fullWidth
195+ variant = "outlined"
196+ onChange = { ( e ) => {
197+ const pos = this . state . position || { } ;
198+ if ( e . target . value !== "" ) {
199+ const v = parseInt ( e . target . value ) ;
200+ if ( isNaN ( v ) ) {
201+ delete pos . top ;
202+ } else {
203+ pos . top = v ;
204+ }
205+ } else {
206+ delete pos . top ;
207+ }
208+ this . setState ( { ...this . state , position : pos } ) ;
209+ } }
210+ value = { this . state ?. position ?. top }
211+ />
212+ < TextField
213+ type = "number"
214+ label = "position right"
215+ fullWidth
216+ variant = "outlined"
217+ onChange = { ( e ) => {
218+ const pos = this . state . position || { } ;
219+ if ( e . target . value !== "" ) {
220+ const v = parseInt ( e . target . value ) ;
221+ if ( isNaN ( v ) ) {
222+ delete pos . right ;
223+ } else {
224+ pos . right = v ;
225+ }
226+ } else {
227+ delete pos . right ;
228+ }
229+ this . setState ( { ...this . state , position : pos } ) ;
230+ } }
231+ value = { this . state . position ?. right }
232+ />
233+ < TextField
234+ type = "number"
235+ label = "position bottom"
236+ fullWidth
237+ variant = "outlined"
238+ onChange = { ( e ) => {
239+ const pos = this . state . position || { } ;
240+ if ( e . target . value !== "" ) {
241+ const v = parseInt ( e . target . value ) ;
242+ if ( isNaN ( v ) ) {
243+ delete pos . bottom ;
244+ } else {
245+ pos . bottom = v ;
246+ }
247+ } else {
248+ delete pos . bottom ;
249+ }
250+ this . setState ( { ...this . state , position : pos } ) ;
251+ } }
252+ value = { this . state . position ?. bottom }
253+ />
254+ < TextField
255+ type = "number"
256+ label = "position left"
257+ fullWidth
258+ variant = "outlined"
259+ onChange = { ( e ) => {
260+ const pos = this . state . position || { } ;
261+ if ( e . target . value !== "" ) {
262+ const v = parseInt ( e . target . value ) ;
263+ if ( isNaN ( v ) ) {
264+ delete pos . left ;
265+ } else {
266+ pos . left = v ;
267+ }
268+ } else {
269+ delete pos . left ;
270+ }
271+ this . setState ( { ...this . state , position : pos } ) ;
272+ } }
273+ value = { this . state . position ?. left }
274+ />
275+ </ FormGroup >
49276
50277 < FirebaseDatabaseMutation
51278 type = "set"
0 commit comments