@@ -9,71 +9,78 @@ import {
99 DateToken ,
1010} from '@layerstack/utils' ;
1111import { isScaleBand , isScaleTime , type AnyScale } from './scales.svelte.js' ;
12+ import type { AxisProps } from '$lib/components/Axis.svelte' ;
13+
14+ export function getDurationFormat (
15+ duration : Duration ,
16+ options : { multiline ?: boolean ; placement ?: AxisProps [ 'placement' ] } = {
17+ multiline : false ,
18+ }
19+ ) {
20+ const { multiline = false , placement = 'bottom' } = options ;
1221
13- export function getDurationFormat ( duration : Duration , multiline = false ) {
1422 return function ( date : Date , i : number ) {
23+ let result : string | Array < string | false > = '' ;
24+
1525 if ( + duration >= + new Duration ( { duration : { years : 1 } } ) ) {
1626 // Year
17- return format ( date , 'year' ) ;
27+ result = format ( date , 'year' ) ;
1828 } else if ( + duration >= + new Duration ( { duration : { days : 28 } } ) ) {
1929 // Month
2030 const isFirst = i === 0 || + timeYear . floor ( date ) === + date ;
2131 if ( multiline ) {
22- return (
23- format ( date , 'month' , { variant : 'short' } ) + ( isFirst ? `\n${ format ( date , 'year' ) } ` : '' )
24- ) ;
32+ result = [ format ( date , 'month' , { variant : 'short' } ) , isFirst && format ( date , 'year' ) ] ;
2533 } else {
26- return (
34+ result =
2735 format ( date , 'month' , { variant : 'short' } ) +
28- ( isFirst ? ` '${ format ( date , 'year' , { variant : 'short' } ) } ` : '' )
29- ) ;
36+ ( isFirst ? ` '${ format ( date , 'year' , { variant : 'short' } ) } ` : '' ) ;
3037 }
3138 } else if ( + duration >= + new Duration ( { duration : { days : 1 } } ) ) {
3239 // Day
3340 const isFirst = i === 0 || date . getDate ( ) <= duration . days ;
3441 if ( multiline ) {
35- return (
36- format ( date , 'custom' , { custom : DateToken . DayOfMonth_numeric } ) +
37- ( isFirst ? `\n ${ format ( date , 'month' , { variant : 'short' } ) } ` : '' )
38- ) ;
42+ result = [
43+ format ( date , 'custom' , { custom : DateToken . DayOfMonth_numeric } ) ,
44+ isFirst && format ( date , 'month' , { variant : 'short' } ) ,
45+ ] ;
3946 } else {
40- return format ( date , 'day' , { variant : 'short' } ) ;
47+ result = format ( date , 'day' , { variant : 'short' } ) ;
4148 }
4249 } else if ( + duration >= + new Duration ( { duration : { hours : 1 } } ) ) {
4350 // Hours
4451 const isFirst = i === 0 || + timeDay . floor ( date ) === + date ;
4552 if ( multiline ) {
46- return (
47- format ( date , 'custom' , { custom : DateToken . Hour_numeric } ) +
48- ( isFirst ? `\n ${ format ( date , 'day' , { variant : 'short' } ) } ` : '' )
49- ) ;
53+ result = [
54+ format ( date , 'custom' , { custom : DateToken . Hour_numeric } ) ,
55+ isFirst && format ( date , 'day' , { variant : 'short' } ) ,
56+ ] ;
5057 } else {
51- return isFirst
58+ result = isFirst
5259 ? format ( date , 'day' , { variant : 'short' } )
5360 : format ( date , 'custom' , { custom : DateToken . Hour_numeric } ) ;
5461 }
5562 } else if ( + duration >= + new Duration ( { duration : { minutes : 1 } } ) ) {
5663 // Minutes
5764 const isFirst = i === 0 || + timeDay . floor ( date ) === + date ;
5865 if ( multiline ) {
59- return (
60- format ( date , 'time' , { variant : 'short' } ) +
61- ( isFirst ? `\n ${ format ( date , 'day' , { variant : 'short' } ) } ` : '' )
62- ) ;
66+ result = [
67+ format ( date , 'time' , { variant : 'short' } ) ,
68+ isFirst && format ( date , 'day' , { variant : 'short' } ) ,
69+ ] ;
6370 } else {
64- return format ( date , 'time' , { variant : 'short' } ) ;
71+ result = format ( date , 'time' , { variant : 'short' } ) ;
6572 }
6673 } else if ( + duration >= + new Duration ( { duration : { seconds : 1 } } ) ) {
6774 // Seconds
6875 const isFirst = i === 0 || + timeDay . floor ( date ) === + date ;
69- return (
70- format ( date , 'time' ) +
71- ( multiline && isFirst ? `\n ${ format ( date , 'day' , { variant : 'short' } ) } ` : '' )
72- ) ;
76+ result = [
77+ format ( date , 'time' ) ,
78+ multiline && isFirst && format ( date , 'day' , { variant : 'short' } ) ,
79+ ] ;
7380 } else if ( + duration >= + new Duration ( { duration : { milliseconds : 1 } } ) ) {
7481 // Milliseconds
7582 const isFirst = i === 0 || + timeDay . floor ( date ) === + date ;
76- return (
83+ result = [
7784 format ( date , 'custom' , {
7885 custom : [
7986 DateToken . Hour_2Digit ,
@@ -82,10 +89,28 @@ export function getDurationFormat(duration: Duration, multiline = false) {
8289 DateToken . MiliSecond_3 ,
8390 DateToken . Hour_woAMPM ,
8491 ] ,
85- } ) + ( multiline && isFirst ? `\n${ format ( date , 'day' , { variant : 'short' } ) } ` : '' )
86- ) ;
92+ } ) ,
93+ multiline && isFirst && format ( date , 'day' , { variant : 'short' } ) ,
94+ ] ;
95+ } else {
96+ result = date . toString ( ) ;
97+ }
98+
99+ if ( Array . isArray ( result ) ) {
100+ switch ( placement ) {
101+ case 'top' :
102+ return result . filter ( Boolean ) . reverse ( ) . join ( '\n' ) ;
103+ case 'bottom' :
104+ return result . filter ( Boolean ) . join ( '\n' ) ;
105+ case 'left' :
106+ return result . filter ( Boolean ) . reverse ( ) . join ( ' ' ) ;
107+ case 'right' :
108+ return result . filter ( Boolean ) . join ( ' ' ) ;
109+ default :
110+ return result . filter ( Boolean ) . join ( '\n' ) ;
111+ }
87112 } else {
88- return date . toString ( ) ;
113+ return result ;
89114 }
90115 } ;
91116}
@@ -127,13 +152,16 @@ export function resolveTickVals(scale: AnyScale, ticks?: TicksConfig, count?: nu
127152 return [ ] ;
128153}
129154
130- export function resolveTickFormat (
131- scale : AnyScale ,
132- ticks ?: TicksConfig ,
133- count ?: number ,
134- formatType ?: FormatType | FormatConfig ,
135- multiline = false
136- ) {
155+ export function resolveTickFormat ( options : {
156+ scale : AnyScale ;
157+ ticks ?: TicksConfig ;
158+ count ?: number ;
159+ formatType ?: FormatType | FormatConfig ;
160+ multiline ?: boolean ;
161+ placement ?: AxisProps [ 'placement' ] ;
162+ } ) {
163+ const { scale, ticks, count, formatType, multiline, placement } = options ;
164+
137165 // Explicit format
138166 if ( formatType ) {
139167 // @ts -expect-error - improve types
@@ -145,11 +173,11 @@ export function resolveTickFormat(
145173 if ( isLiteralObject ( ticks ) && 'interval' in ticks && ticks . interval != null ) {
146174 const start = ticks . interval . floor ( new Date ( ) ) ;
147175 const end = ticks . interval . ceil ( new Date ( ) ) ;
148- return getDurationFormat ( new Duration ( { start, end } ) , multiline ) ;
176+ return getDurationFormat ( new Duration ( { start, end } ) , { multiline, placement } ) ;
149177 } else {
150178 // Compare first 2 ticks to determine duration between ticks for formatting
151179 const [ start , end ] = timeTicks ( scale . domain ( ) [ 0 ] , scale . domain ( ) [ 1 ] , count ) ;
152- return getDurationFormat ( new Duration ( { start, end } ) , multiline ) ;
180+ return getDurationFormat ( new Duration ( { start, end } ) , { multiline, placement } ) ;
153181 }
154182 }
155183
0 commit comments