@@ -9,6 +9,12 @@ function object_map(obj, expr) {
99 if ( obj == null ) return { }
1010 return Object . fromEntries ( Object . entries ( obj ) . map ( ( [ k , v ] ) => [ k , expr ( k , v ) ] ) )
1111}
12+ function is_categorical ( v ) {
13+ return typeof v === 'string' ||
14+ typeof v === 'boolean' ||
15+ typeof v === 'symbol' ||
16+ typeof v === 'object' && typeof v . valueOf ( ) !== 'number' && typeof v . valueOf ( ) !== 'bigint'
17+ }
1218
1319/**
1420 * Graphic Layer object
@@ -68,9 +74,9 @@ class GLayer {
6874 if ( $$data == null ) $$data = $data
6975 $$aes = { ...$aes , ...$$aes }
7076 let data = { }
71- let fns = { } // function names for legend titles
77+ this . $fnames = { } // function names for legend titles
7278 for ( const aes in $$aes ) {
73- fns [ aes ] = String ( $$aes [ aes ] )
79+ this . $fnames [ aes ] = String ( $$aes [ aes ] )
7480 data [ aes ] = $$data . map ( $$aes [ aes ] )
7581 }
7682 data . $raw = $$data
@@ -119,21 +125,18 @@ class GLayer {
119125 ] )
120126
121127 this . $data = data
122- this . $fns = fns
123128 this . data = { ...data }
124129 for ( const aes in data ) {
125130 if ( $$scales [ aes ] != null ) {
126131 let scale = new Scale ( $$scales [ aes ] )
127132 scale . aesthetics = aes
128- if ( scale . title === undefined ) {
129- scale . title = fns [ aes ]
130- }
133+ scale . _title = this . $fnames [ aes ]
131134 let values = this . $data [ aes ]
132135 if ( ! values ?. length ) continue
133136 if ( ! scale . asis ) {
134137 if ( $$levels ?. [ aes ] != null ) {
135138 scale . level = $$levels [ aes ]
136- } else if ( values . some ( v => typeof v === 'string' ) ) {
139+ } else if ( values . some ( is_categorical ) ) {
137140 scale . level = GEnumLevel . from ( values )
138141 } else {
139142 scale . extent = numutils . extent ( values )
@@ -208,15 +211,13 @@ export class GPlot {
208211 if ( ! scale . asis ) {
209212 if ( levels ?. [ aes ] != null ) {
210213 scale . level = levels [ aes ]
211- } else if ( values . some ( v => typeof v === 'string' ) ) {
214+ } else if ( values . some ( is_categorical ) ) {
212215 scale . level = GEnumLevel . from ( values )
213216 } else {
214217 scale . extent = numutils . extent ( values )
215218 }
216219 }
217- if ( scale . title == null ) {
218- scale . title = this . layers . map ( layer => layer . $fns ?. [ aes ] ) . find ( s => s != null )
219- }
220+ scale . _title = this . layers . reduce ( ( v , layer ) => v ?? layer . $fnames ?. [ aes ] , null )
220221 for ( const layer of this . layers ) {
221222 if ( ! layer . localScales . has ( aes ) ) {
222223 layer . applyScale ( aes , scale )
@@ -252,7 +253,7 @@ export class GPlot {
252253 let fn = vvgeom [ layer . geom ] . get_values ?? vvgeom [ layer . geom ] . get_range
253254 return fn ?. ( layer . $data , aes )
254255 } )
255- if ( values . some ( v => typeof v === 'string' ) ) {
256+ if ( values . some ( is_categorical ) ) {
256257 this . levels [ aes ] = GEnumLevel . from ( values )
257258 } else {
258259 values = this . layers . flatMap ( layer => vvgeom [ layer . geom ] . get_range ?. ( layer . $data , aes ) ) . filter ( v => ! isNaN ( v ) )
@@ -373,6 +374,9 @@ export class Scale extends Function {
373374 max = this . $limits ?. max ?? this . level ?. length ?? this . _limits ?. max
374375 return { 0 : min , 1 : max , length : 2 , min, max }
375376 }
377+ toString ( ) {
378+ return this . title ?? String ( this . _fn )
379+ }
376380}
377381
378382class DiscreteCoordScale extends Function {
0 commit comments