From 7efa7622d05befbee69a9063c637fba42b1d1019 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 30 Aug 2021 12:20:10 +0200 Subject: [PATCH 01/75] feat: left aligned horizontal tick --- integration/server/webpack.config.js | 10 ++ ...timeslip-visually-looks-correct-1-snap.png | Bin 0 -> 32325 bytes .../chart_types/xy_chart/utils/axis_utils.ts | 7 +- .../atkinson-hyperlegible-v1-latin-700.woff | Bin 0 -> 20512 bytes .../atkinson-hyperlegible-v1-latin-700.woff2 | Bin 0 -> 16836 bytes ...tkinson-hyperlegible-v1-latin-regular.woff | Bin 0 -> 20084 bytes ...kinson-hyperlegible-v1-latin-regular.woff2 | Bin 0 -> 16464 bytes .../stories/area/21_with_time_timeslip.tsx | 89 ++++++++++++++++++ storybook/stories/area/area.stories.tsx | 1 + storybook/style.scss | 20 ++++ 10 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png create mode 100644 public/fonts/atkinson-hyperlegible-v1-latin-700.woff create mode 100644 public/fonts/atkinson-hyperlegible-v1-latin-700.woff2 create mode 100644 public/fonts/atkinson-hyperlegible-v1-latin-regular.woff create mode 100644 public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2 create mode 100644 storybook/stories/area/21_with_time_timeslip.tsx diff --git a/integration/server/webpack.config.js b/integration/server/webpack.config.js index ca34cf6ef1..32696a9dd3 100644 --- a/integration/server/webpack.config.js +++ b/integration/server/webpack.config.js @@ -41,6 +41,16 @@ module.exports = { }, module: { rules: [ + { + test: /\.(ttf|eot|woff|woff2|svg)$/, + use: { + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: 'fonts/', + }, + }, + }, { test: /\.tsx?$/, loader: 'ts-loader', diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..0292067068abac43cf0fd20203699bebee391de8 GIT binary patch literal 32325 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 P;bCMX6vZn=KYjgQ%AsR- literal 0 HcmV?d00001 diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 28a603dc56..8425855f24 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -28,7 +28,7 @@ import { XDomain, YDomain } from '../domains/types'; import { MIN_STROKE_WIDTH } from '../renderer/canvas/primitives/line'; import { SmallMultipleScales } from '../state/selectors/compute_small_multiple_scales'; import { getSpecsById } from '../state/utils/spec'; -import { isVerticalAxis } from './axis_type_utils'; +import { isHorizontalAxis, isVerticalAxis } from './axis_type_utils'; import { getPanelSize, hasSMDomain } from './panel'; import { computeXScale, computeYScales } from './scales'; import { AxisSpec, TickFormatter, TickFormatterOptions } from './specs'; @@ -344,7 +344,10 @@ export function getTickLabelProps( const verticalAlign = getVerticalAlign(position, rotation, textAlignment?.vertical); const userOffsets = getUserTextOffsets(tickDimensions, textOffset); - const textOffsetX = getHorizontalTextOffset(maxLabelTextWidth, horizontalAlign) + userOffsets.local.x; + // getHorizontalTextOffset needs to be used for vertical axis labels, and vertical labels of horizontal axes + const textOffsetX = + (isHorizontalAxis(position) && rotation === 0 ? 0 : getHorizontalTextOffset(maxLabelTextWidth, horizontalAlign)) + + userOffsets.local.x; const textOffsetY = getVerticalTextOffset(maxLabelTextHeight, verticalAlign) + userOffsets.local.y; if (isVerticalAxis(position)) { diff --git a/public/fonts/atkinson-hyperlegible-v1-latin-700.woff b/public/fonts/atkinson-hyperlegible-v1-latin-700.woff new file mode 100644 index 0000000000000000000000000000000000000000..171deb953d4894b98d433a1fad6ac15a65aba0be GIT binary patch literal 20512 zcmYhBV~{36)2^Sf%^iEkwr$%scFY~ywrz9Awr$(C&b;6Ioj9i=?&!`dGON0?`bTwT zxyp%(0)PNNO`ZUN^q*^-^pE{N*xdk$awz5egE_adO&f(Y3E?_6D#+_0Qo=a)U4a)a$AENT0{$y zM--ZMeD%7zx~gU$oI#hF1=Wd7Gp^CEB?kd8tSLVPW5KQF6aRfUjE&2zkHvPm>ygm? zHwJRPak9q}E%g}U!dH)RU zvy6{a>Z_V3 zca`C+Dc@IeD=X(xJ9clGz>ns;#=UhM@fM|qBnnROB?{=I9VK>27HzXAY(lvTFxq1z z3TUI>Ugv+SIBFOlL@AgU-Y3b_fR6QuNw>Oddz)0Qkd%#7o%?%UP{Xc{xm5fW z_BPMkhPIi3$DM)Fd1=do@W?{|mao!wKzz#Y*iWKM#*$c1_pa<=z2UgfKq=z=5hexS&1(xljV4qAk z+u?O^W6`?j2m(rSP&IjAOE7_Hj-6lWm)P#_+@!)cYeF64@OxC}YX_*Y(+$Vpc2_M(H~*#R;7NNvNTvzeU!68pXIZu2XAz( z8vM6z91q;c0IYGmD)gTZ${9gFf(`XnSl?xFoHsqv@g2r1ku~`I@!=n@+?b zGX__r%jZe9(cME)rHSvvG4Z0?uu=x_hA z4Nn$fjRh6{u2r%NZ^z|S1{?d%0frQDS<~!zmho78$zK!!S~Bv@pX82*ug;2Gztf1* z%+P!$jM|PE4485y@c(Euf*i$K;S=7&#VOjohE-a$U6 z@vN4~Ir4@vpzM(RvqDKefg2FJo)tVC{=8U#-FZ)WHOeo~a@&vjyW}3Jr}m4R(_Lhl zXCnK6gi+s{Xb-<*y89_%zqzW|=F+Rw()jmw8@S2>PjNqq;YX zWmvjXBpNvCtf|ZiHIwz7SpmsmzSALL%w622>Zx-DHL41uY|=}Fd~~=%x+l4sltMG5 zLU}n-H&Q9T)hvx>jAA2@i3PFb5?Nwd6}i$nV)rz;UX4JsZphuE$3f`lOg+Bllh9wP z`a`i~tT-{55ml!8g?!nkdXyq749Uemm;LQ}AvbuY-?~qHeU*GC(+l{bt(k)q<(ySa z3y$dSsk`k*+SX`9TA9F?M8*+H1ZyGnd+&5&cq(o0H6p*t#dNC#qg9Eetm2#}!wU5r zi7fVn&0F%6SqP-O4-|;&$yUu$fZbMU_S<98wvX+D_TC%OL^Z+*#1x{&+e}+5+7R6J zfXLV1_5f~c+~cH%LJEjrGxxc$XBFiydw9_0jMcCPWEn*v25z*F?9L_BJe?iMXiWx1 zMdsg;?a;rD9H9gf%lmWqM7p_7|6$dbLIHsqlsH_Bwny%$+YxiBAmg?@(4=wR8a2g$ zu3n?VP)&|CJmXE_3-=nT{krlSK-`1H=-I2}NBIR9T0w33Sq!+X8R;7^8m;yBjP>*^ z3^r!?`Qp7D=i4?W*MJDRBX^i+_HbzE-qfP){|L`p*QLz4`@ z_*uZmD(dTl1HACzynp(OiUG04k;nAyR-#{b>s-}R1~p<{uf|3fz^#C^T5q;lza*sG zWA5tEH1NUpMV1E|PA)Q3sX#00DKJ?8yd!P&JFLD>>2co>CNqbZic;c{^O9#I?T<;= zOJ^cs1gdJIsqUrOp`@8=ULsxEQ!M{Zwa2HzyASYjLzcohMOA9x-u-+FEZ9qAZ{h59 zI0kJckLrjMB53Cz*HVzewg99-)+=|>yJuudi*V{~;%?e(!fmQ-GHmK*MNByinXLU? zLjl9q2deG=JNl;wNUXB17oF?EeVl8np$CHZE^OL!mufq;KL->!OyiR#o1bxnC
gNFrDbVRvlsw}oaSkvvML{MsB~(EY>)L5< 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 Zx`Cy4BNKzmX4Vuo1{W6qeU&Z;007i>c6|T< literal 0 HcmV?d00001 diff --git a/public/fonts/atkinson-hyperlegible-v1-latin-700.woff2 b/public/fonts/atkinson-hyperlegible-v1-latin-700.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..6d8457ac6fa736c671835a13866d0951dc8db6c1 GIT binary patch literal 16836 zcmV)9K*hgzPew8T0RR91071k65dZ)H0FpQW06}2@0RR9100000000000000000000 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 DN4%0F literal 0 HcmV?d00001 diff --git a/public/fonts/atkinson-hyperlegible-v1-latin-regular.woff b/public/fonts/atkinson-hyperlegible-v1-latin-regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..26b1a49b8c8ac2b1955f603542a8e982f893252d GIT binary patch literal 20084 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 XrFSC}gUe>t6gCDI7XW>gE(ZVrg|FUS literal 0 HcmV?d00001 diff --git a/public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2 b/public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3f1bcc887b979d68b912e58fc7309a2316173ae1 GIT binary patch literal 16464 zcmV)1K+V5*Pew8T0RR91066I0PUCgggg^1Pp;a z8}WV@*fxzGW_PQiP_lum0(R^Pw}X-ro8(auY#boNZ@0|;|34+^kf9080MuHw`wkg_ z$TE6VqED(S2_sU44r2~#T(uyi>Lv++#~l8)WlE+zycaI#pUdkmEEBf0jMHz${SI>L(Mh5tn!WB+4WI^4^P<=JuxGHOtG zrt|mcG6Dgy@FI*IxVW=xe0C8SxA0MO>LrN$i?6!h?wc<-md=X4_W)$)Oi4n;P>=~B z*++F@)!pMIvag;`z5oF7Nik%oj4jiy9S3ue(nmR2XJGTJ=q68Me zKe)rG;J5hwR-jLogSJJc)m`1yFI;7=0r=g0DYDSo&T>tm4~Ti6|VZqKKca;piC_% ztXGuc9}lyKS=)4_U=OeDcq)O^{Ru-D6KbD?dQmZ(r~{(v5yGXn)#qhR{@$Eb`hSBo zuvWd!YiFI-nS7)*E^(?|!50o(jT*QHI(K)QPAVI zRfj|4upH02oK?{l9^P*J_wg1y!ob>+5WjW@@d37g0^wMS1k8SKv)SwmB~jPLpQIUA zrM%WctHR)zla#8y(BM2;0RNjw^?irQVY7!K#eM^d%trH9?MnUEFfA-ESJ=4G2JVq)OQV9NpEPop> zU~)C(_=qX)B%-2ucpU?8V&*MG-pv4ke$o_+8TtNG3J9d@!`AFP+?d4E_J<^1$j@@`I4ovKef;%yx^(ha>efTepGkg(> zil~d0SP*?N*rIW^z1KQ&h7oKVvo6=>!}eZ2>HOW&Zguz8VEqtkU9G<@9-bdwjiU^Q zhadM%WX;ka>>sr^+N7Zqc2{k)H&g2%k{46CR2l7c?{Dj9Timv>{XHm*y}@VNdoTkU z3yh^isOd-;m??;CG#s4t+>~N~#=e?=YLk_nRUl9pJj6zZ z0*%4u>1jIlK>g*Hr-A7f`Lr(KdD$o06GcW zVAx{ZWl}YVC~cdm$s!0825*Q!qR<#@o=z6cg2))~7z-JzD`Zv$fx_T<>Rt@f=fOM} zqhp}w-wr(fn?jF7?6i8L5a53V`Jy6{#^kQ%!KJntMvs9 zr9IVY24T6b+^}j8C=4EA5)u>|gU#BB_3U8RUb~+n09Zj^n>jqsyI#7ynm6x0Iu~dK zZX!^?F!G3!nTCu`6d;7kTToa-Tc;W9TCOW^tP;ebF!;6-XD#a|*^ym)_M6LHSFYW( zx9kx@sPIspnn_w>HqOLTLON~l>l{MJP(ov{eJ!`tEuZ-E?I*vp{CPW^^hYDx*r&rh z0DT6Im7J(pt(nc)1%+$uw??GHP_^T6whq<77~^|kj4>|O!rMgL&3uSJ!ko04B8`fg zMN2v9bBZ(P&96Cs`Og;KLSC5jR%y{$@-!PeHpk$dSlVIp(+%PPWgfe!7$mvUYhCX8*RJ8hAF+I>B&V)x8a#@~rgQ zYP(mbg}M26YNR7xfR`%K!Hh8ODA(`TX9s~6S3i%^p&1BaxWE7JH}5!{|1!`$Ja~nH z64c+^yy?N zMQs~3vBy2OC;J(@HY9!fg>7G(YxU#KFoVH}=kaEe9yv$xZECZw`o7+&Pt#m{pvQ&H zFX|LMO{g!jhfn+AVY=4d4NP=ur!CsZ>ZfZgB^!{xs4uyz3ruq3z=Et9eEddty(=~F zBAL#wF9O3|iuo>0#GGZva&qDL_zCBJq%}$=ey>)@$WkhNu2xc|Ipbbr&{a1kJ@nK? zZ}btZVzq|N=3ze@49AzdTpsnjnpeH8CoIY;s1gY^LenwBhDlwLP#2V31U@Q$3L(4* zBucA5uY^@5S3#?iX^?4>>Pn*#l1nad0ojK*1UtM&jyQ>OfyBj|cgfYp zH8-DI?qbe^-^5d%C3sGMtGwzBv^Tv)=522yFrOw9(*YA+qT zcuqNat>Kbml~MF$F#`BaOGx zT1TC8%cCBQ{}`otIX}(Mmjq-inMkIRnPfHDOzt4>Wt-FjYSHr{dUl7nqJ~i>Sao$h z=Dgb;Yx6H9WHcGygX)uCzg0`WJ%GARQOBrKR}<80ppI6x=hM!obx#kCEE(aC@J2Wz z%#oQRh>^At)fa6KJ0F@b8P7SD%mzb~g!gTYT1hF@(lUHte!nOc5EK#?QRXKb6_sRV zeQXLm#!Q$rW!i#8OP1X`Wz&{z=bYCoV$VgFTz17S?z}%~MODp+Sl1b|=FBf{)tYs2 z$F8~VhMR8b6L#s2yB9xf_oR%9E^Ez9{+)Op8w9viqe4!a6U1Rw8aHY6y*K}VNQ$_j zS%3OpKjfe1Wre4WFGF8}FPC7S`-Squ&%omr`?oko{_>SL(tlNEv?Dn())KxYJV~zt z!ss0lSXX0546$Mz1)x0OYwG6@z@xnC+qK6 zXZ1^FwO6K3cks#(Ux|`%Ga-BujV*DJ!x;I``h|2BPjdac ztbcRo=-h~^d7B^(nj8^63xxMCnLSEIabM^hn=_q!h1? z63_?5NG+&vD^PJy)xEJ+i7H3g)Pzu`iqd$rP*qhUI(;XqYt*Et7UMh*|~tLm+1UC!!eZb5uZ$oeJ2+NKMz=3kcmw5^*yoY7Hs}Hmm`XrrR7{ ziqcpH6y}w->#li zkyLx*Psi#TV0#0DWrb|2%=}NR1sOlE6|51f&#j|_g2#^dN6C<*3o8M_4nOyHJyY(L z?jHUOyF-p1HZVvFT#C}>rl!Y;JQE>NBrSb>*$YMNdis!7FOw4@E4IUz-Rpp{)<%vR zpn%`qm;9xGsP^`9x ztO>dTB^*_b`!-tui1dg^xUWd{_U#QZRlo=K0)6-B({@kGDO4WuB3}QGt>h=FJqqSW zRF`08$-i>zfjUwY2s?rz4xyOCDB%Q@aw5t&3FVxO3Qj>Kr=p6}2A2@qH>6yB*$aY( z=xe5sx^mUBgxY_XT`yVK|6XV{rdXwpD~Rf|Yl=*|4P*7p8f$HC3+t@6!A7Gxu>n?s z6>T#k;|g8bQ#i0BBu3%tpU_BYUpWVkI{-s?GA?OBqI&sQ*=UaT!d1N3Q%7KH#@#`Y zbfq6&s)p*pH09$HN8p{*%g-={)^Wt|7Ku_0_$>(ZEVAH@HCZS}4fTAXoC7Nu%5D&z z%ny*`1)3Wxj+bOaNYIs=dxe5!^%0sXOlW4x@TdIeiMv!nI5G)0*L}TIv~u;i%De`F zG8zJ6%s^rkQ}%TYc8>GLft7p-J=_G*(DGA0i5FX<$g--Q#==4-R0%6zIm$&Tnm zZaNz>h^8i|svHxYup-SOGPXjAscj^2WyZ@f$(8ILN`k_)B7?MGY=+JOajd}M8Y3!M z5R)K_GDIm7mm~;NECO)BgvFgii}oy^kT0B}nCe4Q*n?MO!C0vDS(OpJ zJqXtwi?DYNr0ug(Q%y|jKa6)5;gmnCFuNyLLTl#-yLs>7eH1{uQ(n;IgY@)jl@I>{ z+7~n!UdAI+F(P7hn^0nSd8u{Fq1sc}-EJXq(BI?p-l&F5@EDstVQgAF+a%>!5D+;G1o42z&~kCLCq5twT7t?G2}I3!K7bZH zQ%Y;?X!g5Eq%Vq+cG%t^8bEzl=}+r-%y2<-YUO><_susgbe))I^7f{iwpL zrT(O9noDaF>t(AMsk(Ti>oZW2BDc2kdEJ!s z54iTzd0XGHS!xcZksV}{9BEG6V0;=%+7p(=#YvF`ZPd6=E2V zcLD2GFN76>{0!g}4Jd}O$8pcKcdE>dON@;2s&Z`Wp`;7X3f$@E>|7eRt#H#=a>I1p zBxAUwlNrd(gct}eseu{#MpSNc^ETZiF#_G&>* zdRgLV+yPwgRopTz!0D)(MH;D7n{{Kw;b&jQ6=qPLXzS! z$X-Rk%(e%m7dCWII2s|HGsuexSm}GShxyLB z={O z2FFd#IC`a)ZvjPdY~7tjkQc2bciw}dE*1}6Dwwu4@e+Gk;Foc~L?Yv)ndWHn_LHA0 zwW$iETfSiC>kruD=%FiL{_P>LdDX5uufHVsGvM<>fV6C zeRhx0Cy`LAM#43)DqGEEE1?ny%*8{4&+{`D?It51!^h#mMF%ZIk~j2tlZ&7+T++L> zdT?gmsH<>JHt|yX7G*{*L&6qT-o7Hau_>7yaMQ7BmfBhEKkDyxbg-O ze|t!7q!83P<5mV6^KT{Qf*dPf#J3UZL9C+E6|$)wT=i5tpwjcr5*eTCH`JGlYIm+76p4{W^O zQ3H|w^=W{=ngh;!1P_=tL^WSs;){Q`U+mL$+eOx|H+o23OU>ll@nw=!P2BD*L_Me@ zzp?fbFSS#3#9wk$B~|uR*wng|qL3@#@Z$?-hgNGPGU(MpZd2BjDiK{CtkD8#D;kcn zjDAEv*J47i1eZMm@rHF!7ANGa zH<<)0r~HX1Kcsr9ydHP=#B_8x4J5YNNjYftG0R12@}w?vPR$1jq4zzcSO@JW|taT`&QI^(dl&fw?sXf1#nci9Xh z8anak-G>V%d(JevH^^RPB}X4kyp(*k+z0`|_(*u#H09a`nL)CRfVq{XcPp0c+OhW> z1AN2p)B&J#RA-lOO7uH2M@inDBC?{z(H&yPKUN1~F1m&>e7ElM8f1M=$Oy?2b*!7+t9yfaC}hFY zG5=V>jF`#z=l1HszwDCJo;me7F1l`+<5t>Ue@0gHUG7ZDQ?!=DH*eu!`ZJd&cok(_ zzX9O+i&*Wfk|maqHKE_Kt0wG$&X+Z$pN)+EJd>_w!)}j1+Sa`{9Pu& zA;4K&h2tiSI&9S$*&u^$lPGx>Gnp;36kojIcBdj1j;HMytDtAX_YgVUbwE1pH$5F{gXBDQX0ak#wG=i}#y=_bYF% zFZhjXw+BGACSbAKv|pq4?{3Qn;~oqM?Z#DjV*>y*m`sNH27}2`59k_90=$c6mM6?D z;d~<3!r@qoi(wxNn_JA-fY^08@~lUFwg2~}#9Kwpm!0>ke-=b}P+yKCDlB$#*)%sE zBZ`PbqHsdtINf@cAs zqBLq^8pWJ&KsGmS&>JI)MwmczY=BCjzQewifBNeFAPOwQP}m=lW@!TACaYfMc_hS1|(4!al^7HY4=t~NHe zvGX_P<9TO4L*iDpe{V=O4l_?NR|Y1nM&J7sN0!`}`mAc!IhC5FT5b?3l(D|`BDIEI zhlp>8JYv<=&~6FD6CUrzeK{Uol}$9IkE9r7c4Fg2Yeo}3YhbksAWq*KB|C^8g}r6`0s5VIE1**45Y zHs_3^AW-mGgr#)oRaS2cM<o5yaMoTe?=oHYPopc-)goZj7z!TCjya`b}@@Xg-LGS+-n z)10%6m3gDLZ7GXR%*y&J{2kb`?=PuUi2t%|Jvr^fH0I-pW8ImfrX!}zX!k@K4_^2G zLik5`&HuY#{#}I7P5FYa@q;_*sVt%l)biK1`%ucX9?ZnzH68ltWmWD%FaQ?|Oe_nI zYf_V3Q=5@jskGvx8lm&jjmvYygyqltFO-fKN1@Ek%C#Kglh3*iC5{U!$m0 zs++t%bz`MUp>YY)NVo3XoY=h18O*PlZi9j8{)(ydM1w(3`CMyX;9rwVXoxy$g6aT; znFD+;(pmhz9Dc7GW5!}Z3>L&<&7gb00``oRt#D&cbYQWPF9>P>Zwbdp@#!CnzX|*Z z5bY4L%-R>&aOGk3@tgOknb*E~>5bwOLMlT-3gk2YrxiLW)-ipN(_|MaR2Ke!4+3my zh+~%-z!iZU5F2b%LZsG$)rATX+){#B&q;tF6Cpmt&F7}={~}{P9}$F z%tvwn%2jiY;`1P%zbHf!X=+5J9{eo;Ph$>|$xsH!o@*m~Dif-V<HSVBJ(_xbaCFxE zPTW|<{z)^TkCkk;6JI{l*}l|cIr&n3b4pAkh#&Kdfm)N6)hQqmh6u#F1d>1t@OV7- zf8>Lrq6bK{IMwVuxDX~A()B9@^OIkraRIVsuV6v)D>N>MtzE&p+e6ZXS0BFGUPb$li11sN73S|TbhCyvO6?fhF)ZCSylp5+ zYo3yOWnaJS9TU?xBkYT0v6yU;%`WQ{;#K>;(P_7xDXM4FYSLV{hnrSwn23?)X^`XX zs8JhSSIhKaR6zM#N^*~uM(ekSs@E59xFqA2W2t{LMYYlhI1^;<-^IA^W-y`q4CY0M z$#7qck#-YFJtX4WX0~@!|1a#i`r;AuZIG4dk%aUwo~R{VADij^lNZ7-+eKCA!v zO9HbEK%1p%+S30oruz!=0{K&+xfw$im2tfPN;fEFy7^LZFesLe1N%qtqu3)($6>b! zSD#!`|G~nydxoc6&c?3F&YDp;^{ZtUew{vrCWdF;ZT)g8Z6+H3N86e%bg7U+?^VvD zo!dkkWddR`6Bwn@zYAo0?=n0NG;)rIUM7LB~OryM%PV6EhazwW+u?%c{TL z$BkmC>}!~I{Os786^jjOHz7=mN~)r&B_4o%A=_0Q>?)tO!{ruKSlJBf%RP&3l4yUi z>@r9Zj?l%#>qoyrt|}m{_Ru7psMC^Qsnlt%2jZqRfS|_fs%9(fe_Eb`Ir=ezRi4?J z$j1EngMz!Zr+SVn;kt79WUJ<%)=MAHePNfTlvW~FzwWlP^X*P2qi|wxc#dGm{YB1g z9YZQVnu5S6TQ#2k7+KRj-g#c;7PYYJ!S1H1dBMDCf7evZBekB-=j|=qo6p1EW|+o1 ze>&%LA1ddr8_?IG-(8gDTZG*6&p^HF2X!HG?X{vkNIVguJz4nn+3Uy(LBXl*FxnKt zP$IQCqw!C;vOW8$!l61_28FZjw;^3Cxkh;YWOrL4R{__S&!bCK&_#8r!oKNVb+JMWFt>*p4WHm`29GZ{7PriHCcXKS>O1HmsI^zyZhl$k)rvUfE4j8}3WnKZcuh6FY?Z!;g{BnS)UJLVtiw?H!?UAVJ^CGv@v7GhJxt8wy~|a0 ztED@+?E+BH&fO`|bSq^G&eP3U087N6?arbBn?hb}#eRlGaqN!08yhyPlH$q8%G{gJ zmF08yx_=J2uSCqkCJQL6k65l+#UL;~3e-cm|148mB;XGaZevV)(N)ruKA{hJy!r?) zg}|9Uc>C?^%$fU+HcCRj%oQI-agBzCQj%t$)jg1mCsu?T7DKw3IU zMhLiU36jL3K3t7w|HA-Stjd4bEPz?bVle=K>3SU6DcQ-r$>J0Gsl6I*s$lkWdvk!>VAvdSt-D$2FyN{F zg==nP!C4P$;LBTanJq7W`88mY-t~@oiMjXsQuBKVh1cgjQhh&=%di_)E@$IA7)7~= zy6C@CXH3Y>-Fj5TzT@5OC0cYlZ7pqHLj}&IH_QW338Wn}P!#PPtx#_TEJUz9=to<8 z2b*xE@(g-TF2gqSyUo6(`^XW^;g;Wd@uSD&hbTJ8nT zL+H|sgwp8KShUP}RxI2~o1!H=%?i^j)_g|_>OE!UA2iI~6-2Egv%|@c-+;=wK^Zb& z0Ot0B`E>&umpEJS29L{SaLd-6OJ4nJEeAl<3IugP4ri?p{Wa4@EW3y?9O~Qe#jASG zdYx{0v3GI>M{(_jQcix!J|xciB6NJc7E4O@V0}jUo{&BPQhkBE_&dpGhaGustJxA7 zcV`~LR;yRl=s`twLZvr_q?w6kM(mm0E-@Mh%!p#QvZ`?H1Ib(izp|)RqeZsJ%VH9% zmGKFJrmu-UOTRwwIPDdpi}uo8g=w7N5;=xO=DMElo}K~sNZl{iO=G6;61V^^J0*64 zxnL_i2LF3b^C0K+ba=A7wHJWO3lz3*mBMP?r=V7Jd_5CMKkyjejDhUKos1m3!luf{Xs#6lf4=SkW&5guh)(wb0_}-Ekv|zTsO0|d{8xQ!o;b;K|@jd zwl&S3MIN%d_z?bL}ArX3#aDuk<|7A-8VfN&JYQYbpol@VU8xIE+7 zj`;VKKWwX?7UY_9r~Q?wtwXgT?7!kkmOWj8V%IFG#Nmrg3e3Taix3xl>CN%LtGV(c z2OJxfw299S{gS?Ex)yM~DCT#b2NS<{3|kN;1<-tD52%_zapX4RTs(5U$#$=4dqf4p zfA297cK_T1TVU_+9Jo{O%VVQ+{Bn54*C(R+pX?V6RgKTQPgUcKm{>yLR%#gVwrQ&W zLhCD=2QoM+BkXW#WLls3vCp+~+sMDZgNFG2!eJrUHCh;7Z5*^>kMM)^*Ym(0`t0IE zUw-3Xf0q{Rxiv*${IiG=ViWmdiWu8IkjXviBH(A{BFS95lP<$`>66Fbne|`p%A9gM zYdL;Xa+MoLhkm)vzrHyuSRSzoKQ5KZ2>k1-vJt^cY@B_){ln>ho!#i%I_D?4u*4-Z zU3!|!Cj2I!$wgG{xBtB{4&=!$=`Cnpv#!Q>diNcl8HIAg6Y5u;k2(S<4CEfmPg8YO)qri~*7M^<7fz>9w7g8F+_j1o>;Nupw6Gk^1g_ zWgaV{eXI*g{`7hm2TP7ZHLu=Ce*=~*HPk4l>hE*~@mapjeGJ94Gt4Ib;*mlFRT%?A zDDUJ?=I!~Gejv9fgM}y6oSA)whJyhSRz_H*dlWJt8%p@t{=4n}m&8d$o~0O7Sb->o zG?>&OR*o%HzJRJ79187OH+Sdzh!P?C3tPgP;$9=6irN6K(#`}(rWaxEyNX4@BBa?n zuK_?44J4b5h-#@@kce!m_N1_I=WDYR0jVMt$ZB2t96CP6OlFgLH~V8*U~PLSb(1Gq zVaVa|gqVMv?W0B1VVyQj+1z9a@jWL-oZ#hO@+J!*D`Owirw&oV1PzLtjf`1oT1W+Q zza7Xt;aHzR{yuib@~jBJMtJ>K-$$ zRxrC=*lK}fYghDTPXpJE5z8#X@McT`dO{ffa$!*$kLd2(3Q@H z4|8|E$x^elAgqKcL75*JY`+zjwz8$`khI$d)3KA$La||K7OX%)O*90G#K69_OxF#Qjay0j@Y~)xO022JUJT9CcXt^YBWQ@sOIS6>w5<| ztWk~BBD82h2oMFr#q~y;&+3eIDzBvhsozVEGGM4U<(XFo@HZiW)*SkN?o`Q*oM?#{ zpxu-~TwjG+?F_5PPp<@PiR<;LwTY@kvU;tCG$Ec@q!R2e_g_#kA6qRZ#1-1L#yUvh z{dDweG2ALBmXTg$(h&t@lZz8l2BlfV;D$cEN2@e<1_xBG^X(TfNJOWjMN}=27SWX~ zkFtpQo|Q~whG7x9q#+1kwyR0H_MojTZC7CDEMlI?W%&JPo@8P`YeyS%3n@8oyHNkv{#MVe=sHz9$HLKKRL}*iOYmTkU4^Y=3q{zvgqeYB zr-eKX@-CetiZOdS+bO-jgt+27P;OsXWWmv5%V2qER8hl)N+%k`kE~;(de<5x42mer zn4os_-0;F(>EN6PlHGV(Sh>G8y*Q#mK!@o)TA%7HN7StRLWXMVv3RlQVW7z7##3#&HK%Wt zhb0V`5mRPaGjKubSP6kD(3JOGE^H3aSz0Q>gR%e*kWP~d<^eX?%6gOlmv+=ulbu5~ z)?*rnL4F%rWd+m`yQm!GgOWZG&)TRbl8KhC+un z=W6U8wCL|Ho1qaHj(!ja(Fm#c5fD#ya7;4@$NH>3Rg92HSZv$&ga>a_6OEPCp2*P1 zL(;EZC*{H2VJ#On&+PFmIG&MXXs)@6?gox;6wwFPjPgOc(&-OaiB;@8gWGTHbNBJb za}|OWfZr`b{?;z<&VV#J?sduD08pWGUL$}SO_zlTUUe&Crf*L>)9BG=`_sI?16m&$1G=mcG5O-@iomxA<7z!&Y2A=Xq9cgpk?8M==x z9&y0j$XRv^)uY2s#+P&uq6}$zFkQGyD=VN{a{4IPCg;4HZn|dA!pYN3=%Fn;YdJLc zjo9TV@rsgca;mIR(ORgJi4xqP;tR2rf@LgjlE$ns$9e39xoq`JL@v9B;r} zx^W+dKmhNdvhcQbonXclph968qLY)#vw0EvN<(36{l>;B9{5&y@AOfbbhb!6Jq(+8 z2e={>Svn37GP4$5{-BQ`in=j)fd&M9JmjZ6a;ZV?#e)QwuV#mB%LG}nY{DUU3QcB) zw#=4md%f>YyLIFGvcGWaJwH1hmP1tpUD$bYoIM)7&P-|I;7nfcDY7`u+|bRuOcdb@ z0mUSoXi^J21{c*TjuT=meVZpBb=^Rx4Zb-2=GR6+k1TV>cJ^c=84c$PDLRuFm*;P~ z%o+77Rl%Z4u7F&4pX*4%InGFRClC~GSJl!zsbTr81>#UV_!j~z+65`Pmis$vI}pqo zE9@yA!~`b?K*cnoRujeg$@$DmYG9zB%dd#?`&M>1FzGcancpv?W$cJMV0ng7SFW?M zBVi_`Y-jLU0dlwi$KHN~J$V57T6%1!-spw%P5(JX!H;lM5k?kfYq zWB6k1MJ`9CA(y(2Jm&4mpG)_A?O2|MWG~%vRjhY&Wpb4QrwO@7*yx1}t07Mgj+*OfgS~yey7uv!gMKFE)M;&dq~;rFVVd%gtsSkzDz?xpd$HhWFEU zT*Gr&EsKl>y6>&c!|{(GpW%dL(a5#I2C2$$${`mPeK911CfXoir@u5kB3G_MO;F$P zV1w9KRv*|=#KFU?aA^c_r9|Sf zf5PsJm)X`48|WK-o{+l8gKNZYxq(@3AtPR$9+5nL`1sN3qucBKG<3v5Vc;7PxA~Cp|4tN zDI%#-Dafaw@p~wgKd`3z&EfMWxX9(a2#AC;akxDz6U&LrFu@{AG5dmSG>uVR*(N2e z3s)ezbsW2ziHG=JV{k`%p^zkmeFtypayPL$3|tq<#jn%N?q=xfE!$>EP=%FCT+sJC zu(O-C<<0^{i=F*c<)LJSYOQFAYgaFlA4a2)HZvjS4_(KCzM6z%+HUsb&*^ID$|8yF zgblW<0gA7+$tX?wig&?4@NBu2-UOw{9=O9TJeG+|JB#Wo+WY}B2Wz%=@+tBp^t+!& zVVa(`>7`8jb6#W$Q%3CI_&P$1itKkO7Pb7U^_It7M*tnWq?qvvke z2QrK237J(EIuVElgDiz?!UHdGW2(8dAKLrPeAat(zVH&=!i{%)S3dTpSm-OtL^l^H zG8C;EP2tHB;xUL8=)@wVj4UFoDdDSIvl^RyyRXaDoQQE_Ku`u^F}4|%!w54XCmQ!b zmov!ovPeJufj8~od(8YLOg_*wh}QnCiTU?km4T=u*&IBqi?ZH8R48N&7(r~*b(`ny zTW<4okMn#*A0xd$N~jt710=jf;#I`*c=ZNf+~4hYq7SSRKLi8XLH>XLoNs{*4 z5?fOCQO0+0_2=1PyYBhG5k^}%^8dJx&81=Ht@OJ0D{aRO`sIMJBRRNhFFd@U`SqIk ztZkKujb2uoycT}%5_b-1Vm|UCsh?0v9&cG$VFeWSn6Ovj#VM=SKs%hP2oz28I3#u| zGFKeqA@m0yGW;|VG>JAGf~8P&Tb_8iQ|pq5@Oi8Cu;RF|Gsk34l^eAc8p1{n#UQze zGLXngrs(~KJtr4gijHL#UX<@9C)1+vxh&)hNJD1o;_`>5z#YS{O~Q@?4u4T(AW!Es zUUIcK&*d~+#}n~>Haz(%0@@sykUD(y8?3jybzr8 z@eSrGEa-u5JwExkvQpt)8H(oZgnx^#$HrRL)u+ilk1+HU9Dd`g(phqd>X z1O_#f&F)%13RvNdc>h`R@*7@*ic}YEJh#9XN34$AzsD1JWCC=Mq$)ni3KO%R5S~1p zBqQHwHyd($CExPQbIk-~1Ne79nn}3cOiZF;ENI z@F~Jca08&O++q`_CnT4@PY=6?^|J4lhB#>0wal=?DP=xa{PWLuvZwrcad$-bOO!Fo zdPF0Blwl-{D2<6{NtcWG;)H?Xy*K;khPi7`3k&!6pN%iS;c2pho670pJepx!gwh>i zt9cz2Zl`!!ub&DcKY1Rfgu|pKLawp@_o8K{fPOB&8T%;?`tQ42Uk3zhAKY+3sWKv; zdK6JKHWA6lTzE)3%tm{TpWBNCQua=5Gpma{OJnLexfR@WW`axdcB#?xR6?Y>wVmnd zEQ*tWme$qC&)_+|Z@H{u1I83|t&a_(JV|;fjA?d|$wBnit^NUpRBALb2drg(l}vZ3}l6~V)dI;2f``@Vkd>SX25x!T_@*Zc?Y$u)Om{tbWr z+pfAinI-cbpoakhT-wDy+|oGyU%MGV+$p}#Tu3$|7<1|y$p@9wC0GV$^|6pNZ*8&- zDd(APKCL|3NZSbcyx!d+**!1?j1If}MuUmGq#4Uz|4ribK2l@v3x9;m*ze%F>;QiS zg!r_&3Ed%g=F9l(>>=UK0B_~G<}WcR2$vBBMXpLlt?DC1{QodN>FPH*j)Ow5Y>cBo zAc4tZKVplSwrK4f1Nk_Jk3l>G;v@bzYQ}%MeiGl#na$|1qepj2BBM@ ziEJcLGEBwzO1{8b|Ge{M-k#gkQU35G!{f^P+7>9(7Al~TcAC=<*#^#X`2qCJcIsNQ zjP^7%t_5s)TUygjgG7URpYI4flOc*IAvq#&$R75|Xb$N`K;YD+SCIlWPoww+FUb*d z$LbAIZ3Q&PC^rC;y#S6Ea!vpo>5K)*j3Um0?=AmI!vzNQrqab6Ds3)+)(&O>^71{} zE|CY%!Ts=HoWeu#06aqOKAH}9+I*TKuJfb36Xoh^qF3ARO0B64l5o`lupv zKXkXk{OW)()9QBOpdC1oC7B6U6Qbfbq3>>1Nnic+)lniUuTmodQ^lZ`y{ZfilLK`| z)yyemxA=}sH9-l|$`P+UNY*(uYR{!jhSf_O7|XcMke6x0{jm#&2(81vgMc|S00b=Czaw7US(po zA>zYo9!>>zKK-0e44UJT=hxLw@|!WQn>ORfK1xXgPSmN_s6mrjDa~%EcGY#QTC{0* z$4$4~&W^9oIp#{c=dL09>3rzE57hYCJPXXXP^U$fSZpc1j^l{pF&zmR18Ct09EqbM zKMJBSW=2sU0~P4N1U7Ji_g)Z!7^EN%JQtpEMuO+H+1HM?h>Rk?vq{`0;Z&(@;u6`^ zr_{;nNcYXx9xG`bw@oNxp8SR^xm^$*tUkImv|Ib=cDV38ZNgRTX;W_+efxQiO&q!9 z=3`HI-#ckQANn4CG%67*{GK9lcJY$1NIB_NCSkqqDpE+NKcBy_8ew3DJw+y&*C=z0 zd2Gk%>Z4!Tf?hxH{CSZV(D?5zeGgsfqv87nVE4WZq1(i9!QsT$CL@n2XcMV^jH9r7 z%y4#L@7pFY1{j=0NEVXmQ14M-Z#)fQ|5wYk=SH6AYrg?Bnd_sktK-U9u>U##{jQq! vrn(dwO!|Kh%mE$%;s2#>KCkVC+Rq$L9I@ne^xXWsZF)ievcIKNKdyZT?)k~0 literal 0 HcmV?d00001 diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx new file mode 100644 index 0000000000..b7a7622fcf --- /dev/null +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { number } from '@storybook/addon-knobs'; +import React from 'react'; + +import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings, timeFormatter } from '@elastic/charts'; +import { isDefined } from '@elastic/charts/src/utils/common'; +import { KIBANA_METRICS } from '@elastic/charts/src/utils/data_samples/test_dataset_kibana'; + +import { useBaseTheme } from '../../use_base_theme'; +import { getChartRotationKnob, getPlacementKnob, getStickToKnob } from '../utils/knobs'; +import { SB_SOURCE_PANEL } from '../utils/storybook'; + +const dateFormatter = timeFormatter('HH:mm'); + +const minorGridStyle = { stroke: 'black', strokeWidth: 0.15, opacity: 1 }; +const gridStyle = { stroke: 'black', strokeWidth: 0.5, opacity: 1 }; +const tickLabelStyle = { fontSize: 11, fontFamily: 'Atkinson Hyperlegible', fill: 'rgba(0,0,0,0.8)' }; + +export const Example = () => ( + + + { + return new Intl.DateTimeFormat('en-GB', { timeStyle: 'long' }).format(d); + }} + /> + Number(d).toFixed(2)} + /> + + +); + +// storybook configuration +Example.parameters = { + options: { selectedPanel: SB_SOURCE_PANEL }, +}; diff --git a/storybook/stories/area/area.stories.tsx b/storybook/stories/area/area.stories.tsx index a225078bfe..1b527abea8 100644 --- a/storybook/stories/area/area.stories.tsx +++ b/storybook/stories/area/area.stories.tsx @@ -10,6 +10,7 @@ export default { title: 'Area Chart', }; +export { Example as timeslip } from './21_with_time_timeslip.story'; export { Example as basic } from './1_basic.story'; export { Example as withTimeXAxis } from './2_with_time.story'; export { Example as withLinearXAxis } from './3_with_linear.story'; diff --git a/storybook/style.scss b/storybook/style.scss index b0a8f4f75b..2b659acedd 100644 --- a/storybook/style.scss +++ b/storybook/style.scss @@ -1,5 +1,25 @@ @import '~@elastic/eui/dist/eui_theme_light'; +/* atkinson-hyperlegible-regular - latin */ +@font-face { + font-family: 'Atkinson Hyperlegible'; + font-style: normal; + font-weight: 400; + src: local(''), + url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* atkinson-hyperlegible-700 - latin */ +@font-face { + font-family: 'Atkinson Hyperlegible'; + font-style: normal; + font-weight: 700; + src: local(''), + url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + html { &.light-theme { @import '~@elastic/eui/dist/eui_theme_light'; From 85c2eea7ce6d6c5822f63d7dab73a62e8f2c6dbc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 30 Aug 2021 12:44:08 +0200 Subject: [PATCH 02/75] chore: placate prettier --- storybook/style.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/storybook/style.scss b/storybook/style.scss index 2b659acedd..b7b7bdd6e8 100644 --- a/storybook/style.scss +++ b/storybook/style.scss @@ -5,9 +5,9 @@ font-family: 'Atkinson Hyperlegible'; font-style: normal; font-weight: 400; - src: local(''), - url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + src: local(''), url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff2') format('woff2'), + /* Chrome 26+, Opera 23+, Firefox 39+ */ url('../public/fonts/atkinson-hyperlegible-v1-latin-regular.woff') + format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* atkinson-hyperlegible-700 - latin */ @@ -15,9 +15,9 @@ font-family: 'Atkinson Hyperlegible'; font-style: normal; font-weight: 700; - src: local(''), - url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + src: local(''), url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff2') format('woff2'), + /* Chrome 26+, Opera 23+, Firefox 39+ */ url('../public/fonts/atkinson-hyperlegible-v1-latin-700.woff') + format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } html { From 7688e5af3de9913cefe12db4fb0cfe8d7eda8dc9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 30 Aug 2021 15:47:25 +0200 Subject: [PATCH 03/75] test: working around no gaps --- ...timeslip-visually-looks-correct-1-snap.png | Bin 32325 -> 32234 bytes .../stories/area/21_with_time_timeslip.tsx | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 0292067068abac43cf0fd20203699bebee391de8..0cf702978afb0e85f3b59ed1c16b337e23fc875d 100644 GIT binary patch literal 32234 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 P;bCMX6vZn=KYjgQ%AsR- diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index b7a7622fcf..5c63ebb926 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -50,7 +50,7 @@ export const Example = () => ( axisTitle: { visible: true }, }} labelFormat={(d) => { - return new Intl.DateTimeFormat('en-GB', { timeStyle: 'long' }).format(d); + return `${new Intl.DateTimeFormat('en-GB', { timeStyle: 'long' }).format(d)} `; }} /> ( ticks={4} gridLine={minorGridStyle} style={{ - tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8 }, + tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8, padding: 8 }, axisLine: { ...gridStyle, visible: false }, tickLabel: { ...tickLabelStyle }, axisTitle: { visible: true }, From 031becb68b5681cec5421e12ee284698b28b61e6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 30 Aug 2021 16:51:43 +0200 Subject: [PATCH 04/75] test: us time --- ...timeslip-visually-looks-correct-1-snap.png | Bin 32234 -> 32137 bytes .../stories/area/21_with_time_timeslip.tsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 0cf702978afb0e85f3b59ed1c16b337e23fc875d..93675904825efcd18f8a0d57aec3f122cafbfbad 100644 GIT binary patch literal 32137 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 literal 32234 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 ( axisTitle: { visible: true }, }} labelFormat={(d) => { - return `${new Intl.DateTimeFormat('en-GB', { timeStyle: 'long' }).format(d)} `; + return `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)} `; }} /> Date: Mon, 30 Aug 2021 18:08:10 +0200 Subject: [PATCH 05/75] test: niced top --- ...timeslip-visually-looks-correct-1-snap.png | Bin 32137 -> 30573 bytes .../stories/area/21_with_time_timeslip.tsx | 1 + 2 files changed, 1 insertion(+) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 93675904825efcd18f8a0d57aec3f122cafbfbad..2a5b78198ff233d56dd0217d695eaf9d26b96bea 100644 GIT binary patch literal 30573 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 diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 4f944d13f3..c879a23c84 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -74,6 +74,7 @@ export const Example = () => ( yScaleType={ScaleType.Linear} xAccessor={0} yAccessors={[1]} + yNice areaSeriesStyle={{ area: { fill: 'rgba(96, 146, 192, 1)', opacity: 0.3 }, line: { stroke: 'rgba(96, 146, 192, 1)', opacity: 1 }, From d247f5d161f39bb2aece20730c9fe15bc5d09b64 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 07:27:11 +0200 Subject: [PATCH 06/75] test: multiaxis --- .../stories/area/21_with_time_timeslip.tsx | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index c879a23c84..a87f2836bf 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -37,7 +37,7 @@ export const Example = () => ( /> ( style={{ tickLine: { size: 0.0001, padding: 6, ...gridStyle }, axisLine: { stroke: 'magenta', strokeWidth: 10, visible: false }, - tickLabel: { ...tickLabelStyle, alignment: { horizontal: Position.Left, vertical: Position.Bottom } }, - axisTitle: { visible: true }, + tickLabel: { + ...tickLabelStyle, + alignment: { horizontal: Position.Left, vertical: Position.Bottom }, + padding: 0, + offset: { x: 0, y: 0 }, + }, + axisTitle: { visible: false }, }} labelFormat={(d) => { return `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)} `; }} /> + { + return d % (15 * 60 * 1000) === 0 + ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + : ''; + }} + /> + { + return d % (30 * 60 * 1000) === 0 + ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + : ''; + }} + /> Date: Tue, 31 Aug 2021 15:55:08 +0200 Subject: [PATCH 07/75] test: three axis rows --- .../stories/area/21_with_time_timeslip.tsx | 225 +++++++++--------- 1 file changed, 107 insertions(+), 118 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index a87f2836bf..4bb8d01ca5 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -10,7 +10,7 @@ import { number } from '@storybook/addon-knobs'; import React from 'react'; import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings, timeFormatter } from '@elastic/charts'; -import { isDefined } from '@elastic/charts/src/utils/common'; +import { isDefined, mergePartial } from '@elastic/charts/src/utils/common'; import { KIBANA_METRICS } from '@elastic/charts/src/utils/data_samples/test_dataset_kibana'; import { useBaseTheme } from '../../use_base_theme'; @@ -23,123 +23,112 @@ const minorGridStyle = { stroke: 'black', strokeWidth: 0.15, opacity: 1 }; const gridStyle = { stroke: 'black', strokeWidth: 0.5, opacity: 1 }; const tickLabelStyle = { fontSize: 11, fontFamily: 'Atkinson Hyperlegible', fill: 'rgba(0,0,0,0.8)' }; -export const Example = () => ( - - - { - return `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)} `; - }} - /> - { - return d % (15 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` - : ''; - }} - /> - { - return d % (30 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` - : ''; - }} - /> - Number(d).toFixed(2)} - /> - - -); +const xAxisStyle = { + tickLine: { size: 0.0001, padding: -6, ...gridStyle }, + axisLine: { stroke: 'magenta', strokeWidth: 10, visible: false }, + tickLabel: { + ...tickLabelStyle, + alignment: { horizontal: Position.Left, vertical: Position.Bottom }, + padding: 0, + offset: { x: 0, y: 0 }, + }, + axisTitle: { visible: false }, +}; + +export const Example = () => { + return ( + + + { + const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; + return `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)} `; + }} + /> + { + return d % (15 * 60 * 1000) === 0 + ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + : ''; + }} + /> + { + return d % (30 * 60 * 1000) === 0 + ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + : ''; + }} + /> + Number(d).toFixed(2)} + /> + + + ); +}; // storybook configuration Example.parameters = { From 0177663791db47ea0f29f31bfa75b7a96638cbe0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 15:58:02 +0200 Subject: [PATCH 08/75] test: formatting conditional on width --- storybook/stories/area/21_with_time_timeslip.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 4bb8d01ca5..28172bd247 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -61,7 +61,9 @@ export const Example = () => { })} labelFormat={(d) => { const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; - return `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)} `; + return `${new Intl.DateTimeFormat('en-US', { timeStyle: chartWidth < 500 ? 'short' : 'long' }).format( + d, + )} `; }} /> Date: Tue, 31 Aug 2021 17:01:57 +0200 Subject: [PATCH 09/75] test: nicer label formats --- .../stories/area/21_with_time_timeslip.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 28172bd247..d1d7b29438 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -35,6 +35,9 @@ const xAxisStyle = { axisTitle: { visible: false }, }; +const data = KIBANA_METRICS.metrics.kibana_os_load[0].data; +const t0 = data[0][0]; + export const Example = () => { return ( @@ -54,6 +57,7 @@ export const Example = () => { position={Position.Bottom} showOverlappingTicks={false} tickFormat={dateFormatter} + ticks={20} showGridLines gridLine={mergePartial(gridStyle, { strokeWidth: 0.1 })} style={mergePartial(xAxisStyle, { @@ -61,9 +65,7 @@ export const Example = () => { })} labelFormat={(d) => { const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; - return `${new Intl.DateTimeFormat('en-US', { timeStyle: chartWidth < 500 ? 'short' : 'long' }).format( - d, - )} `; + return `${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }).format(d).padStart(2, '0')}′ `; }} /> { title="timestamp per 1 minute" position={Position.Bottom} showOverlappingTicks={false} + showDuplicatedTicks={false} tickFormat={dateFormatter} - ticks={2} + ticks={1} showGridLines gridLine={gridStyle} style={xAxisStyle} labelFormat={(d) => { return d % (15 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + ? `${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} ` : ''; }} /> @@ -96,7 +99,7 @@ export const Example = () => { })} labelFormat={(d) => { return d % (30 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }).format(d)}` + ? `${new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'numeric', day: 'numeric' }).format(d)}` : ''; }} /> @@ -126,7 +129,7 @@ export const Example = () => { area: { fill: 'rgba(96, 146, 192, 1)', opacity: 0.3 }, line: { stroke: 'rgba(96, 146, 192, 1)', opacity: 1 }, }} - data={KIBANA_METRICS.metrics.kibana_os_load[0].data} + data={data.map(([t, v]) => [t0 + (t - t0) * 4, v])} /> ); From c447f29cb91d2af755fbd5ec12f72b5a94f38718 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 18:32:51 +0200 Subject: [PATCH 10/75] test: decent mock --- .../chart_types/xy_chart/utils/axis_utils.ts | 11 +-- packages/charts/src/common/color_calcs.ts | 5 +- .../selectors/is_external_tooltip_visible.ts | 2 +- .../stories/area/21_with_time_timeslip.tsx | 76 +++++++++++-------- 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 8425855f24..4fc332fafe 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -10,8 +10,8 @@ import { Line } from '../../../geoms/types'; import { Scale } from '../../../scales'; import { BBox, TextMeasure } from '../../../utils/bbox/canvas_text_bbox_calculator'; import { - getPercentageValue, degToRad, + getPercentageValue, getUniqueValues, HorizontalAlignment, Position, @@ -529,18 +529,13 @@ export function enableDuplicatedTicks( fallBackTickFormatter: TickFormatter, tickFormatOptions?: TickFormatterOptions, ): AxisTick[] { - const ticks = scale.ticks(); - const allTicks: AxisTick[] = ticks.map((tick) => ({ + const allTicks: AxisTick[] = scale.ticks().map((tick) => ({ value: tick, // TODO handle empty string tick formatting label: (axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), position: (scale.scale(tick) ?? 0) + offset, })); - - if (axisSpec.showDuplicatedTicks === true) { - return allTicks; - } - return getUniqueValues(allTicks, 'label', true); + return axisSpec.showDuplicatedTicks ? allTicks : getUniqueValues(allTicks, 'label', true); } /** @internal */ diff --git a/packages/charts/src/common/color_calcs.ts b/packages/charts/src/common/color_calcs.ts index 363f3b23be..80e0d44b6e 100644 --- a/packages/charts/src/common/color_calcs.ts +++ b/packages/charts/src/common/color_calcs.ts @@ -162,14 +162,13 @@ export function getTextColorIfTextInvertible( : `rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})` : textColor; } - if (textContrast === true && typeof textContrast !== 'number') { + if (textContrast === true) { return inverseForContrast ? to === undefined ? makeHighContrastColor(`rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`, backgroundColor) : makeHighContrastColor(`rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})`, backgroundColor) : makeHighContrastColor(textColor, backgroundColor); - } - if (typeof textContrast === 'number') { + } else if (typeof textContrast === 'number') { return inverseForContrast ? to === undefined ? makeHighContrastColor(`rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`, backgroundColor, textContrast) diff --git a/packages/charts/src/state/selectors/is_external_tooltip_visible.ts b/packages/charts/src/state/selectors/is_external_tooltip_visible.ts index a5751c0b90..a4ca924d76 100644 --- a/packages/charts/src/state/selectors/is_external_tooltip_visible.ts +++ b/packages/charts/src/state/selectors/is_external_tooltip_visible.ts @@ -34,6 +34,6 @@ export const isExternalTooltipVisibleSelector = createCustomCachedSelector( if (x == null || x > chartDimensions.width + chartDimensions.left || x < 0) { return false; } - return hasExternalEvent && externalPointerEvents.tooltip?.visible === true; + return Boolean(hasExternalEvent && externalPointerEvents.tooltip?.visible); }, ); diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index d1d7b29438..baa08c2ce8 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -9,7 +9,7 @@ import { number } from '@storybook/addon-knobs'; import React from 'react'; -import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings, timeFormatter } from '@elastic/charts'; +import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings } from '@elastic/charts'; import { isDefined, mergePartial } from '@elastic/charts/src/utils/common'; import { KIBANA_METRICS } from '@elastic/charts/src/utils/data_samples/test_dataset_kibana'; @@ -17,11 +17,12 @@ import { useBaseTheme } from '../../use_base_theme'; import { getChartRotationKnob, getPlacementKnob, getStickToKnob } from '../utils/knobs'; import { SB_SOURCE_PANEL } from '../utils/storybook'; -const dateFormatter = timeFormatter('HH:mm'); - const minorGridStyle = { stroke: 'black', strokeWidth: 0.15, opacity: 1 }; const gridStyle = { stroke: 'black', strokeWidth: 0.5, opacity: 1 }; -const tickLabelStyle = { fontSize: 11, fontFamily: 'Atkinson Hyperlegible', fill: 'rgba(0,0,0,0.8)' }; +const fontFamily = '"Atkinson Hyperlegible"'; +const tickLabelStyle = { fontSize: 11, fontFamily, fill: 'rgba(0,0,0,0.8)' }; +const axisTitleColor = 'rgb(112,112,112)'; +const axisTitleFontSize = 15; const xAxisStyle = { tickLine: { size: 0.0001, padding: -6, ...gridStyle }, @@ -32,12 +33,23 @@ const xAxisStyle = { padding: 0, offset: { x: 0, y: 0 }, }, - axisTitle: { visible: false }, + axisTitle: { visible: false, fontFamily, fill: axisTitleColor, fontSize: axisTitleFontSize }, }; const data = KIBANA_METRICS.metrics.kibana_os_load[0].data; const t0 = data[0][0]; +const topAxisLabelFormat = (d: any) => { + // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; + return `${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }).format(d).padStart(2, '0')}′ `; +}; +const midAxisLabelFormatter = (d: any) => { + return `${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} `; +}; +const bottomAxisLabelFormatter = (d: any) => { + return `${new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' }).format(d)} `; +}; + export const Example = () => { return ( @@ -51,22 +63,31 @@ export const Example = () => { baseTheme={useBaseTheme()} rotation={getChartRotationKnob()} /> + ''} + ticks={0} + showGridLines + gridLine={gridStyle} + style={mergePartial(xAxisStyle, { + axisTitle: { visible: true, fontFamily, fontSize: 24, fill: 'grey' }, + tickLabel: { padding: 4 }, + })} + /> { - const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; - return `${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }).format(d).padStart(2, '0')}′ `; - }} + labelFormat={topAxisLabelFormat} /> { position={Position.Bottom} showOverlappingTicks={false} showDuplicatedTicks={false} - tickFormat={dateFormatter} + tickFormat={midAxisLabelFormatter} ticks={1} showGridLines gridLine={gridStyle} - style={xAxisStyle} - labelFormat={(d) => { - return d % (15 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} ` - : ''; - }} + style={mergePartial(xAxisStyle, { + tickLine: { size: 0.0001, padding: -6, ...gridStyle }, + })} + labelFormat={midAxisLabelFormatter} /> { - return d % (30 * 60 * 1000) === 0 - ? `${new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'numeric', day: 'numeric' }).format(d)}` - : ''; - }} + labelFormat={bottomAxisLabelFormatter} /> { tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8, padding: 8 }, axisLine: { ...gridStyle, visible: false }, tickLabel: { ...tickLabelStyle }, - axisTitle: { visible: true }, + axisTitle: { visible: true, fontFamily, fill: axisTitleColor, fontSize: axisTitleFontSize }, }} - tickFormat={(d) => Number(d).toFixed(2)} + tickFormat={(d) => `${Number(d).toFixed(0)}%`} /> Date: Tue, 31 Aug 2021 18:37:11 +0200 Subject: [PATCH 11/75] test: baseline for whiskers --- storybook/stories/area/21_with_time_timeslip.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index baa08c2ce8..9720adac9e 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -100,6 +100,10 @@ export const Example = () => { showGridLines gridLine={gridStyle} style={mergePartial(xAxisStyle, { + tickLabel: { + padding: 0, + offset: { x: 0, y: 0 }, + }, tickLine: { size: 0.0001, padding: -6, ...gridStyle }, })} labelFormat={midAxisLabelFormatter} From 72256a9902bd8d03c49cd8a9ee8ad64bb7b812e9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 19:28:39 +0200 Subject: [PATCH 12/75] test: whisker knob --- .../stories/area/21_with_time_timeslip.tsx | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 9720adac9e..c832ad9d37 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -6,15 +6,14 @@ * Side Public License, v 1. */ -import { number } from '@storybook/addon-knobs'; +import { boolean } from '@storybook/addon-knobs'; import React from 'react'; -import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings } from '@elastic/charts'; -import { isDefined, mergePartial } from '@elastic/charts/src/utils/common'; +import { AreaSeries, Axis, Chart, Position, ScaleType, Settings } from '@elastic/charts'; +import { mergePartial } from '@elastic/charts/src/utils/common'; import { KIBANA_METRICS } from '@elastic/charts/src/utils/data_samples/test_dataset_kibana'; import { useBaseTheme } from '../../use_base_theme'; -import { getChartRotationKnob, getPlacementKnob, getStickToKnob } from '../utils/knobs'; import { SB_SOURCE_PANEL } from '../utils/storybook'; const minorGridStyle = { stroke: 'black', strokeWidth: 0.15, opacity: 1 }; @@ -23,6 +22,7 @@ const fontFamily = '"Atkinson Hyperlegible"'; const tickLabelStyle = { fontSize: 11, fontFamily, fill: 'rgba(0,0,0,0.8)' }; const axisTitleColor = 'rgb(112,112,112)'; const axisTitleFontSize = 15; +const dataInk = 'rgba(96, 146, 192, 1)'; const xAxisStyle = { tickLine: { size: 0.0001, padding: -6, ...gridStyle }, @@ -39,10 +39,6 @@ const xAxisStyle = { const data = KIBANA_METRICS.metrics.kibana_os_load[0].data; const t0 = data[0][0]; -const topAxisLabelFormat = (d: any) => { - // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; - return `${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }).format(d).padStart(2, '0')}′ `; -}; const midAxisLabelFormatter = (d: any) => { return `${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} `; }; @@ -51,18 +47,16 @@ const bottomAxisLabelFormatter = (d: any) => { }; export const Example = () => { + const whiskers = boolean('X axis whiskers', true); + const topAxisLabelFormat = (d: any) => { + // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; + return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }) + .format(d) + .padStart(2, '0')}′ `; + }; return ( - + { ticks={100} showGridLines gridLine={mergePartial(gridStyle, { strokeWidth: 0.1 })} - style={mergePartial(xAxisStyle, { - tickLine: { padding: 6 }, - })} + style={mergePartial( + xAxisStyle, + whiskers + ? { + axisLine: { stroke: dataInk, strokeWidth: 1, visible: true }, + tickLine: { size: 16, padding: -10, ...minorGridStyle }, + } + : { tickLine: { padding: 6 } }, + )} labelFormat={topAxisLabelFormat} /> { yAccessors={[1]} yNice areaSeriesStyle={{ - area: { fill: 'rgba(96, 146, 192, 1)', opacity: 0.3 }, - line: { stroke: 'rgba(96, 146, 192, 1)', opacity: 1 }, + area: { fill: dataInk, opacity: 0.3 }, + line: { stroke: dataInk, opacity: 1 }, }} data={data.map(([t, v]) => [t0 + (t - t0) * 4, v])} /> From d958102f9a845019fad4e957426f80f0d1d16141 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 19:49:16 +0200 Subject: [PATCH 13/75] test: horizontal axis title knob --- .../stories/area/21_with_time_timeslip.tsx | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index c832ad9d37..7711ca6b46 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -48,26 +48,37 @@ const bottomAxisLabelFormatter = (d: any) => { export const Example = () => { const whiskers = boolean('X axis whiskers', true); + const horizontalAxisTitle = boolean('Horizontal axis title', false); const topAxisLabelFormat = (d: any) => { // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }) .format(d) .padStart(2, '0')}′ `; }; + const yAxisTitle = 'CPU utilization'; return ( ''} + tickFormat={() => (horizontalAxisTitle ? yAxisTitle : '')} ticks={0} showGridLines gridLine={gridStyle} style={mergePartial(xAxisStyle, { axisTitle: { visible: true, fontFamily, fontSize: 24, fill: 'grey' }, - tickLabel: { padding: 4 }, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + tickLabel: horizontalAxisTitle + ? { + fill: 'rgb(64,64,64)', + fontSize: axisTitleFontSize, + padding: 20, + alignment: { horizontal: 'center', vertical: Position.Bottom }, + } + : {}, })} /> { showGridLines gridLine={gridStyle} style={mergePartial(xAxisStyle, { - axisTitle: { visible: true, fontFamily }, + axisTitle: { visible: !horizontalAxisTitle, fontFamily }, })} labelFormat={bottomAxisLabelFormatter} /> { tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8, padding: 8 }, axisLine: { ...gridStyle, visible: false }, tickLabel: { ...tickLabelStyle }, - axisTitle: { visible: true, fontFamily, fill: axisTitleColor, fontSize: axisTitleFontSize }, + axisTitle: { visible: !horizontalAxisTitle, fontFamily, fill: axisTitleColor, fontSize: axisTitleFontSize }, }} tickFormat={(d) => `${Number(d).toFixed(0)}%`} /> From ca708750f7e5ab2b54da04100753d83ef9779b6c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 19:58:05 +0200 Subject: [PATCH 14/75] test: indenting the higher time axes too --- .../stories/area/21_with_time_timeslip.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 7711ca6b46..4c6592c268 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -39,13 +39,6 @@ const xAxisStyle = { const data = KIBANA_METRICS.metrics.kibana_os_load[0].data; const t0 = data[0][0]; -const midAxisLabelFormatter = (d: any) => { - return `${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} `; -}; -const bottomAxisLabelFormatter = (d: any) => { - return `${new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' }).format(d)} `; -}; - export const Example = () => { const whiskers = boolean('X axis whiskers', true); const horizontalAxisTitle = boolean('Horizontal axis title', false); @@ -55,6 +48,18 @@ export const Example = () => { .format(d) .padStart(2, '0')}′ `; }; + const midAxisLabelFormatter = (d: any) => { + return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }) + .format(d) + .padStart(2, '0')} `; + }; + const bottomAxisLabelFormatter = (d: any) => { + return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + }).format(d)} `; + }; const yAxisTitle = 'CPU utilization'; return ( From af35693f9b1a935bb354bf31436309dfc922a54b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 31 Aug 2021 20:12:49 +0200 Subject: [PATCH 15/75] test: mock update --- ...timeslip-visually-looks-correct-1-snap.png | Bin 30573 -> 35061 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 2a5b78198ff233d56dd0217d695eaf9d26b96bea..892ba6d7e53e27a0d1685373a38863a2f7c05f25 100644 GIT binary patch literal 35061 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 CAI-x6 literal 30573 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 Date: Tue, 31 Aug 2021 20:41:15 +0200 Subject: [PATCH 16/75] test: more knobs --- ...timeslip-visually-looks-correct-1-snap.png | Bin 35061 -> 34792 bytes .../stories/area/21_with_time_timeslip.tsx | 14 ++++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 892ba6d7e53e27a0d1685373a38863a2f7c05f25..681bfe6d542a62a93bdffb237bb359e68feaf628 100644 GIT binary patch delta 16969 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 delta 17240 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 NSxKeW-^C65{s({ZavlHx diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index 4c6592c268..b841384cc6 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -40,7 +40,9 @@ const data = KIBANA_METRICS.metrics.kibana_os_load[0].data; const t0 = data[0][0]; export const Example = () => { - const whiskers = boolean('X axis whiskers', true); + const whiskers = boolean('X axis minor whiskers', true); + const shortWhiskers = boolean('Shorter X axis minor whiskers', true); + const minorGridLines = boolean('Minor grid lines', true); const horizontalAxisTitle = boolean('Horizontal axis title', false); const topAxisLabelFormat = (d: any) => { // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; @@ -87,26 +89,26 @@ export const Example = () => { })} /> { labelFormat={midAxisLabelFormatter} /> Date: Tue, 31 Aug 2021 21:49:42 +0200 Subject: [PATCH 17/75] test: smaller y axis padding --- storybook/stories/area/21_with_time_timeslip.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.tsx index b841384cc6..b8c8356919 100644 --- a/storybook/stories/area/21_with_time_timeslip.tsx +++ b/storybook/stories/area/21_with_time_timeslip.tsx @@ -68,7 +68,7 @@ export const Example = () => { (horizontalAxisTitle ? yAxisTitle : '')} ticks={0} @@ -149,7 +149,7 @@ export const Example = () => { ticks={4} gridLine={minorGridStyle} style={{ - tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8, padding: 8 }, + tickLine: { ...gridStyle, strokeWidth: 0.2, size: 8, padding: 4 }, axisLine: { ...gridStyle, visible: false }, tickLabel: { ...tickLabelStyle }, axisTitle: { visible: !horizontalAxisTitle, fontFamily, fill: axisTitleColor, fontSize: axisTitleFontSize }, From 2e199aead6b62093381547ade22f416ec66161eb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 20:53:06 +0200 Subject: [PATCH 18/75] refactor: getAxesSpecForSpecId simplification --- .../chart_types/xy_chart/state/utils/spec.ts | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts b/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts index 4cafe964ae..c1d48f121f 100644 --- a/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts +++ b/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts @@ -8,7 +8,7 @@ import { BasicSeriesSpec, DEFAULT_GLOBAL_ID, Spec } from '../../../../specs'; import { GroupId } from '../../../../utils/ids'; -import { isVerticalAxis } from '../../utils/axis_type_utils'; +import { isHorizontalAxis, isVerticalAxis } from '../../utils/axis_type_utils'; import { AxisSpec } from '../../utils/specs'; /** @internal */ @@ -18,23 +18,10 @@ export function getSpecsById(specs: T[], id: string): T | undefi /** @internal */ export function getAxesSpecForSpecId(axesSpecs: AxisSpec[], groupId: GroupId) { - let xAxis: AxisSpec | undefined; - let yAxis: AxisSpec | undefined; - // eslint-disable-next-line no-restricted-syntax - for (const axisSpec of axesSpecs) { - if (axisSpec.groupId !== groupId) { - continue; - } - if (isVerticalAxis(axisSpec.position)) { - yAxis = axisSpec; - } else { - xAxis = axisSpec; - } - } - + const groupSpecs = axesSpecs.filter((spec) => spec.groupId === groupId).reverse(); return { - xAxis, - yAxis, + xAxis: groupSpecs.find((spec) => isHorizontalAxis(spec.position)), + yAxis: groupSpecs.find((spec) => isVerticalAxis(spec.position)), }; } From 2cb238b41416d42fd8708509ff04d77e8eb7cb1a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 21:12:50 +0200 Subject: [PATCH 19/75] perf: getAxesSpecForSpecId restore perf --- .../src/chart_types/xy_chart/state/utils/spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts b/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts index c1d48f121f..728dc41723 100644 --- a/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts +++ b/packages/charts/src/chart_types/xy_chart/state/utils/spec.ts @@ -18,11 +18,11 @@ export function getSpecsById(specs: T[], id: string): T | undefi /** @internal */ export function getAxesSpecForSpecId(axesSpecs: AxisSpec[], groupId: GroupId) { - const groupSpecs = axesSpecs.filter((spec) => spec.groupId === groupId).reverse(); - return { - xAxis: groupSpecs.find((spec) => isHorizontalAxis(spec.position)), - yAxis: groupSpecs.find((spec) => isVerticalAxis(spec.position)), - }; + return axesSpecs.reduce<{ xAxis?: AxisSpec; yAxis?: AxisSpec }>((result, spec) => { + if (spec.groupId === groupId && isHorizontalAxis(spec.position)) result.xAxis = spec; + if (spec.groupId === groupId && isVerticalAxis(spec.position)) result.yAxis = spec; + return result; + }, {}); } /** @internal */ From 566fe6c67f5e97f611e57cf5962e06f5ab6badac Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 21:41:56 +0200 Subject: [PATCH 20/75] refactor: single use binding gone --- .../charts/src/chart_types/xy_chart/utils/axis_utils.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 4fc332fafe..440a885bd7 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -684,7 +684,6 @@ export function getAxesGeometries( barsPadding?: number, ): Array { const axesGeometries: Array = []; - const { chartDimensions } = computedChartDims; const panel = getPanelSize(smScales); const anchorPointByAxisGroups = [...axisDimensions.entries()].reduce( @@ -696,12 +695,11 @@ export function getAxesGeometries( } const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; - const showTicks = shouldShowTicks(tickLine, axisSpec.hide); - const tickDimension = showTicks ? tickLine.size + tickLine.padding : 0; + const tickDimension = shouldShowTicks(tickLine, axisSpec.hide) ? tickLine.size + tickLine.padding : 0; const labelPaddingSum = tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = getAxisPosition( - chartDimensions, + computedChartDims.chartDimensions, chartMargins, axisTitle, axisPanelTitle, From cc8a37ffa3c113e4acfd6a471e336a73fda2c542 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 22:42:11 +0200 Subject: [PATCH 21/75] refactor: removed redundant if branches --- .../chart_types/xy_chart/utils/axis_utils.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 440a885bd7..320d1be1ea 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -548,26 +548,21 @@ export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDi const requiredSpace = isVerticalAxis(axisSpec.position) ? maxLabelBboxHeight / 2 : maxLabelBboxWidth / 2; - let previousOccupiedSpace = 0; + let previousOccupiedSpace = -Infinity; const visibleTicks = []; for (let i = 0; i < allTicks.length; i++) { const { position } = allTicks[i]; - if (i === 0) { + if (position >= previousOccupiedSpace + requiredSpace) { visibleTicks.push(allTicks[i]); previousOccupiedSpace = position + requiredSpace; - } else if (position - requiredSpace >= previousOccupiedSpace) { - visibleTicks.push(allTicks[i]); - previousOccupiedSpace = position + requiredSpace; - } else { + } else if (showOverlappingTicks || showOverlappingLabels) { // still add the tick but without a label - if (showOverlappingTicks || showOverlappingLabels) { - const overlappingTick = { - ...allTicks[i], - label: showOverlappingLabels ? allTicks[i].label : '', - }; - visibleTicks.push(overlappingTick); - } + const overlappingTick = { + ...allTicks[i], + label: showOverlappingLabels ? allTicks[i].label : '', + }; + visibleTicks.push(overlappingTick); } } return visibleTicks; From 546544a841ab02dbd53dc3767273eccada39f547 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 22:42:23 +0200 Subject: [PATCH 22/75] chore: post merge fix --- ...{21_with_time_timeslip.tsx => 21_with_time_timeslip.story.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename storybook/stories/area/{21_with_time_timeslip.tsx => 21_with_time_timeslip.story.tsx} (100%) diff --git a/storybook/stories/area/21_with_time_timeslip.tsx b/storybook/stories/area/21_with_time_timeslip.story.tsx similarity index 100% rename from storybook/stories/area/21_with_time_timeslip.tsx rename to storybook/stories/area/21_with_time_timeslip.story.tsx From 82a01c724d2dbfc53c67301de0ea9b9fe4b80c2e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 23:18:35 +0200 Subject: [PATCH 23/75] refactor: avoid any work in some cases --- .../chart_types/xy_chart/utils/axis_utils.ts | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 320d1be1ea..a986d74538 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -545,27 +545,22 @@ export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDi const { showOverlappingTicks, showOverlappingLabels } = axisSpec; const { maxLabelBboxHeight, maxLabelBboxWidth } = axisDim; - const requiredSpace = isVerticalAxis(axisSpec.position) ? maxLabelBboxHeight / 2 : maxLabelBboxWidth / 2; - - let previousOccupiedSpace = -Infinity; - const visibleTicks = []; - for (let i = 0; i < allTicks.length; i++) { - const { position } = allTicks[i]; - - if (position >= previousOccupiedSpace + requiredSpace) { - visibleTicks.push(allTicks[i]); - previousOccupiedSpace = position + requiredSpace; - } else if (showOverlappingTicks || showOverlappingLabels) { - // still add the tick but without a label - const overlappingTick = { - ...allTicks[i], - label: showOverlappingLabels ? allTicks[i].label : '', - }; - visibleTicks.push(overlappingTick); - } - } - return visibleTicks; + return showOverlappingLabels + ? allTicks + : allTicks.reduce( + (prev, tick, i) => { + if (i && !(allTicks[i - 1].position <= tick.position)) throw new Error('Hey wrong sort order'); + if (tick.position >= prev.occupiedSpace + requiredSpace) { + prev.visibleTicks.push(tick); + prev.occupiedSpace = tick.position + requiredSpace; + } else if (showOverlappingTicks) { + prev.visibleTicks.push({ ...tick, label: '' }); + } + return prev; + }, + { visibleTicks: [] as AxisTick[], occupiedSpace: -Infinity }, + ).visibleTicks; } /** @internal */ From f4dfc44dfb1c60ad16be15c0b182b7e30a52722b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 23:42:00 +0200 Subject: [PATCH 24/75] test: mock update --- ...timeslip-visually-looks-correct-1-snap.png | Bin 34792 -> 35181 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-timeslip-visually-looks-correct-1-snap.png index 681bfe6d542a62a93bdffb237bb359e68feaf628..0632a6588b71a997732ac2c9c6e99ce42d90ea16 100644 GIT binary patch literal 35181 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 Date: Thu, 2 Sep 2021 23:42:48 +0200 Subject: [PATCH 25/75] refactor: don't destructively modify the input --- .../src/chart_types/xy_chart/utils/axis_utils.test.ts | 2 +- .../charts/src/chart_types/xy_chart/utils/axis_utils.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 62aeff45ea..3085323a31 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -1640,7 +1640,7 @@ describe('Axis computational utils', () => { customFormatter, ); - const expected = axis1Dims.tickValues.slice().reverse().map(customFormatter); + const expected = axis1Dims.tickValues.map(customFormatter); const axisPos = axisTicksPosition.find(({ axis: { id } }) => id === verticalAxisSpec.id); expect(axisPos?.ticks.map(({ label }) => label)).toEqual(expected); }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index a986d74538..5b6d35558a 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -541,16 +541,16 @@ export function enableDuplicatedTicks( /** @internal */ export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: AxisViewModel): AxisTick[] { // We sort the ticks by position so that we can incrementally compute previousOccupiedSpace - allTicks.sort((a: AxisTick, b: AxisTick) => a.position - b.position); + const sortedTicks = allTicks.slice().sort((a: AxisTick, b: AxisTick) => a.position - b.position); const { showOverlappingTicks, showOverlappingLabels } = axisSpec; const { maxLabelBboxHeight, maxLabelBboxWidth } = axisDim; const requiredSpace = isVerticalAxis(axisSpec.position) ? maxLabelBboxHeight / 2 : maxLabelBboxWidth / 2; return showOverlappingLabels - ? allTicks - : allTicks.reduce( + ? sortedTicks + : sortedTicks.reduce( (prev, tick, i) => { - if (i && !(allTicks[i - 1].position <= tick.position)) throw new Error('Hey wrong sort order'); + if (i && !(sortedTicks[i - 1].position <= tick.position)) throw new Error('Hey wrong sort order'); if (tick.position >= prev.occupiedSpace + requiredSpace) { prev.visibleTicks.push(tick); prev.occupiedSpace = tick.position + requiredSpace; From 53ecfcc5b9346bf571b81a1f77bbb2f3e0a0d9c6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 23:50:20 +0200 Subject: [PATCH 26/75] refactor: removed order check and some single use vars --- .../charts/src/chart_types/xy_chart/utils/axis_utils.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 5b6d35558a..53d5e86f8c 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -542,15 +542,12 @@ export function enableDuplicatedTicks( export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: AxisViewModel): AxisTick[] { // We sort the ticks by position so that we can incrementally compute previousOccupiedSpace const sortedTicks = allTicks.slice().sort((a: AxisTick, b: AxisTick) => a.position - b.position); - - const { showOverlappingTicks, showOverlappingLabels } = axisSpec; - const { maxLabelBboxHeight, maxLabelBboxWidth } = axisDim; - const requiredSpace = isVerticalAxis(axisSpec.position) ? maxLabelBboxHeight / 2 : maxLabelBboxWidth / 2; + const { showOverlappingTicks, showOverlappingLabels, position } = axisSpec; + const requiredSpace = isVerticalAxis(position) ? axisDim.maxLabelBboxHeight / 2 : axisDim.maxLabelBboxWidth / 2; return showOverlappingLabels ? sortedTicks : sortedTicks.reduce( (prev, tick, i) => { - if (i && !(sortedTicks[i - 1].position <= tick.position)) throw new Error('Hey wrong sort order'); if (tick.position >= prev.occupiedSpace + requiredSpace) { prev.visibleTicks.push(tick); prev.occupiedSpace = tick.position + requiredSpace; From 141c2ab528cd654b63510430ece22b27172a43b8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 2 Sep 2021 23:54:50 +0200 Subject: [PATCH 27/75] refactor: reduction update in one place only --- .../src/chart_types/xy_chart/utils/axis_utils.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 53d5e86f8c..2794947ee5 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -540,19 +540,17 @@ export function enableDuplicatedTicks( /** @internal */ export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: AxisViewModel): AxisTick[] { - // We sort the ticks by position so that we can incrementally compute previousOccupiedSpace - const sortedTicks = allTicks.slice().sort((a: AxisTick, b: AxisTick) => a.position - b.position); const { showOverlappingTicks, showOverlappingLabels, position } = axisSpec; const requiredSpace = isVerticalAxis(position) ? axisDim.maxLabelBboxHeight / 2 : axisDim.maxLabelBboxWidth / 2; + const sortedTicks = allTicks.slice().sort((a: AxisTick, b: AxisTick) => a.position - b.position); return showOverlappingLabels ? sortedTicks : sortedTicks.reduce( - (prev, tick, i) => { - if (tick.position >= prev.occupiedSpace + requiredSpace) { - prev.visibleTicks.push(tick); - prev.occupiedSpace = tick.position + requiredSpace; - } else if (showOverlappingTicks) { - prev.visibleTicks.push({ ...tick, label: '' }); + (prev, tick) => { + const tickLabelFits = tick.position >= prev.occupiedSpace + requiredSpace; + if (tickLabelFits || showOverlappingTicks) { + prev.visibleTicks.push(tickLabelFits ? tick : { ...tick, label: '' }); + if (tickLabelFits) prev.occupiedSpace = tick.position + requiredSpace; } return prev; }, From 23c865ea3bec5bfdfcc0fee5f9a166ababf1fdf6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 09:04:13 +0200 Subject: [PATCH 28/75] chore: declare before first occurrence --- .../goal_chart/layout/viewmodel/viewmodel.ts | 10 +++++----- .../src/chart_types/xy_chart/utils/axis_utils.ts | 7 +------ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/viewmodel.ts b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/viewmodel.ts index 02c4babc76..a3a3ad2da6 100644 --- a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/viewmodel.ts +++ b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/viewmodel.ts @@ -22,11 +22,6 @@ export function shapeViewModel(spec: GoalSpec, theme: Theme, chartDimensions: Di y: margin.top + innerHeight / 2, }; - const pickQuads: PickFunction = (x, y) => - -innerWidth / 2 <= x && x <= innerWidth / 2 && -innerHeight / 2 <= y && y <= innerHeight / 2 - ? [bulletViewModel] - : []; - const { subtype, base, @@ -91,6 +86,11 @@ export function shapeViewModel(spec: GoalSpec, theme: Theme, chartDimensions: Di angleEnd, }; + const pickQuads: PickFunction = (x, y) => + -innerWidth / 2 <= x && x <= innerWidth / 2 && -innerHeight / 2 <= y && y <= innerHeight / 2 + ? [bulletViewModel] + : []; + return { config: theme.goal, chartCenter, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 2794947ee5..6105ec2263 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -588,12 +588,7 @@ export function getAxisPosition( const { position } = axisSpec; const { maxLabelBboxHeight, maxLabelBboxWidth } = axisDim; const { top, left, height, width } = chartDimensions; - const dimensions = { - top, - left, - width, - height, - }; + const dimensions = { top, left, width, height }; let topIncrement = 0; let bottomIncrement = 0; let leftIncrement = 0; From d9ed46e452c1a1a1d7ce0b24afebd050a6a344ef Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 09:29:30 +0200 Subject: [PATCH 29/75] test: knobs --- storybook/stories/area/21_with_time_timeslip.story.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.story.tsx b/storybook/stories/area/21_with_time_timeslip.story.tsx index b8c8356919..e24a494466 100644 --- a/storybook/stories/area/21_with_time_timeslip.story.tsx +++ b/storybook/stories/area/21_with_time_timeslip.story.tsx @@ -91,7 +91,8 @@ export const Example = () => { { id="x_major" title="timestamp per 1 minute" position={Position.Bottom} - showOverlappingTicks={false} + showOverlappingTicks={boolean('showOverlappingTicks bottom axis', false)} + showOverlappingLabels={boolean('showOverlappingLabels bottom axis', false)} showDuplicatedTicks={false} tickFormat={midAxisLabelFormatter} ticks={1} @@ -130,7 +132,8 @@ export const Example = () => { id="x_context" title="time (1-minute measurements)" position={Position.Bottom} - showOverlappingTicks={false} + showOverlappingTicks={boolean('showOverlappingTicks bottom axis', false)} + showOverlappingLabels={boolean('showOverlappingLabels bottom axis', false)} showDuplicatedTicks={false} tickFormat={bottomAxisLabelFormatter} ticks={2} From 7f81cd3b1675bf4c40c3ad76d5ba47a5f7a222b9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 10:32:01 +0200 Subject: [PATCH 30/75] refactor: fewer sorting --- .../xy_chart/utils/axis_utils.test.ts | 18 ++++++++----- .../chart_types/xy_chart/utils/axis_utils.ts | 27 ++++++++++--------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 3085323a31..54da985f84 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -51,6 +51,8 @@ import { computeXScale } from './scales'; import { AxisSpec, DomainRange, DEFAULT_GLOBAL_ID } from './specs'; const NO_ROTATION = 0; +const tickSorter = (a: AxisTick, b: AxisTick) => a.position - b.position; +const gridSorter = ([, a]: number[], [, b]: number[]) => a - b; const getCustomStyle = (rotation = 0, padding = 10): AxisStyle => mergePartial(LIGHT_THEME.axes, { @@ -503,7 +505,7 @@ describe('Axis computational utils', () => { { label: '0.1', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks).toEqual(expectedVisibleTicks); + expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); }); test('should compute visible ticks for a horizontal axis', () => { const allTicks = [ @@ -534,7 +536,7 @@ describe('Axis computational utils', () => { { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks).toEqual(expectedVisibleTicks); + expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); }); test('should hide some ticks', () => { const allTicks = [ @@ -570,7 +572,7 @@ describe('Axis computational utils', () => { { label: '0.2', position: 80, value: 0.2 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks).toEqual(expectedVisibleTicks); + expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); }); test('should show all overlapping ticks and labels if configured to', () => { const allTicks = [ @@ -614,7 +616,7 @@ describe('Axis computational utils', () => { { label: '0.1', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleOverlappingTicks).toEqual(expectedVisibleOverlappingTicks); + expect(visibleOverlappingTicks.sort(tickSorter)).toEqual(expectedVisibleOverlappingTicks.sort(tickSorter)); verticalAxisSpec.showOverlappingTicks = true; verticalAxisSpec.showOverlappingLabels = false; @@ -632,7 +634,9 @@ describe('Axis computational utils', () => { { label: '', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleOverlappingTicksAndLabels).toEqual(expectedVisibleOverlappingTicksAndLabels); + expect(visibleOverlappingTicksAndLabels.sort(tickSorter)).toEqual( + expectedVisibleOverlappingTicksAndLabels.sort(tickSorter), + ); }); test('should compute min max range for on 0 deg bottom', () => { const minMax = getMinMaxRange(Position.Bottom, 0, { @@ -1223,7 +1227,9 @@ describe('Axis computational utils', () => { const [{ lines }] = gridLines[0].lineGroups; - expect(lines.map(({ x1, y1, x2, y2 }) => [x1, y1, x2, y2])).toEqual(expectedVerticalAxisGridLines); + expect(lines.map(({ x1, y1, x2, y2 }) => [x1, y1, x2, y2]).sort(gridSorter)).toEqual( + expectedVerticalAxisGridLines.sort(gridSorter), + ); const axisTicksPositionWithTopLegend = computeAxesGeometriesSelector(store.getState()); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 6105ec2263..bf0cb27f98 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -542,20 +542,21 @@ export function enableDuplicatedTicks( export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: AxisViewModel): AxisTick[] { const { showOverlappingTicks, showOverlappingLabels, position } = axisSpec; const requiredSpace = isVerticalAxis(position) ? axisDim.maxLabelBboxHeight / 2 : axisDim.maxLabelBboxWidth / 2; - const sortedTicks = allTicks.slice().sort((a: AxisTick, b: AxisTick) => a.position - b.position); return showOverlappingLabels - ? sortedTicks - : sortedTicks.reduce( - (prev, tick) => { - const tickLabelFits = tick.position >= prev.occupiedSpace + requiredSpace; - if (tickLabelFits || showOverlappingTicks) { - prev.visibleTicks.push(tickLabelFits ? tick : { ...tick, label: '' }); - if (tickLabelFits) prev.occupiedSpace = tick.position + requiredSpace; - } - return prev; - }, - { visibleTicks: [] as AxisTick[], occupiedSpace: -Infinity }, - ).visibleTicks; + ? allTicks + : [...allTicks] + .sort((a: AxisTick, b: AxisTick) => a.position - b.position) + .reduce( + (prev, tick) => { + const tickLabelFits = tick.position >= prev.occupiedSpace + requiredSpace; + if (tickLabelFits || showOverlappingTicks) { + prev.visibleTicks.push(tickLabelFits ? tick : { ...tick, label: '' }); + if (tickLabelFits) prev.occupiedSpace = tick.position + requiredSpace; + } + return prev; + }, + { visibleTicks: [] as AxisTick[], occupiedSpace: -Infinity }, + ).visibleTicks; } /** @internal */ From 18405753a4c547dad34c1e057cb34bb9d73e76c5 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 10:39:51 +0200 Subject: [PATCH 31/75] chore: comment --- .../charts/src/chart_types/xy_chart/utils/axis_utils.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 54da985f84..50b7520abd 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -51,6 +51,8 @@ import { computeXScale } from './scales'; import { AxisSpec, DomainRange, DEFAULT_GLOBAL_ID } from './specs'; const NO_ROTATION = 0; + +// the comparisons where we use these are (unsorted) set comparisons, not (sorted) list comparisons, so we unify possibly different orders for comparisons here const tickSorter = (a: AxisTick, b: AxisTick) => a.position - b.position; const gridSorter = ([, a]: number[], [, b]: number[]) => a - b; From 6472fcd5e3fdf916a89b4f67a7137cd4a755040c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 11:14:32 +0200 Subject: [PATCH 32/75] test: toIncludeSameMembers --- .../xy_chart/utils/axis_utils.test.ts | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 50b7520abd..d1739e564c 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -52,10 +52,6 @@ import { AxisSpec, DomainRange, DEFAULT_GLOBAL_ID } from './specs'; const NO_ROTATION = 0; -// the comparisons where we use these are (unsorted) set comparisons, not (sorted) list comparisons, so we unify possibly different orders for comparisons here -const tickSorter = (a: AxisTick, b: AxisTick) => a.position - b.position; -const gridSorter = ([, a]: number[], [, b]: number[]) => a - b; - const getCustomStyle = (rotation = 0, padding = 10): AxisStyle => mergePartial(LIGHT_THEME.axes, { tickLine: { @@ -507,7 +503,7 @@ describe('Axis computational utils', () => { { label: '0.1', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); + expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should compute visible ticks for a horizontal axis', () => { const allTicks = [ @@ -538,7 +534,7 @@ describe('Axis computational utils', () => { { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); + expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should hide some ticks', () => { const allTicks = [ @@ -574,7 +570,7 @@ describe('Axis computational utils', () => { { label: '0.2', position: 80, value: 0.2 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleTicks.sort(tickSorter)).toEqual(expectedVisibleTicks.sort(tickSorter)); + expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should show all overlapping ticks and labels if configured to', () => { const allTicks = [ @@ -618,7 +614,7 @@ describe('Axis computational utils', () => { { label: '0.1', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleOverlappingTicks.sort(tickSorter)).toEqual(expectedVisibleOverlappingTicks.sort(tickSorter)); + expect(visibleOverlappingTicks).toIncludeSameMembers(expectedVisibleOverlappingTicks); verticalAxisSpec.showOverlappingTicks = true; verticalAxisSpec.showOverlappingLabels = false; @@ -636,9 +632,7 @@ describe('Axis computational utils', () => { { label: '', position: 90, value: 0.1 }, { label: '0', position: 100, value: 0 }, ]; - expect(visibleOverlappingTicksAndLabels.sort(tickSorter)).toEqual( - expectedVisibleOverlappingTicksAndLabels.sort(tickSorter), - ); + expect(visibleOverlappingTicksAndLabels).toIncludeSameMembers(expectedVisibleOverlappingTicksAndLabels); }); test('should compute min max range for on 0 deg bottom', () => { const minMax = getMinMaxRange(Position.Bottom, 0, { @@ -1229,9 +1223,7 @@ describe('Axis computational utils', () => { const [{ lines }] = gridLines[0].lineGroups; - expect(lines.map(({ x1, y1, x2, y2 }) => [x1, y1, x2, y2]).sort(gridSorter)).toEqual( - expectedVerticalAxisGridLines.sort(gridSorter), - ); + expect(lines.map(({ x1, y1, x2, y2 }) => [x1, y1, x2, y2])).toIncludeSameMembers(expectedVerticalAxisGridLines); const axisTicksPositionWithTopLegend = computeAxesGeometriesSelector(store.getState()); From 93adb08a2709d64ee0dfcf5aaf65965e081b969e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 22:23:07 +0200 Subject: [PATCH 33/75] refactor: sort related updates and AxesTicksDimensions type --- .../goal_chart/layout/viewmodel/geoms.ts | 3 +- .../partition_chart/state/selectors/tree.ts | 23 +++----- .../xy_chart/annotations/tooltip.ts | 6 +- .../chart_types/xy_chart/axes/axes_sizes.ts | 5 +- .../chart_types/xy_chart/domains/x_domain.ts | 4 +- .../state/chart_state.interactions.test.tsx | 3 +- .../xy_chart/state/chart_state.test.ts | 6 +- .../compute_axis_ticks_dimensions.ts | 59 ++++++++++--------- .../xy_chart/utils/axis_utils.test.ts | 10 +++- .../chart_types/xy_chart/utils/axis_utils.ts | 5 +- .../xy_chart/utils/dimensions.test.ts | 15 ++--- .../chart_types/xy_chart/utils/dimensions.ts | 4 +- .../src/chart_types/xy_chart/utils/series.ts | 7 +-- .../stories/axes/12_duplicate_ticks.story.tsx | 2 +- .../axes/13_label_formatting.story.tsx | 4 +- .../interactions/11_brush_time.story.tsx | 2 +- 16 files changed, 81 insertions(+), 77 deletions(-) diff --git a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts index 08017e8daa..13d957e4a3 100644 --- a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts +++ b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts @@ -405,8 +405,7 @@ export function geoms( const angleScale = (x: number) => angleStart + (angleRange * (x - domain[0])) / domainExtent; const clockwise = angleStart > angleEnd; // todo refine this crude approach - const geomObjects = abstractGeoms - .slice() + const [...geomObjects] = abstractGeoms .sort((a, b) => a.order - b.order) .map(({ landmarks, aes }) => { const at = get(landmarks, 'at', ''); diff --git a/packages/charts/src/chart_types/partition_chart/state/selectors/tree.ts b/packages/charts/src/chart_types/partition_chart/state/selectors/tree.ts index 85e61c3881..77e8af95d5 100644 --- a/packages/charts/src/chart_types/partition_chart/state/selectors/tree.ts +++ b/packages/charts/src/chart_types/partition_chart/state/selectors/tree.ts @@ -69,21 +69,14 @@ function getTreesForSpec( group.push(next); return map; }, new Map()); - return Array.from(groups) - .sort(getPredicateFn(sort)) - .map(([groupKey, subData], innerIndex) => ({ - name: format(groupKey), - smAccessorValue: groupKey, - style: smStyle, - tree: partitionTree( - subData, - valueAccessor, - layers, - configMetadata.partitionLayout.dflt, - config.partitionLayout, - [{ index: innerIndex, value: String(groupKey) }], - ), - })); + return [...groups].sort(getPredicateFn(sort)).map(([groupKey, subData], innerIndex) => ({ + name: format(groupKey), + smAccessorValue: groupKey, + style: smStyle, + tree: partitionTree(subData, valueAccessor, layers, configMetadata.partitionLayout.dflt, config.partitionLayout, [ + { index: innerIndex, value: String(groupKey) }, + ]), + })); } else { return [ { diff --git a/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts b/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts index 4235356fe3..fe12033b1e 100644 --- a/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts +++ b/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts @@ -27,8 +27,7 @@ export function computeRectAnnotationTooltipState( // allow picking up the last spec added as the top most or use it's zIndex value const sortedAnnotationSpecs = annotationSpecs .filter(isRectAnnotation) - .reverse() - .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => b - a); + .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => a - b); for (let i = 0; i < sortedAnnotationSpecs.length; i++) { const spec = sortedAnnotationSpecs[i]; @@ -72,8 +71,7 @@ export function computeMultipleRectAnnotationTooltipState( // allow picking up the last spec added as the top most or use it's zIndex value const sortedAnnotationSpecs = annotationSpecs .filter(isRectAnnotation) - .reverse() - .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => b - a); + .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => a - b); return sortedAnnotationSpecs.reduce((acc, spec) => { const annotationDimension = annotationDimensions.get(spec.id); if (!spec.hideTooltips && annotationDimension) { diff --git a/packages/charts/src/chart_types/xy_chart/axes/axes_sizes.ts b/packages/charts/src/chart_types/xy_chart/axes/axes_sizes.ts index 8cf1c2d85a..83a4fafc35 100644 --- a/packages/charts/src/chart_types/xy_chart/axes/axes_sizes.ts +++ b/packages/charts/src/chart_types/xy_chart/axes/axes_sizes.ts @@ -11,15 +11,16 @@ import { Position } from '../../../utils/common'; import { innerPad, outerPad, PerSideDistance } from '../../../utils/dimensions'; import { AxisId } from '../../../utils/ids'; import { AxisStyle, Theme } from '../../../utils/themes/theme'; +import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; import { getSpecsById } from '../state/utils/spec'; import { isVerticalAxis } from '../utils/axis_type_utils'; -import { AxisViewModel, getTitleDimension, shouldShowTicks } from '../utils/axis_utils'; +import { getTitleDimension, shouldShowTicks } from '../utils/axis_utils'; import { AxisSpec } from '../utils/specs'; /** @internal */ export function computeAxesSizes( { axes: sharedAxesStyles, chartMargins }: Theme, - axisDimensions: Map, + axisDimensions: AxesTicksDimensions, axesStyles: Map, axisSpecs: AxisSpec[], smSpec?: SmallMultiplesSpec, diff --git a/packages/charts/src/chart_types/xy_chart/domains/x_domain.ts b/packages/charts/src/chart_types/xy_chart/domains/x_domain.ts index b2ec5405c8..9e0f1589aa 100644 --- a/packages/charts/src/chart_types/xy_chart/domains/x_domain.ts +++ b/packages/charts/src/chart_types/xy_chart/domains/x_domain.ts @@ -40,7 +40,7 @@ export function mergeXDomain( seriesXComputedDomains = computeOrdinalDataDomain(values, identity, false, true); if (customDomain) { if (Array.isArray(customDomain)) { - seriesXComputedDomains = customDomain; + seriesXComputedDomains = [...customDomain]; } else { if (fallbackScale === ScaleType.Ordinal) { Logger.warn(`xDomain ignored for fallback ordinal scale. Options to resolve: @@ -140,7 +140,7 @@ export function findMinInterval(xValues: number[]): number { if (valuesLength === 1) { return 1; } - const sortedValues = xValues.slice().sort(compareByValueAsc); + const sortedValues = [...xValues].sort(compareByValueAsc); let i; let minInterval = Math.abs(sortedValues[1] - sortedValues[0]); for (i = 1; i < valuesLength - 1; i++) { diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx b/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx index 70e8fe7e03..e37e0b60c1 100644 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx +++ b/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx @@ -9,6 +9,7 @@ // eslint-disable-next-line eslint-comments/disable-enable-pair /* eslint-disable jest/no-conditional-expect */ +import 'jest-extended'; import React from 'react'; import { Store } from 'redux'; @@ -1289,7 +1290,7 @@ describe('Clickable annotations', () => { expect(onAnnotationClick).toBeCalled(); const callArgs = onAnnotationClick.mock.calls[0][0]; - expect(callArgs.rects).toEqual([ + expect(callArgs.rects).toIncludeSameMembers([ { id: 'rect2', datum: { diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts index aaae009afc..bed990477a 100644 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts +++ b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts @@ -9,10 +9,10 @@ import { ChartType } from '../..'; import { SpecType } from '../../../specs/constants'; import { Position, RecursivePartial } from '../../../utils/common'; -import { AxisId } from '../../../utils/ids'; import { AxisStyle } from '../../../utils/themes/theme'; import { AxisViewModel, hasDuplicateAxis } from '../utils/axis_utils'; import { AxisSpec } from '../utils/specs'; +import { AxesTicksDimensions } from './selectors/compute_axis_ticks_dimensions'; const style: RecursivePartial = { tickLine: { @@ -49,11 +49,11 @@ describe('isDuplicateAxis', () => { maxLabelTextHeight: 1, isHidden: false, }; - let tickMap: Map; + let tickMap: AxesTicksDimensions; let specMap: AxisSpec[]; beforeEach(() => { - tickMap = new Map(); + tickMap = new Map(); specMap = []; }); diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 1708d5dc9d..53781aa510 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -19,6 +19,9 @@ import { getBarPaddingsSelector } from './get_bar_paddings'; import { getAxisSpecsSelector, getSeriesSpecsSelector } from './get_specs'; import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +/** @internal */ +export type AxesTicksDimensions = Map; + /** @internal */ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( [ @@ -42,34 +45,36 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( totalBarsInCluster, seriesSpecs, axesStyles, - ): Map => { + ): AxesTicksDimensions => { const { xDomain, yDomains } = seriesDomainsAndData; const fallBackTickFormatter = seriesSpecs.find(({ tickFormat }) => tickFormat)?.tickFormat ?? defaultTickFormatter; - return withTextMeasure((textMeasure) => { - const axesTicksDimensions: Map = new Map(); - axesSpecs.forEach((axisSpec) => { - const { id } = axisSpec; - const axisStyle = axesStyles.get(id) ?? chartTheme.axes; - const dimensions = axisViewModel( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - textMeasure, - settingsSpec.rotation, - axisStyle, - fallBackTickFormatter, - barsPadding, - isHistogramMode, - ); - if ( - dimensions && - (!settingsSpec.hideDuplicateAxes || !hasDuplicateAxis(axisSpec, dimensions, axesTicksDimensions, axesSpecs)) - ) { - axesTicksDimensions.set(id, dimensions); - } - }); - return axesTicksDimensions; - }); + return withTextMeasure( + (textMeasure): AxesTicksDimensions => { + const axesTicksDimensions: AxesTicksDimensions = new Map(); + axesSpecs.forEach((axisSpec) => { + const { id } = axisSpec; + const axisStyle = axesStyles.get(id) ?? chartTheme.axes; + const dimensions = axisViewModel( + axisSpec, + xDomain, + yDomains, + totalBarsInCluster, + textMeasure, + settingsSpec.rotation, + axisStyle, + fallBackTickFormatter, + barsPadding, + isHistogramMode, + ); + if ( + dimensions && + (!settingsSpec.hideDuplicateAxes || !hasDuplicateAxis(axisSpec, dimensions, axesTicksDimensions, axesSpecs)) + ) { + axesTicksDimensions.set(id, dimensions); + } + }); + return axesTicksDimensions; + }, + ); }, ); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index d1739e564c..5434abe56f 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -9,6 +9,7 @@ import { DateTime } from 'luxon'; import moment from 'moment-timezone'; +import 'jest-extended'; import { ChartType } from '../..'; import { MockGlobalSpec, MockSeriesSpec } from '../../../mocks/specs/specs'; import { MockStore } from '../../../mocks/store/store'; @@ -20,11 +21,14 @@ import { withTextMeasure } from '../../../utils/bbox/canvas_text_bbox_calculator import { Position, mergePartial } from '../../../utils/common'; import { niceTimeFormatter } from '../../../utils/data/formatters'; import { OrdinalDomain } from '../../../utils/domain'; -import { AxisId, GroupId } from '../../../utils/ids'; +import { GroupId } from '../../../utils/ids'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { AxisStyle, TextOffset } from '../../../utils/themes/theme'; import { computeAxesGeometriesSelector } from '../state/selectors/compute_axes_geometries'; -import { computeAxisTicksDimensionsSelector } from '../state/selectors/compute_axis_ticks_dimensions'; +import { + AxesTicksDimensions, + computeAxisTicksDimensionsSelector, +} from '../state/selectors/compute_axis_ticks_dimensions'; import { getScale, SmallMultipleScales } from '../state/selectors/compute_small_multiple_scales'; import { getAxesStylesSelector } from '../state/selectors/get_axis_styles'; import { computeGridLinesSelector } from '../state/selectors/get_grid_lines'; @@ -1163,7 +1167,7 @@ describe('Axis computational utils', () => { test('should not compute axis ticks positions if missaligned specs', () => { const axisSpecs = [verticalAxisSpec]; const axisStyles = new Map(); - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); axisDims.set('not_a_mapped_one', axis1Dims); const axisTicksPosition = getAxesGeometries( diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index bf0cb27f98..0a2cacf363 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -26,6 +26,7 @@ import { Point } from '../../../utils/point'; import { AxisStyle, TextAlignment, TextOffset, Theme } from '../../../utils/themes/theme'; import { XDomain, YDomain } from '../domains/types'; import { MIN_STROKE_WIDTH } from '../renderer/canvas/primitives/line'; +import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; import { SmallMultipleScales } from '../state/selectors/compute_small_multiple_scales'; import { getSpecsById } from '../state/utils/spec'; import { isHorizontalAxis, isVerticalAxis } from './axis_type_utils'; @@ -654,7 +655,7 @@ export function getAxesGeometries( { chartPaddings, chartMargins, axes: sharedAxesStyle }: Theme, chartRotation: Rotation, axisSpecs: AxisSpec[], - axisDimensions: Map, + axisDimensions: AxesTicksDimensions, axesStyles: Map, xDomain: XDomain, yDomains: YDomain[], @@ -808,7 +809,7 @@ export function getAxesGeometries( export const hasDuplicateAxis = ( { position, title }: AxisSpec, { tickLabels }: AxisViewModel, - tickMap: Map, + tickMap: AxesTicksDimensions, specs: AxisSpec[], ): boolean => [...tickMap].some(([axisId, { tickLabels: axisTickLabels }]) => { diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts index ad7a28ba27..87a7b0d03f 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -13,6 +13,7 @@ import { Margins } from '../../../utils/dimensions'; import { AxisId } from '../../../utils/ids'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { LegendStyle } from '../../../utils/themes/theme'; +import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; import { AxisViewModel } from './axis_utils'; import { computeChartDimensions } from './dimensions'; import { AxisSpec } from './specs'; @@ -79,7 +80,7 @@ describe('Computed chart dimensions', () => { chartTheme.axes.axisTitle.fontSize = 10; chartTheme.axes.axisTitle.padding = 10; test('should be equal to parent dimension with no axis minus margins', () => { - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs: AxisSpec[] = []; const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisStyles, axisSpecs); @@ -90,7 +91,7 @@ describe('Computed chart dimensions', () => { test('should be padded by a left axis', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxWidth|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from left - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs = [axisLeftSpec]; axisDims.set('axis_1', axis1Dims); @@ -102,7 +103,7 @@ describe('Computed chart dimensions', () => { test('should be padded by a right axis', () => { // |padding|tickSize|tickPadding|maxLabelBBoxWidth|titlePadding|titleFontSize\margin| // \10|10|10|10|10|10|10| = 70px from right - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs = [{ ...axisLeftSpec, position: Position.Right }]; axisDims.set('axis_1', axis1Dims); @@ -114,7 +115,7 @@ describe('Computed chart dimensions', () => { test('should be padded by a top axis', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxHeight|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from top - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs = [ { @@ -131,7 +132,7 @@ describe('Computed chart dimensions', () => { test('should be padded by a bottom axis', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxHeight|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from bottom - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs = [ { @@ -146,7 +147,7 @@ describe('Computed chart dimensions', () => { expect(chartDimensions).toMatchSnapshot(); }); test('should not add space for axis when no spec for axis dimensions or axis is hidden', () => { - const axisDims = new Map(); + const axisDims: AxesTicksDimensions = new Map(); const axisStyles = new Map(); const axisSpecs = [ { @@ -169,7 +170,7 @@ describe('Computed chart dimensions', () => { expect(chartDimensions).toEqual(expectedDims); - const hiddenAxisDims = new Map(); + const hiddenAxisDims: AxesTicksDimensions = new Map(); const hiddenAxisSpecs = new Map(); hiddenAxisDims.set('axis_1', axis1Dims); hiddenAxisSpecs.set('axis_1', { diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.ts index 60a321b063..1d1aba593d 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.ts @@ -11,7 +11,7 @@ import { Dimensions } from '../../../utils/dimensions'; import { AxisId } from '../../../utils/ids'; import { Theme, AxisStyle } from '../../../utils/themes/theme'; import { computeAxesSizes } from '../axes/axes_sizes'; -import { AxisViewModel } from './axis_utils'; +import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; import { AxisSpec } from './specs'; /** @@ -36,7 +36,7 @@ export interface ChartDimensions { export function computeChartDimensions( parentDimensions: Dimensions, theme: Theme, - axisDimensions: Map, + axisDimensions: AxesTicksDimensions, axesStyles: Map, axisSpecs: AxisSpec[], smSpec?: SmallMultiplesSpec, diff --git a/packages/charts/src/chart_types/xy_chart/utils/series.ts b/packages/charts/src/chart_types/xy_chart/utils/series.ts index 565a557f2c..a135bb1c41 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/series.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/series.ts @@ -299,7 +299,7 @@ const getSortedDataSeries = ( xValues: Set, xScaleType: ScaleType, ): DataSeries[] => - dataSeries.map(({ data, ...rest }) => ({ + [...dataSeries].map(({ data, ...rest }) => ({ ...rest, data: data.sort(datumXSortPredicate(xScaleType, [...xValues.values()])), })); @@ -490,8 +490,7 @@ function getSeriesNameFromOptions( } return ( - options.names - .slice() + [...options.names] .sort(({ sortIndex: a = BIG_NUMBER }, { sortIndex: b = BIG_NUMBER }) => a - b) .map(({ accessor, value, name }) => { const accessorValue = splitAccessors.get(accessor) ?? null; @@ -570,7 +569,7 @@ export function getSeriesColors( ): Map { const seriesColorMap = new Map(); let counter = 0; - const sortedDataSeries = dataSeries.slice().sort((a, b) => a.insertIndex - b.insertIndex); + const sortedDataSeries = [...dataSeries].sort((a, b) => a.insertIndex - b.insertIndex); groupBy( sortedDataSeries, (ds) => { diff --git a/storybook/stories/axes/12_duplicate_ticks.story.tsx b/storybook/stories/axes/12_duplicate_ticks.story.tsx index 7037657760..a8b0c96ffe 100644 --- a/storybook/stories/axes/12_duplicate_ticks.story.tsx +++ b/storybook/stories/axes/12_duplicate_ticks.story.tsx @@ -8,7 +8,7 @@ import { boolean, select } from '@storybook/addon-knobs'; import { DateTime } from 'luxon'; -import moment from 'moment-timezone'; +import * as moment from 'moment-timezone'; import React from 'react'; import { diff --git a/storybook/stories/axes/13_label_formatting.story.tsx b/storybook/stories/axes/13_label_formatting.story.tsx index 6287d386ac..2b6e4b4a3d 100644 --- a/storybook/stories/axes/13_label_formatting.story.tsx +++ b/storybook/stories/axes/13_label_formatting.story.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { text } from '@storybook/addon-knobs'; +import { boolean, text } from '@storybook/addon-knobs'; import numeral from 'numeral'; import React from 'react'; @@ -30,6 +30,8 @@ export const Example = () => { id="bottom" title="Weight" position={Position.Bottom} + showOverlappingTicks={boolean('showOverlappingTicks bottom axis', false)} + showOverlappingLabels={boolean('showOverlappingLabels bottom axis', false)} tickFormat={(d) => numeral(d).format(tickFormatBottom)} labelFormat={(d) => numeral(d).format(labelFormatBottom)} /> diff --git a/storybook/stories/interactions/11_brush_time.story.tsx b/storybook/stories/interactions/11_brush_time.story.tsx index f7362492aa..b8420606b6 100644 --- a/storybook/stories/interactions/11_brush_time.story.tsx +++ b/storybook/stories/interactions/11_brush_time.story.tsx @@ -9,7 +9,7 @@ import { action } from '@storybook/addon-actions'; import { boolean } from '@storybook/addon-knobs'; import { DateTime } from 'luxon'; -import moment from 'moment-timezone'; +import * as moment from 'moment-timezone'; import React from 'react'; import { From 404d195d33aeb156eeaa98cafbc12fbe0f130c21 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 3 Sep 2021 23:41:03 +0200 Subject: [PATCH 34/75] test: a leftover order lock-in relaxed --- .../charts/src/chart_types/xy_chart/annotations/tooltip.ts | 4 ++-- .../charts/src/chart_types/xy_chart/utils/axis_utils.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts b/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts index fe12033b1e..83c0622b75 100644 --- a/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts +++ b/packages/charts/src/chart_types/xy_chart/annotations/tooltip.ts @@ -24,7 +24,7 @@ export function computeRectAnnotationTooltipState( chartRotation: Rotation, chartDimensions: Dimensions, ): AnnotationTooltipState | null { - // allow picking up the last spec added as the top most or use it's zIndex value + // allow picking up the last spec added as the top most or use its zIndex value const sortedAnnotationSpecs = annotationSpecs .filter(isRectAnnotation) .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => a - b); @@ -68,7 +68,7 @@ export function computeMultipleRectAnnotationTooltipState( chartRotation: Rotation, chartDimensions: Dimensions, ): AnnotationTooltipState[] { - // allow picking up the last spec added as the top most or use it's zIndex value + // allow picking up the last spec added as the top most or use its zIndex value const sortedAnnotationSpecs = annotationSpecs .filter(isRectAnnotation) .sort(({ zIndex: a = Number.MIN_SAFE_INTEGER }, { zIndex: b = Number.MIN_SAFE_INTEGER }) => a - b); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 5434abe56f..a82abe0dbf 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -1646,7 +1646,7 @@ describe('Axis computational utils', () => { const expected = axis1Dims.tickValues.map(customFormatter); const axisPos = axisTicksPosition.find(({ axis: { id } }) => id === verticalAxisSpec.id); - expect(axisPos?.ticks.map(({ label }) => label)).toEqual(expected); + expect(axisPos?.ticks.map(({ label }) => label)).toIncludeSameMembers(expected); }); it('should not use custom formatter with x axis', () => { From 46e98f3a316362cb819cf4f156f6dc8833828b86 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 4 Sep 2021 01:35:53 +0200 Subject: [PATCH 35/75] feat: fully separated general vs axis tick label code --- .../renderer/canvas/axes/tick_label.ts | 4 +- .../xy_chart/utils/axis_utils.test.ts | 284 +++++++++--------- .../chart_types/xy_chart/utils/axis_utils.ts | 14 +- 3 files changed, 155 insertions(+), 147 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts b/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts index 14f165e585..6cf6a8da97 100644 --- a/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts +++ b/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts @@ -16,7 +16,7 @@ export function renderTickLabel( ctx: CanvasRenderingContext2D, tick: AxisTick, showTicks: boolean, - { axisSpec: { position, labelFormat }, dimension, size, debug, axisStyle }: AxisProps, + { axisSpec: { position }, dimension, size, debug, axisStyle }: AxisProps, ) { const labelStyle = axisStyle.tickLabel; const tickLabelProps = getTickLabelProps( @@ -46,7 +46,7 @@ export function renderTickLabel( renderText( ctx, center, - labelFormat ? labelFormat(tick.value) : tick.label, + tick.axisTickLabel, { fontFamily: labelStyle.fontFamily, fontStyle: labelStyle.fontStyle ?? 'normal', diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index a82abe0dbf..41bbd6540e 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -365,17 +365,17 @@ describe('Axis computational utils', () => { const scale = getScaleForAxisSpec(verticalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); const axisPositions = getAvailableTicks(verticalAxisSpec, scale!, 0, false, (v) => `${v}`, 0); const expectedAxisPositions = [ - { label: '0', position: 100, value: 0 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '1', position: 0, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, ]; expect(axisPositions).toEqual(expectedAxisPositions); }); @@ -385,17 +385,17 @@ describe('Axis computational utils', () => { const scale = getScaleForAxisSpec(verticalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); const axisPositions = getAvailableTicks(verticalAxisSpec, scale!, 0, false, (v) => `${v}`, rotationalOffset); const expectedAxisPositions = [ - { label: '0', position: 100 + rotationalOffset, value: 0 }, - { label: '0.1', position: 90 + rotationalOffset, value: 0.1 }, - { label: '0.2', position: 80 + rotationalOffset, value: 0.2 }, - { label: '0.3', position: 70 + rotationalOffset, value: 0.3 }, - { label: '0.4', position: 60 + rotationalOffset, value: 0.4 }, - { label: '0.5', position: 50 + rotationalOffset, value: 0.5 }, - { label: '0.6', position: 40 + rotationalOffset, value: 0.6 }, - { label: '0.7', position: 30 + rotationalOffset, value: 0.7 }, - { label: '0.8', position: 20 + rotationalOffset, value: 0.8 }, - { label: '0.9', position: 10 + rotationalOffset, value: 0.9 }, - { label: '1', position: rotationalOffset, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100 + rotationalOffset, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90 + rotationalOffset, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80 + rotationalOffset, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70 + rotationalOffset, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60 + rotationalOffset, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50 + rotationalOffset, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40 + rotationalOffset, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30 + rotationalOffset, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20 + rotationalOffset, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10 + rotationalOffset, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: rotationalOffset, value: 1 }, ]; expect(axisPositions).toEqual(expectedAxisPositions); }); @@ -481,78 +481,78 @@ describe('Axis computational utils', () => { }); test('should compute visible ticks for a vertical axis', () => { const allTicks = [ - { label: '0', position: 100, value: 0 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '1', position: 0, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, ]; const visibleTicks = getVisibleTicks(allTicks, verticalAxisSpec, axis1Dims); const expectedVisibleTicks = [ - { label: '1', position: 0, value: 1 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0', position: 100, value: 0 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, ]; expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should compute visible ticks for a horizontal axis', () => { const allTicks = [ - { label: '0', position: 100, value: 0 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '1', position: 0, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, ]; const visibleTicks = getVisibleTicks(allTicks, horizontalAxisSpec, axis1Dims); const expectedVisibleTicks = [ - { label: '1', position: 0, value: 1 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0', position: 100, value: 0 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, ]; expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should hide some ticks', () => { const allTicks = [ - { label: '0', position: 100, value: 0 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '1', position: 0, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, ]; const axis2Dims = { axisScaleType: ScaleType.Linear, @@ -567,28 +567,28 @@ describe('Axis computational utils', () => { }; const visibleTicks = getVisibleTicks(allTicks, verticalAxisSpec, axis2Dims); const expectedVisibleTicks = [ - { label: '1', position: 0, value: 1 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0', position: 100, value: 0 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, ]; expect(visibleTicks).toIncludeSameMembers(expectedVisibleTicks); }); test('should show all overlapping ticks and labels if configured to', () => { const allTicks = [ - { label: '0', position: 100, value: 0 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '1', position: 0, value: 1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, ]; const axis2Dims = { axisScaleType: ScaleType.Linear, @@ -606,17 +606,17 @@ describe('Axis computational utils', () => { verticalAxisSpec.showOverlappingLabels = true; const visibleOverlappingTicks = getVisibleTicks(allTicks, verticalAxisSpec, axis2Dims); const expectedVisibleOverlappingTicks = [ - { label: '1', position: 0, value: 1 }, - { label: '0.9', position: 10, value: 0.9 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '0.7', position: 30, value: 0.7 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '0.5', position: 50, value: 0.5 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '0.3', position: 70, value: 0.3 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '0.1', position: 90, value: 0.1 }, - { label: '0', position: 100, value: 0 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, + { label: '0.9', axisTickLabel: '0.9', position: 10, value: 0.9 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.7', axisTickLabel: '0.7', position: 30, value: 0.7 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.5', axisTickLabel: '0.5', position: 50, value: 0.5 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.3', axisTickLabel: '0.3', position: 70, value: 0.3 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.1', axisTickLabel: '0.1', position: 90, value: 0.1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, ]; expect(visibleOverlappingTicks).toIncludeSameMembers(expectedVisibleOverlappingTicks); @@ -624,17 +624,17 @@ describe('Axis computational utils', () => { verticalAxisSpec.showOverlappingLabels = false; const visibleOverlappingTicksAndLabels = getVisibleTicks(allTicks, verticalAxisSpec, axis2Dims); const expectedVisibleOverlappingTicksAndLabels = [ - { label: '1', position: 0, value: 1 }, - { label: '', position: 10, value: 0.9 }, - { label: '0.8', position: 20, value: 0.8 }, - { label: '', position: 30, value: 0.7 }, - { label: '0.6', position: 40, value: 0.6 }, - { label: '', position: 50, value: 0.5 }, - { label: '0.4', position: 60, value: 0.4 }, - { label: '', position: 70, value: 0.3 }, - { label: '0.2', position: 80, value: 0.2 }, - { label: '', position: 90, value: 0.1 }, - { label: '0', position: 100, value: 0 }, + { label: '1', axisTickLabel: '1', position: 0, value: 1 }, + { label: '0.9', axisTickLabel: '', position: 10, value: 0.9 }, + { label: '0.8', axisTickLabel: '0.8', position: 20, value: 0.8 }, + { label: '0.7', axisTickLabel: '', position: 30, value: 0.7 }, + { label: '0.6', axisTickLabel: '0.6', position: 40, value: 0.6 }, + { label: '0.5', axisTickLabel: '', position: 50, value: 0.5 }, + { label: '0.4', axisTickLabel: '0.4', position: 60, value: 0.4 }, + { label: '0.3', axisTickLabel: '', position: 70, value: 0.3 }, + { label: '0.2', axisTickLabel: '0.2', position: 80, value: 0.2 }, + { label: '0.1', axisTickLabel: '', position: 90, value: 0.1 }, + { label: '0', axisTickLabel: '0', position: 100, value: 0 }, ]; expect(visibleOverlappingTicksAndLabels).toIncludeSameMembers(expectedVisibleOverlappingTicksAndLabels); }); @@ -1494,12 +1494,12 @@ describe('Axis computational utils', () => { const offset = 0; const tickFormatOption = { timeZone: 'utc+1' }; expect(enableDuplicatedTicks(axisSpec, scale, offset, (v) => `${v}`, tickFormatOption)).toEqual([ - { value: 1547208000000, label: '2019-01-11', position: 25.145833333333332 }, - { value: 1547251200000, label: '2019-01-12', position: 85.49583333333334 }, - { value: 1547337600000, label: '2019-01-13', position: 206.19583333333333 }, - { value: 1547424000000, label: '2019-01-14', position: 326.8958333333333 }, - { value: 1547510400000, label: '2019-01-15', position: 447.59583333333336 }, - { value: 1547596800000, label: '2019-01-16', position: 568.2958333333333 }, + { value: 1547208000000, label: '2019-01-11', axisTickLabel: '2019-01-11', position: 25.145833333333332 }, + { value: 1547251200000, label: '2019-01-12', axisTickLabel: '2019-01-12', position: 85.49583333333334 }, + { value: 1547337600000, label: '2019-01-13', axisTickLabel: '2019-01-13', position: 206.19583333333333 }, + { value: 1547424000000, label: '2019-01-14', axisTickLabel: '2019-01-14', position: 326.8958333333333 }, + { value: 1547510400000, label: '2019-01-15', axisTickLabel: '2019-01-15', position: 447.59583333333336 }, + { value: 1547596800000, label: '2019-01-16', axisTickLabel: '2019-01-16', position: 568.2958333333333 }, ]); }); test('should show unique consecutive ticks if duplicateTicks is set to false', () => { @@ -1567,16 +1567,16 @@ describe('Axis computational utils', () => { const offset = 0; const tickFormatOption = { timeZone: 'utc+1' }; expect(enableDuplicatedTicks(axisSpec, scale, offset, (v) => `${v}`, tickFormatOption)).toEqual([ - { value: 1547208000000, label: '2019-01-11', position: 25.145833333333332 }, - { value: 1547251200000, label: '2019-01-12', position: 85.49583333333334 }, - { value: 1547294400000, label: '2019-01-12', position: 145.84583333333333 }, - { value: 1547337600000, label: '2019-01-13', position: 206.19583333333333 }, - { value: 1547380800000, label: '2019-01-13', position: 266.54583333333335 }, - { value: 1547424000000, label: '2019-01-14', position: 326.8958333333333 }, - { value: 1547467200000, label: '2019-01-14', position: 387.24583333333334 }, - { value: 1547510400000, label: '2019-01-15', position: 447.59583333333336 }, - { value: 1547553600000, label: '2019-01-15', position: 507.9458333333333 }, - { value: 1547596800000, label: '2019-01-16', position: 568.2958333333333 }, + { value: 1547208000000, label: '2019-01-11', axisTickLabel: '2019-01-11', position: 25.145833333333332 }, + { value: 1547251200000, label: '2019-01-12', axisTickLabel: '2019-01-12', position: 85.49583333333334 }, + { value: 1547294400000, label: '2019-01-12', axisTickLabel: '2019-01-12', position: 145.84583333333333 }, + { value: 1547337600000, label: '2019-01-13', axisTickLabel: '2019-01-13', position: 206.19583333333333 }, + { value: 1547380800000, label: '2019-01-13', axisTickLabel: '2019-01-13', position: 266.54583333333335 }, + { value: 1547424000000, label: '2019-01-14', axisTickLabel: '2019-01-14', position: 326.8958333333333 }, + { value: 1547467200000, label: '2019-01-14', axisTickLabel: '2019-01-14', position: 387.24583333333334 }, + { value: 1547510400000, label: '2019-01-15', axisTickLabel: '2019-01-15', position: 447.59583333333336 }, + { value: 1547553600000, label: '2019-01-15', axisTickLabel: '2019-01-15', position: 507.9458333333333 }, + { value: 1547596800000, label: '2019-01-16', axisTickLabel: '2019-01-16', position: 568.2958333333333 }, ]); }); test('should use custom tick formatter', () => { @@ -1605,16 +1605,16 @@ describe('Axis computational utils', () => { const offset = 0; const tickFormatOption = { timeZone: 'utc+1' }; expect(enableDuplicatedTicks(axisSpec, scale, offset, (v) => `${v}`, tickFormatOption)).toEqual([ - { value: 1547208000000, label: '2019-01-11', position: 25.145833333333332 }, - { value: 1547251200000, label: '2019-01-12', position: 85.49583333333334 }, - { value: 1547294400000, label: '2019-01-12', position: 145.84583333333333 }, - { value: 1547337600000, label: '2019-01-13', position: 206.19583333333333 }, - { value: 1547380800000, label: '2019-01-13', position: 266.54583333333335 }, - { value: 1547424000000, label: '2019-01-14', position: 326.8958333333333 }, - { value: 1547467200000, label: '2019-01-14', position: 387.24583333333334 }, - { value: 1547510400000, label: '2019-01-15', position: 447.59583333333336 }, - { value: 1547553600000, label: '2019-01-15', position: 507.9458333333333 }, - { value: 1547596800000, label: '2019-01-16', position: 568.2958333333333 }, + { value: 1547208000000, label: '2019-01-11', axisTickLabel: '2019-01-11', position: 25.145833333333332 }, + { value: 1547251200000, label: '2019-01-12', axisTickLabel: '2019-01-12', position: 85.49583333333334 }, + { value: 1547294400000, label: '2019-01-12', axisTickLabel: '2019-01-12', position: 145.84583333333333 }, + { value: 1547337600000, label: '2019-01-13', axisTickLabel: '2019-01-13', position: 206.19583333333333 }, + { value: 1547380800000, label: '2019-01-13', axisTickLabel: '2019-01-13', position: 266.54583333333335 }, + { value: 1547424000000, label: '2019-01-14', axisTickLabel: '2019-01-14', position: 326.8958333333333 }, + { value: 1547467200000, label: '2019-01-14', axisTickLabel: '2019-01-14', position: 387.24583333333334 }, + { value: 1547510400000, label: '2019-01-15', axisTickLabel: '2019-01-15', position: 447.59583333333336 }, + { value: 1547553600000, label: '2019-01-15', axisTickLabel: '2019-01-15', position: 507.9458333333333 }, + { value: 1547596800000, label: '2019-01-16', axisTickLabel: '2019-01-16', position: 568.2958333333333 }, ]); }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 0a2cacf363..e7c6f61936 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -40,6 +40,7 @@ type TickValue = number | string; export interface AxisTick { value: TickValue; label: string; + axisTickLabel: string; position: number; } @@ -501,19 +502,24 @@ export function getAvailableTicks( const offset = (enableHistogramMode ? -halfPadding : (scale.bandwidth * shift) / 2) + (scale.isSingleValue() ? 0 : rotationOffset); const tickFormatter = axisSpec.tickFormat ?? fallBackTickFormatter; + const labelFormatter = axisSpec.labelFormat ?? tickFormatter; if (isSingleValueScale && hasAdditionalTicks) { const [firstTickValue] = ticks; + const firstLabel = tickFormatter(firstTickValue, tickFormatOptions); const firstTick = { value: firstTickValue, - label: tickFormatter(firstTickValue, tickFormatOptions), + label: firstLabel, + axisTickLabel: labelFormatter(firstTickValue, tickFormatOptions), position: (scale.scale(firstTickValue) ?? 0) + offset, }; const lastTickValue = firstTickValue + scale.minInterval; + const lastLabel = tickFormatter(lastTickValue, tickFormatOptions); const lastTick = { value: lastTickValue, - label: tickFormatter(lastTickValue, tickFormatOptions), + label: lastLabel, + axisTickLabel: labelFormatter(lastTickValue, tickFormatOptions), position: scale.bandwidth + halfPadding * 2, }; @@ -533,7 +539,9 @@ export function enableDuplicatedTicks( const allTicks: AxisTick[] = scale.ticks().map((tick) => ({ value: tick, // TODO handle empty string tick formatting + // Nick is this ^^^ now handled here? vvv Or you meant sg else? label: (axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), + axisTickLabel: (axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), position: (scale.scale(tick) ?? 0) + offset, })); return axisSpec.showDuplicatedTicks ? allTicks : getUniqueValues(allTicks, 'label', true); @@ -551,7 +559,7 @@ export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDi (prev, tick) => { const tickLabelFits = tick.position >= prev.occupiedSpace + requiredSpace; if (tickLabelFits || showOverlappingTicks) { - prev.visibleTicks.push(tickLabelFits ? tick : { ...tick, label: '' }); + prev.visibleTicks.push(tickLabelFits ? tick : { ...tick, axisTickLabel: '' }); if (tickLabelFits) prev.occupiedSpace = tick.position + requiredSpace; } return prev; From e2f10a785c5ddb5c34f3374f28fa1478533cef44 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 4 Sep 2021 03:18:55 +0200 Subject: [PATCH 36/75] chore: removed unused axis properties --- .../xy_chart/state/chart_state.test.ts | 1 - .../xy_chart/utils/axis_utils.test.ts | 104 ------------------ .../chart_types/xy_chart/utils/axis_utils.ts | 6 +- .../xy_chart/utils/dimensions.test.ts | 1 - 4 files changed, 1 insertion(+), 111 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts index bed990477a..d1288a02fd 100644 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts +++ b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts @@ -41,7 +41,6 @@ describe('isDuplicateAxis', () => { groupId: 'group_2', }; const axisTicksDimensions: AxisViewModel = { - tickValues: [], tickLabels: ['10', '20', '30'], maxLabelBboxWidth: 1, maxLabelBboxHeight: 1, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 41bbd6540e..ca32d4f683 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -49,7 +49,6 @@ import { getVisibleTicks, isYDomain, enableDuplicatedTicks, - defaultTickFormatter, } from './axis_utils'; import { computeXScale } from './scales'; import { AxisSpec, DomainRange, DEFAULT_GLOBAL_ID } from './specs'; @@ -100,7 +99,6 @@ describe('Axis computational utils', () => { left: 0, }; const axis1Dims = { - tickValues: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, @@ -351,7 +349,6 @@ describe('Axis computational utils', () => { maxLabelTextHeight: 100, maxLabelTextWidth: 100, tickLabels: [], - tickValues: [], isHidden: false, }; const offset: TextOffset = { @@ -557,7 +554,6 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickValues: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, @@ -593,7 +589,6 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickValues: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, @@ -1618,105 +1613,6 @@ describe('Axis computational utils', () => { ]); }); - describe('Custom formatting', () => { - it('should get custom labels for y axis', () => { - const customFormatter = (v: any) => `${v} custom`; - const axisSpecs = [verticalAxisSpec]; - const axesStyles = new Map(); - const axisDims = new Map(); - axisDims.set(verticalAxisSpec.id, axis1Dims); - - const axisTicksPosition = getAxesGeometries( - { - chartDimensions: chartDim, - leftMargin: 0, - }, - LIGHT_THEME, - NO_ROTATION, - axisSpecs, - axisDims, - axesStyles, - xDomain, - [yDomain], - emptySmScales, - 1, - false, - customFormatter, - ); - - const expected = axis1Dims.tickValues.map(customFormatter); - const axisPos = axisTicksPosition.find(({ axis: { id } }) => id === verticalAxisSpec.id); - expect(axisPos?.ticks.map(({ label }) => label)).toIncludeSameMembers(expected); - }); - - it('should not use custom formatter with x axis', () => { - const customFotmatter = (v: any) => `${v} custom`; - const axisSpecs = [horizontalAxisSpec]; - const axesStyles = new Map(); - const axisDims = new Map(); - axisDims.set(horizontalAxisSpec.id, axis1Dims); - - const axisTicksPosition = getAxesGeometries( - { - chartDimensions: chartDim, - leftMargin: 0, - }, - LIGHT_THEME, - NO_ROTATION, - axisSpecs, - axisDims, - axesStyles, - xDomain, - [yDomain], - emptySmScales, - 1, - false, - customFotmatter, - ); - - const expected = axis1Dims.tickValues.slice().map(defaultTickFormatter); - expect( - axisTicksPosition.find(({ axis: { id } }) => id === horizontalAxisSpec.id)!.ticks.map(({ label }) => label), - ).toEqual(expected); - }); - - it('should use custom axis tick formatter to get labels for x axis', () => { - const customFotmatter = (v: any) => `${v} custom`; - const customAxisFotmatter = (v: any) => `${v} custom`; - const spec: AxisSpec = { - ...horizontalAxisSpec, - tickFormat: customAxisFotmatter, - }; - const axisSpecs = [spec]; - const axesStyles = new Map(); - const axisDims = new Map(); - axisDims.set(spec.id, axis1Dims); - - const axisTicksPosition = getAxesGeometries( - { - chartDimensions: chartDim, - leftMargin: 0, - }, - LIGHT_THEME, - NO_ROTATION, - axisSpecs, - axisDims, - axesStyles, - xDomain, - [yDomain], - emptySmScales, - 1, - false, - customFotmatter, - ); - - const expected = axis1Dims.tickValues.slice().map(customAxisFotmatter); - expect(axisTicksPosition.find(({ axis: { id } }) => id === spec.id)!.ticks.map(({ label }) => label)).toEqual( - expected, - ); - }); - }); - describe('Small multiples', () => { const axisStyles = axisTitleStyles(10, 8); const cumTopSum = 10; diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index e7c6f61936..531d5227f7 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -46,7 +46,6 @@ export interface AxisTick { /** @internal */ export interface AxisViewModel { - tickValues: TickValue[]; tickLabels: string[]; maxLabelBboxWidth: number; maxLabelBboxHeight: number; @@ -118,9 +117,7 @@ export function axisViewModel( const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; const tickFormatOptions = { timeZone: xDomain.timeZone }; - - const tickValues = scale.ticks(); - const tickLabels = tickValues.map((d) => tickFormat(d, tickFormatOptions)); + const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); let maxLabelBboxWidth = 0; let maxLabelBboxHeight = 0; @@ -143,7 +140,6 @@ export function axisViewModel( maxLabelBboxHeight, maxLabelTextWidth, maxLabelTextHeight, - tickValues, tickLabels, isHidden: axisSpec.hide && gridLineVisible, }; diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts index 87a7b0d03f..faaaed3a6f 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -39,7 +39,6 @@ describe('Computed chart dimensions', () => { }; const axis1Dims: AxisViewModel = { - tickValues: [0, 1], tickLabels: ['first', 'second'], maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, From fdd00d571d2084d18227e90da8b20d4fd61405f4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 4 Sep 2021 04:00:14 +0200 Subject: [PATCH 37/75] refactor: use all ticks for deduplication fingerprinting --- .../xy_chart/state/chart_state.test.ts | 8 ++++---- .../xy_chart/utils/axis_utils.test.ts | 20 +++++++++---------- .../chart_types/xy_chart/utils/axis_utils.ts | 13 +++--------- .../xy_chart/utils/dimensions.test.ts | 2 +- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts index d1288a02fd..ae79678061 100644 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts +++ b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts @@ -41,7 +41,7 @@ describe('isDuplicateAxis', () => { groupId: 'group_2', }; const axisTicksDimensions: AxisViewModel = { - tickLabels: ['10', '20', '30'], + tickLabels: ['10', '20', '30'].join('|'), maxLabelBboxWidth: 1, maxLabelBboxHeight: 1, maxLabelTextWidth: 1, @@ -86,7 +86,7 @@ describe('isDuplicateAxis', () => { it('should return true with single tick', () => { const newAxisTicksDimensions = { ...axisTicksDimensions, - tickLabels: ['10'], + tickLabels: '10', }; tickMap.set(AXIS_2_ID, newAxisTicksDimensions); specMap.push(axis2); @@ -134,7 +134,7 @@ describe('isDuplicateAxis', () => { it('should return false if tickFormat is different', () => { tickMap.set(AXIS_2_ID, { ...axisTicksDimensions, - tickLabels: ['10%', '20%', '30%'], + tickLabels: ['10%', '20%', '30%'].join('|'), }); specMap.push(axis2); @@ -146,7 +146,7 @@ describe('isDuplicateAxis', () => { it('should return false if tick label count is different', () => { tickMap.set(AXIS_2_ID, { ...axisTicksDimensions, - tickLabels: ['10', '20', '25', '30'], + tickLabels: ['10', '20', '25', '30'].join('|'), }); specMap.push(axis2); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index ca32d4f683..e84e548c5a 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -99,7 +99,7 @@ describe('Axis computational utils', () => { left: 0, }; const axis1Dims = { - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], + tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, maxLabelTextWidth: 10, @@ -279,8 +279,8 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels[0]).toBe('11:00:00'); - expect(axisDimensions?.tickLabels[11]).toBe('11:55:00'); + expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('11:00:00|'); + expect(axisDimensions?.tickLabels.slice(-9)).toBe('|11:55:00'); axisDimensions = axisViewModel( xAxisWithTime, @@ -293,8 +293,8 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels[0]).toBe('14:00:00'); - expect(axisDimensions?.tickLabels[11]).toBe('14:55:00'); + expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('14:00:00|'); + expect(axisDimensions?.tickLabels.slice(-9)).toBe('|14:55:00'); axisDimensions = axisViewModel( xAxisWithTime, @@ -307,8 +307,8 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels[0]).toBe('08:00:00'); - expect(axisDimensions?.tickLabels[11]).toBe('08:55:00'); + expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('08:00:00|'); + expect(axisDimensions?.tickLabels.slice(-9)).toBe('|08:55:00'); }); }); @@ -348,7 +348,7 @@ describe('Axis computational utils', () => { maxLabelBboxHeight: 100, maxLabelTextHeight: 100, maxLabelTextWidth: 100, - tickLabels: [], + tickLabels: '', isHidden: false, }; const offset: TextOffset = { @@ -554,7 +554,7 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], + tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, maxLabelTextWidth: 10, @@ -589,7 +589,7 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'], + tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, maxLabelTextWidth: 10, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 531d5227f7..ed1fda8c68 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -46,7 +46,7 @@ export interface AxisTick { /** @internal */ export interface AxisViewModel { - tickLabels: string[]; + tickLabels: string; maxLabelBboxWidth: number; maxLabelBboxHeight: number; maxLabelTextWidth: number; @@ -140,7 +140,7 @@ export function axisViewModel( maxLabelBboxHeight, maxLabelTextWidth, maxLabelTextHeight, - tickLabels, + tickLabels: tickLabels.join('|'), isHidden: axisSpec.hide && gridLineVisible, }; } @@ -818,12 +818,5 @@ export const hasDuplicateAxis = ( ): boolean => [...tickMap].some(([axisId, { tickLabels: axisTickLabels }]) => { const spec = getSpecsById(specs, axisId); - return ( - spec?.position === position && - title === spec.title && - axisTickLabels && - tickLabels.length === axisTickLabels.length && - tickLabels[0] === axisTickLabels[0] && - tickLabels[tickLabels.length - 1] === axisTickLabels[axisTickLabels.length - 1] - ); + return spec?.position === position && title === spec.title && axisTickLabels && tickLabels === axisTickLabels; }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts index faaaed3a6f..74e32649c2 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -39,7 +39,7 @@ describe('Computed chart dimensions', () => { }; const axis1Dims: AxisViewModel = { - tickLabels: ['first', 'second'], + tickLabels: ['first', 'second'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, maxLabelTextWidth: 10, From bdfa38ff5f2543a961b37e2191e308da13da9a80 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 10:21:05 +0200 Subject: [PATCH 38/75] refactor: use a simple reduction --- .../chart_types/xy_chart/utils/axis_utils.ts | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index ed1fda8c68..9c709f3415 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -119,30 +119,20 @@ export function axisViewModel( const tickFormatOptions = { timeZone: xDomain.timeZone }; const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); - let maxLabelBboxWidth = 0; - let maxLabelBboxHeight = 0; - let maxLabelTextWidth = 0; - let maxLabelTextHeight = 0; - - if (tickLabel.visible) { - for (const labelText of tickLabels) { + const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( + (sizes, labelText) => { const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); - maxLabelBboxWidth = Math.max(maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); - maxLabelBboxHeight = Math.max(maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); - maxLabelTextWidth = Math.max(maxLabelTextWidth, Math.ceil(bbox.width)); - maxLabelTextHeight = Math.max(maxLabelTextHeight, Math.ceil(bbox.height)); - } - } + sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); + sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); + sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); + sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); + return sizes; + }, + { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, + ); - return { - maxLabelBboxWidth, - maxLabelBboxHeight, - maxLabelTextWidth, - maxLabelTextHeight, - tickLabels: tickLabels.join('|'), - isHidden: axisSpec.hide && gridLineVisible, - }; + return { ...maxLabelSizes, tickLabels: tickLabels.join('|'), isHidden: axisSpec.hide && gridLineVisible }; } /** @internal */ From a3d11934156773b6f202185eb81d52f823fab285 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 14:10:10 +0200 Subject: [PATCH 39/75] feat: removed the optional and unused axis deduplication --- ...ate-axis-visually-looks-correct-1-snap.png | Bin 17056 -> 0 bytes packages/charts/api/charts.api.md | 3 +- .../state/chart_state.interactions.test.tsx | 1 - .../xy_chart/state/chart_state.test.ts | 164 ------------------ .../compute_axis_ticks_dimensions.ts | 9 +- .../xy_chart/utils/axis_utils.test.ts | 11 +- .../chart_types/xy_chart/utils/axis_utils.ts | 15 +- .../xy_chart/utils/dimensions.test.ts | 1 - .../__snapshots__/chart.test.tsx.snap | 2 +- packages/charts/src/specs/constants.ts | 1 - packages/charts/src/specs/settings.test.tsx | 1 - packages/charts/src/specs/settings.tsx | 16 +- .../scales/5_remove_duplicates.story.tsx | 44 ----- storybook/stories/scales/scales.stories.tsx | 1 - 14 files changed, 13 insertions(+), 256 deletions(-) delete mode 100644 integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-axis-visually-looks-correct-1-snap.png delete mode 100644 packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts delete mode 100644 storybook/stories/scales/5_remove_duplicates.story.tsx diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-axis-visually-looks-correct-1-snap.png deleted file mode 100644 index 52457d8ec5f4f9bf0a4cf674f78fb3460fd213e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17056 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 diff --git a/packages/charts/api/charts.api.md b/packages/charts/api/charts.api.md index 56ebff7924..7d1cd804fa 100644 --- a/packages/charts/api/charts.api.md +++ b/packages/charts/api/charts.api.md @@ -640,7 +640,7 @@ export const DEFAULT_TOOLTIP_SNAP = true; export const DEFAULT_TOOLTIP_TYPE: "vertical"; // @public (undocumented) -export type DefaultSettingsProps = 'id' | 'chartType' | 'specType' | 'rendering' | 'rotation' | 'resizeDebounce' | 'pointerUpdateDebounce' | 'pointerUpdateTrigger' | 'animateData' | 'debug' | 'tooltip' | 'theme' | 'hideDuplicateAxes' | 'brushAxis' | 'minBrushDelta' | 'externalPointerEvents' | 'showLegend' | 'showLegendExtra' | 'legendPosition' | 'legendMaxDepth' | 'ariaUseDefaultSummary' | 'ariaLabelHeadingLevel' | 'ariaTableCaption'; +export type DefaultSettingsProps = 'id' | 'chartType' | 'specType' | 'rendering' | 'rotation' | 'resizeDebounce' | 'pointerUpdateDebounce' | 'pointerUpdateTrigger' | 'animateData' | 'debug' | 'tooltip' | 'theme' | 'brushAxis' | 'minBrushDelta' | 'externalPointerEvents' | 'showLegend' | 'showLegendExtra' | 'legendPosition' | 'legendMaxDepth' | 'ariaUseDefaultSummary' | 'ariaLabelHeadingLevel' | 'ariaTableCaption'; // @public (undocumented) export const DEPTH_KEY = "depth"; @@ -1869,7 +1869,6 @@ export interface SettingsSpec extends Spec, LegendSpec { debugState?: boolean; // @alpha externalPointerEvents: ExternalPointerEventsSettings; - hideDuplicateAxes: boolean; minBrushDelta?: number; noResults?: ComponentType | ReactChild; onAnnotationClick?: AnnotationClickListener; diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx b/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx index e37e0b60c1..f95c895dd6 100644 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx +++ b/packages/charts/src/chart_types/xy_chart/state/chart_state.interactions.test.tsx @@ -80,7 +80,6 @@ const settingSpec = MockGlobalSpec.settings({ tooltip: { type: TooltipType.VerticalCursor, }, - hideDuplicateAxes: false, theme: { chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, chartMargins: { top: 10, left: 10, bottom: 0, right: 0 }, diff --git a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts b/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts deleted file mode 100644 index ae79678061..0000000000 --- a/packages/charts/src/chart_types/xy_chart/state/chart_state.test.ts +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ChartType } from '../..'; -import { SpecType } from '../../../specs/constants'; -import { Position, RecursivePartial } from '../../../utils/common'; -import { AxisStyle } from '../../../utils/themes/theme'; -import { AxisViewModel, hasDuplicateAxis } from '../utils/axis_utils'; -import { AxisSpec } from '../utils/specs'; -import { AxesTicksDimensions } from './selectors/compute_axis_ticks_dimensions'; - -const style: RecursivePartial = { - tickLine: { - size: 30, - padding: 10, - }, -}; -describe('isDuplicateAxis', () => { - const AXIS_1_ID = 'spec_1'; - const AXIS_2_ID = 'spec_1'; - const axis1: AxisSpec = { - chartType: ChartType.XYAxis, - specType: SpecType.Axis, - id: AXIS_1_ID, - groupId: 'group_1', - hide: false, - showOverlappingTicks: false, - showOverlappingLabels: false, - position: Position.Left, - style, - tickFormat: (value: any) => `${value}%`, - }; - const axis2: AxisSpec = { - ...axis1, - id: AXIS_2_ID, - groupId: 'group_2', - }; - const axisTicksDimensions: AxisViewModel = { - tickLabels: ['10', '20', '30'].join('|'), - maxLabelBboxWidth: 1, - maxLabelBboxHeight: 1, - maxLabelTextWidth: 1, - maxLabelTextHeight: 1, - isHidden: false, - }; - let tickMap: AxesTicksDimensions; - let specMap: AxisSpec[]; - - beforeEach(() => { - tickMap = new Map(); - specMap = []; - }); - - it('should return true if axisSpecs and ticks match', () => { - tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.push(axis2); - const result = hasDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); - - expect(result).toBe(true); - }); - - it('should return false if axisSpecs, ticks AND title match', () => { - tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.push({ - ...axis2, - title: 'TESTING', - }); - const result = hasDuplicateAxis( - { - ...axis1, - title: 'TESTING', - }, - axisTicksDimensions, - tickMap, - specMap, - ); - - expect(result).toBe(true); - }); - - it('should return true with single tick', () => { - const newAxisTicksDimensions = { - ...axisTicksDimensions, - tickLabels: '10', - }; - tickMap.set(AXIS_2_ID, newAxisTicksDimensions); - specMap.push(axis2); - - const result = hasDuplicateAxis(axis1, newAxisTicksDimensions, tickMap, specMap); - - expect(result).toBe(true); - }); - - it('should return false if axisSpecs and ticks match but title is different', () => { - tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.push({ - ...axis2, - title: 'TESTING', - }); - const result = hasDuplicateAxis( - { - ...axis1, - title: 'NOT TESTING', - }, - axisTicksDimensions, - tickMap, - specMap, - ); - - expect(result).toBe(false); - }); - - it('should return false if axisSpecs and ticks match but position is different', () => { - tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.push(axis2); - const result = hasDuplicateAxis( - { - ...axis1, - position: Position.Top, - }, - axisTicksDimensions, - tickMap, - specMap, - ); - - expect(result).toBe(false); - }); - - it('should return false if tickFormat is different', () => { - tickMap.set(AXIS_2_ID, { - ...axisTicksDimensions, - tickLabels: ['10%', '20%', '30%'].join('|'), - }); - specMap.push(axis2); - - const result = hasDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); - - expect(result).toBe(false); - }); - - it('should return false if tick label count is different', () => { - tickMap.set(AXIS_2_ID, { - ...axisTicksDimensions, - tickLabels: ['10', '20', '25', '30'].join('|'), - }); - specMap.push(axis2); - - const result = hasDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); - - expect(result).toBe(false); - }); - - it("should return false if can't find spec", () => { - tickMap.set(AXIS_2_ID, axisTicksDimensions); - const result = hasDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); - - expect(result).toBe(false); - }); -}); diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 53781aa510..3a70166cef 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -11,7 +11,7 @@ import { getChartThemeSelector } from '../../../../state/selectors/get_chart_the import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; import { withTextMeasure } from '../../../../utils/bbox/canvas_text_bbox_calculator'; import { AxisId } from '../../../../utils/ids'; -import { axisViewModel, AxisViewModel, hasDuplicateAxis, defaultTickFormatter } from '../../utils/axis_utils'; +import { axisViewModel, AxisViewModel, defaultTickFormatter } from '../../utils/axis_utils'; import { computeSeriesDomainsSelector } from './compute_series_domains'; import { countBarsInClusterSelector } from './count_bars_in_cluster'; import { getAxesStylesSelector } from './get_axis_styles'; @@ -66,12 +66,7 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( barsPadding, isHistogramMode, ); - if ( - dimensions && - (!settingsSpec.hideDuplicateAxes || !hasDuplicateAxis(axisSpec, dimensions, axesTicksDimensions, axesSpecs)) - ) { - axesTicksDimensions.set(id, dimensions); - } + if (dimensions) axesTicksDimensions.set(id, dimensions); }); return axesTicksDimensions; }, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index e84e548c5a..6df48fd468 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -7,6 +7,7 @@ */ import { DateTime } from 'luxon'; +// @ts-ignore import moment from 'moment-timezone'; import 'jest-extended'; @@ -99,7 +100,6 @@ describe('Axis computational utils', () => { left: 0, }; const axis1Dims = { - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, maxLabelTextWidth: 10, @@ -279,8 +279,6 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('11:00:00|'); - expect(axisDimensions?.tickLabels.slice(-9)).toBe('|11:55:00'); axisDimensions = axisViewModel( xAxisWithTime, @@ -293,8 +291,6 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('14:00:00|'); - expect(axisDimensions?.tickLabels.slice(-9)).toBe('|14:55:00'); axisDimensions = axisViewModel( xAxisWithTime, @@ -307,8 +303,6 @@ describe('Axis computational utils', () => { (v) => `${v}`, ); expect(axisDimensions).not.toBeNull(); - expect(axisDimensions?.tickLabels.slice(0, 9)).toBe('08:00:00|'); - expect(axisDimensions?.tickLabels.slice(-9)).toBe('|08:55:00'); }); }); @@ -348,7 +342,6 @@ describe('Axis computational utils', () => { maxLabelBboxHeight: 100, maxLabelTextHeight: 100, maxLabelTextWidth: 100, - tickLabels: '', isHidden: false, }; const offset: TextOffset = { @@ -554,7 +547,6 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, maxLabelTextWidth: 10, @@ -589,7 +581,6 @@ describe('Axis computational utils', () => { const axis2Dims = { axisScaleType: ScaleType.Linear, axisScaleDomain: [0, 1], - tickLabels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 20, maxLabelTextWidth: 10, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 9c709f3415..1e4200d87b 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -46,7 +46,6 @@ export interface AxisTick { /** @internal */ export interface AxisViewModel { - tickLabels: string; maxLabelBboxWidth: number; maxLabelBboxHeight: number; maxLabelTextWidth: number; @@ -132,7 +131,7 @@ export function axisViewModel( { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, ); - return { ...maxLabelSizes, tickLabels: tickLabels.join('|'), isHidden: axisSpec.hide && gridLineVisible }; + return { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }; } /** @internal */ @@ -798,15 +797,3 @@ export function getAxesGeometries( }); return axesGeometries; } - -/** @internal */ -export const hasDuplicateAxis = ( - { position, title }: AxisSpec, - { tickLabels }: AxisViewModel, - tickMap: AxesTicksDimensions, - specs: AxisSpec[], -): boolean => - [...tickMap].some(([axisId, { tickLabels: axisTickLabels }]) => { - const spec = getSpecsById(specs, axisId); - return spec?.position === position && title === spec.title && axisTickLabels && tickLabels === axisTickLabels; - }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts index 74e32649c2..74d83e49af 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -39,7 +39,6 @@ describe('Computed chart dimensions', () => { }; const axis1Dims: AxisViewModel = { - tickLabels: ['first', 'second'].join('|'), maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, maxLabelTextWidth: 10, diff --git a/packages/charts/src/components/__snapshots__/chart.test.tsx.snap b/packages/charts/src/components/__snapshots__/chart.test.tsx.snap index 93ea083865..3b5eee9beb 100644 --- a/packages/charts/src/components/__snapshots__/chart.test.tsx.snap +++ b/packages/charts/src/components/__snapshots__/chart.test.tsx.snap @@ -56,7 +56,7 @@ exports[`Chart should render the legend name test 1`] = ` - + diff --git a/packages/charts/src/specs/constants.ts b/packages/charts/src/specs/constants.ts index 92088df83f..1cedd90613 100644 --- a/packages/charts/src/specs/constants.ts +++ b/packages/charts/src/specs/constants.ts @@ -176,7 +176,6 @@ export const DEFAULT_SETTINGS_SPEC: SettingsSpec = { visible: false, }, }, - hideDuplicateAxes: false, baseTheme: LIGHT_THEME, brushAxis: BrushAxis.X, minBrushDelta: 2, diff --git a/packages/charts/src/specs/settings.test.tsx b/packages/charts/src/specs/settings.test.tsx index 2bf2a7a023..a47ca24b41 100644 --- a/packages/charts/src/specs/settings.test.tsx +++ b/packages/charts/src/specs/settings.test.tsx @@ -175,7 +175,6 @@ describe('Settings spec component', () => { }, legendPosition: Position.Bottom, showLegendExtra: false, - hideDuplicateAxes: false, debug: true, xDomain: { min: 0, max: 10 }, }; diff --git a/packages/charts/src/specs/settings.tsx b/packages/charts/src/specs/settings.tsx index 51040a948a..001d59d4b1 100644 --- a/packages/charts/src/specs/settings.tsx +++ b/packages/charts/src/specs/settings.tsx @@ -49,7 +49,7 @@ import { /** @public */ export interface LayerValue { /** - * The category value as retrieved by the `groupByRollup` callback + * The category value as retrieved by the `groupByRollup` callback§ */ groupByRollup: PrimitiveValue; /** @@ -84,6 +84,7 @@ export interface GroupBrushExtent { groupId: GroupId; extent: [number, number]; } + /** @public */ export interface XYBrushArea { x?: [number, number]; @@ -167,11 +168,13 @@ export type AnnotationClickListener = (annotations: { rects: RectAnnotationEvent[]; lines: LineAnnotationEvent[]; }) => void; + /** @public */ export interface BasePointerEvent { chartId: string; type: PointerEventType; } + /** * Event used to synchronize pointers/mouse positions between Charts. * @@ -187,6 +190,7 @@ export interface PointerOverEvent extends BasePointerEvent, ProjectedValues { */ unit?: string; } + /** @public */ export interface PointerOutEvent extends BasePointerEvent { type: typeof PointerEventType.Out; @@ -338,6 +342,7 @@ export interface LegendActionProps { */ color: string; } + /** * Legend action component used to render actions next to legend items * @@ -370,6 +375,7 @@ export interface LegendColorPickerProps { */ seriesIdentifiers: SeriesIdentifier[]; } + /** @public */ export type LegendColorPicker = ComponentType; @@ -499,13 +505,6 @@ export interface SettingsSpec extends Spec, LegendSpec { * @alpha */ debugState?: boolean; - - /** - * Removes duplicate axes - * - * Compares title, position and first & last tick labels - */ - hideDuplicateAxes: boolean; /** * Attach a listener for click on the projection area. * The listener will be called with the current x value snapped to the closest @@ -684,7 +683,6 @@ export type DefaultSettingsProps = | 'debug' | 'tooltip' | 'theme' - | 'hideDuplicateAxes' | 'brushAxis' | 'minBrushDelta' | 'externalPointerEvents' diff --git a/storybook/stories/scales/5_remove_duplicates.story.tsx b/storybook/stories/scales/5_remove_duplicates.story.tsx deleted file mode 100644 index c4a6e5fd93..0000000000 --- a/storybook/stories/scales/5_remove_duplicates.story.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { boolean } from '@storybook/addon-knobs'; -import React from 'react'; - -import { Axis, Chart, LineSeries, Position, ScaleType, Settings } from '@elastic/charts'; - -import { useBaseTheme } from '../../use_base_theme'; - -export const Example = () => ( - - - - `${d}%`} /> - `${d}%`} /> - `${d}%`} /> - `${d}%`} /> - - -); - -Example.parameters = { - markdown: 'hideDuplicateAxes will remove redundant axes that have the same min and max labels and position', -}; diff --git a/storybook/stories/scales/scales.stories.tsx b/storybook/stories/scales/scales.stories.tsx index b00e900b32..11231b5c5a 100644 --- a/storybook/stories/scales/scales.stories.tsx +++ b/storybook/stories/scales/scales.stories.tsx @@ -14,6 +14,5 @@ export { Example as timezoneConfiguration } from './1_different_timezones.story' export { Example as tooltipInLocalTimezone } from './2_local_tooltip.story'; export { Example as tooltipInUTC } from './3_utc_tooltip.story'; export { Example as specifiedTimezone } from './4_specified_timezone.story'; -export { Example as removeDuplicateAxis } from './5_remove_duplicates.story'; export { Example as xScaleFallback } from './6_x_scale_fallback.story'; export { Example as logScaleOptions } from './7_log_scale_options.story'; From e20c790cf37b234da48bf22a7f5bd871ea7538a4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 14:40:51 +0200 Subject: [PATCH 40/75] refactor: repackage axis view model calcs 1 --- .../compute_axis_ticks_dimensions.ts | 69 +++++++++++++++---- .../chart_types/xy_chart/utils/axis_utils.ts | 4 +- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 3a70166cef..01c341e240 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -11,7 +11,14 @@ import { getChartThemeSelector } from '../../../../state/selectors/get_chart_the import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; import { withTextMeasure } from '../../../../utils/bbox/canvas_text_bbox_calculator'; import { AxisId } from '../../../../utils/ids'; -import { axisViewModel, AxisViewModel, defaultTickFormatter } from '../../utils/axis_utils'; +import { Logger } from '../../../../utils/logger'; +import { isVerticalAxis } from '../../utils/axis_type_utils'; +import { + AxisViewModel, + computeRotatedLabelDimensions, + defaultTickFormatter, + getScaleForAxisSpec, +} from '../../utils/axis_utils'; import { computeSeriesDomainsSelector } from './compute_series_domains'; import { countBarsInClusterSelector } from './count_bars_in_cluster'; import { getAxesStylesSelector } from './get_axis_styles'; @@ -53,19 +60,53 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( const axesTicksDimensions: AxesTicksDimensions = new Map(); axesSpecs.forEach((axisSpec) => { const { id } = axisSpec; - const axisStyle = axesStyles.get(id) ?? chartTheme.axes; - const dimensions = axisViewModel( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - textMeasure, - settingsSpec.rotation, - axisStyle, - fallBackTickFormatter, - barsPadding, - isHistogramMode, - ); + const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; + const chartRotation = settingsSpec.rotation; + const dimensions = (() => { + const gridLineVisible = isVerticalAxis(axisSpec.position) + ? gridLine.vertical.visible + : gridLine.horizontal.visible; + + // don't compute anything on this axis if grid is hidden and axis is hidden + if (axisSpec.hide && !gridLineVisible) { + return null; + } + + const scale = getScaleForAxisSpec( + axisSpec, + xDomain, + yDomains, + totalBarsInCluster, + chartRotation, + [0, 1], + barsPadding, + isHistogramMode, + ); + + if (!scale) { + Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); + return null; + } + + const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; + const tickFormatOptions = { timeZone: xDomain.timeZone }; + const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); + + const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( + (sizes, labelText) => { + const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); + const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); + sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); + sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); + sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); + sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); + return sizes; + }, + { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, + ); + + return { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }; + })(); if (dimensions) axesTicksDimensions.set(id, dimensions); }); return axesTicksDimensions; diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 1e4200d87b..b2e5805cba 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -89,7 +89,7 @@ export function axisViewModel( { gridLine, tickLabel }: AxisStyle, fallBackTickFormatter: TickFormatter, barsPadding?: number, - enableHistogramMode?: boolean, + isHistogramMode?: boolean, ): AxisViewModel | null { const gridLineVisible = isVerticalAxis(axisSpec.position) ? gridLine.vertical.visible : gridLine.horizontal.visible; @@ -106,7 +106,7 @@ export function axisViewModel( chartRotation, [0, 1], barsPadding, - enableHistogramMode, + isHistogramMode, ); if (!scale) { From 277c0938521957180c0bd900cf0e01b53dc5cb98 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 14:45:03 +0200 Subject: [PATCH 41/75] refactor: repackage axis view model calcs 2 --- .../compute_axis_ticks_dimensions.ts | 80 +++++++++---------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 01c341e240..312b45c584 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -48,12 +48,11 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( axesSpecs, chartTheme, settingsSpec, - seriesDomainsAndData, + { xDomain, yDomains }, totalBarsInCluster, seriesSpecs, axesStyles, ): AxesTicksDimensions => { - const { xDomain, yDomains } = seriesDomainsAndData; const fallBackTickFormatter = seriesSpecs.find(({ tickFormat }) => tickFormat)?.tickFormat ?? defaultTickFormatter; return withTextMeasure( (textMeasure): AxesTicksDimensions => { @@ -62,52 +61,49 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( const { id } = axisSpec; const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; const chartRotation = settingsSpec.rotation; - const dimensions = (() => { - const gridLineVisible = isVerticalAxis(axisSpec.position) - ? gridLine.vertical.visible - : gridLine.horizontal.visible; + const gridLineVisible = isVerticalAxis(axisSpec.position) + ? gridLine.vertical.visible + : gridLine.horizontal.visible; - // don't compute anything on this axis if grid is hidden and axis is hidden - if (axisSpec.hide && !gridLineVisible) { - return null; - } + // don't compute anything on this axis if grid is hidden and axis is hidden + if (axisSpec.hide && !gridLineVisible) { + return; + } - const scale = getScaleForAxisSpec( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - chartRotation, - [0, 1], - barsPadding, - isHistogramMode, - ); + const scale = getScaleForAxisSpec( + axisSpec, + xDomain, + yDomains, + totalBarsInCluster, + chartRotation, + [0, 1], + barsPadding, + isHistogramMode, + ); - if (!scale) { - Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); - return null; - } + if (!scale) { + Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); + return; + } - const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; - const tickFormatOptions = { timeZone: xDomain.timeZone }; - const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); + const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; + const tickFormatOptions = { timeZone: xDomain.timeZone }; + const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); - const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( - (sizes, labelText) => { - const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); - const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); - sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); - sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); - sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); - sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); - return sizes; - }, - { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, - ); + const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( + (sizes, labelText) => { + const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); + const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); + sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); + sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); + sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); + sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); + return sizes; + }, + { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, + ); - return { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }; - })(); - if (dimensions) axesTicksDimensions.set(id, dimensions); + axesTicksDimensions.set(id, { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }); }); return axesTicksDimensions; }, From ebca0685802131228b2e2b3b6ae759863879470f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 15:11:27 +0200 Subject: [PATCH 42/75] refactor: repackage axis view model calcs 3 --- .../selectors/compute_axis_ticks_dimensions.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 312b45c584..0d93cf99f8 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -55,19 +55,16 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( ): AxesTicksDimensions => { const fallBackTickFormatter = seriesSpecs.find(({ tickFormat }) => tickFormat)?.tickFormat ?? defaultTickFormatter; return withTextMeasure( - (textMeasure): AxesTicksDimensions => { - const axesTicksDimensions: AxesTicksDimensions = new Map(); - axesSpecs.forEach((axisSpec) => { + (textMeasure): AxesTicksDimensions => + axesSpecs.reduce((axesTicksDimensions, axisSpec) => { const { id } = axisSpec; const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; - const chartRotation = settingsSpec.rotation; const gridLineVisible = isVerticalAxis(axisSpec.position) ? gridLine.vertical.visible : gridLine.horizontal.visible; - // don't compute anything on this axis if grid is hidden and axis is hidden if (axisSpec.hide && !gridLineVisible) { - return; + return axesTicksDimensions; // don't compute anything on this axis if grid is hidden and axis is hidden } const scale = getScaleForAxisSpec( @@ -75,7 +72,7 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( xDomain, yDomains, totalBarsInCluster, - chartRotation, + settingsSpec.rotation, [0, 1], barsPadding, isHistogramMode, @@ -83,7 +80,7 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( if (!scale) { Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); - return; + return axesTicksDimensions; } const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; @@ -104,9 +101,8 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( ); axesTicksDimensions.set(id, { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }); - }); - return axesTicksDimensions; - }, + return axesTicksDimensions; + }, new Map()), ); }, ); From 7790347299d7b83f1dd770aabf4f10731ba9338a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 15:54:15 +0200 Subject: [PATCH 43/75] refactor: repackage axis view model calcs 4 --- .../compute_axis_ticks_dimensions.ts | 74 ++++++++----------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 0d93cf99f8..d0dc62ada6 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -57,50 +57,40 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( return withTextMeasure( (textMeasure): AxesTicksDimensions => axesSpecs.reduce((axesTicksDimensions, axisSpec) => { - const { id } = axisSpec; + const { id, hide, position, labelFormat: axisLabelFormat, tickFormat: axisTickFormat } = axisSpec; const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; - const gridLineVisible = isVerticalAxis(axisSpec.position) - ? gridLine.vertical.visible - : gridLine.horizontal.visible; - - if (axisSpec.hide && !gridLineVisible) { - return axesTicksDimensions; // don't compute anything on this axis if grid is hidden and axis is hidden - } - - const scale = getScaleForAxisSpec( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - settingsSpec.rotation, - [0, 1], - barsPadding, - isHistogramMode, - ); - - if (!scale) { - Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); - return axesTicksDimensions; + const gridLineVisible = isVerticalAxis(position) ? gridLine.vertical.visible : gridLine.horizontal.visible; + if (gridLineVisible || !hide) { + const scale = getScaleForAxisSpec( + axisSpec, + xDomain, + yDomains, + totalBarsInCluster, + settingsSpec.rotation, + [0, 1], + barsPadding, + isHistogramMode, + ); + if (scale) { + const tickFormat = axisLabelFormat ?? axisTickFormat ?? fallBackTickFormatter; + const tickLabels = scale.ticks().map((d) => tickFormat(d, { timeZone: xDomain.timeZone })); + const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( + (sizes, labelText) => { + const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); + const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); + sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); + sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); + sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); + sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); + return sizes; + }, + { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, + ); + axesTicksDimensions.set(id, { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }); + } else { + Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); + } } - - const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; - const tickFormatOptions = { timeZone: xDomain.timeZone }; - const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); - - const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( - (sizes, labelText) => { - const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); - const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); - sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); - sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); - sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); - sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); - return sizes; - }, - { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, - ); - - axesTicksDimensions.set(id, { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }); return axesTicksDimensions; }, new Map()), ); From 82ce347a573b5cb69a2b72d51f48c1b391f9740b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 16:07:05 +0200 Subject: [PATCH 44/75] refactor: lift out scale fun --- .../compute_axis_ticks_dimensions.ts | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index d0dc62ada6..91a180ade5 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -10,15 +10,13 @@ import { createCustomCachedSelector } from '../../../../state/create_selector'; import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; import { withTextMeasure } from '../../../../utils/bbox/canvas_text_bbox_calculator'; +import { Range } from '../../../../utils/domain'; import { AxisId } from '../../../../utils/ids'; import { Logger } from '../../../../utils/logger'; import { isVerticalAxis } from '../../utils/axis_type_utils'; -import { - AxisViewModel, - computeRotatedLabelDimensions, - defaultTickFormatter, - getScaleForAxisSpec, -} from '../../utils/axis_utils'; +import { AxisViewModel, computeRotatedLabelDimensions, defaultTickFormatter, isYDomain } from '../../utils/axis_utils'; +import { computeXScale, computeYScales } from '../../utils/scales'; +import { AxisSpec } from '../../utils/specs'; import { computeSeriesDomainsSelector } from './compute_series_domains'; import { countBarsInClusterSelector } from './count_bars_in_cluster'; import { getAxesStylesSelector } from './get_axis_styles'; @@ -26,6 +24,8 @@ import { getBarPaddingsSelector } from './get_bar_paddings'; import { getAxisSpecsSelector, getSeriesSpecsSelector } from './get_specs'; import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +const RANGE: Range = [0, 1]; + /** @internal */ export type AxesTicksDimensions = Map; @@ -44,16 +44,20 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( ], ( barsPadding, - isHistogramMode, + enableHistogramMode, axesSpecs, chartTheme, - settingsSpec, + { rotation: chartRotation }, { xDomain, yDomains }, totalBarsInCluster, seriesSpecs, axesStyles, ): AxesTicksDimensions => { const fallBackTickFormatter = seriesSpecs.find(({ tickFormat }) => tickFormat)?.tickFormat ?? defaultTickFormatter; + const getScale = ({ groupId, integersOnly, position }: AxisSpec) => + isYDomain(position, chartRotation) + ? computeYScales({ yDomains, range: RANGE, integersOnly }).get(groupId) ?? null + : computeXScale({ xDomain, totalBarsInCluster, range: RANGE, barsPadding, enableHistogramMode, integersOnly }); return withTextMeasure( (textMeasure): AxesTicksDimensions => axesSpecs.reduce((axesTicksDimensions, axisSpec) => { @@ -61,16 +65,7 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; const gridLineVisible = isVerticalAxis(position) ? gridLine.vertical.visible : gridLine.horizontal.visible; if (gridLineVisible || !hide) { - const scale = getScaleForAxisSpec( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - settingsSpec.rotation, - [0, 1], - barsPadding, - isHistogramMode, - ); + const scale = getScale(axisSpec); if (scale) { const tickFormat = axisLabelFormat ?? axisTickFormat ?? fallBackTickFormatter; const tickLabels = scale.ticks().map((d) => tickFormat(d, { timeZone: xDomain.timeZone })); From d788082a91f1a311a94671467d3ab010b46a2148 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 18:32:11 +0200 Subject: [PATCH 45/75] refactor: scale calc is its own node --- .../compute_axis_ticks_dimensions.ts | 50 +++--- .../xy_chart/utils/axis_utils.test.ts | 165 +++++------------- .../chart_types/xy_chart/utils/axis_utils.ts | 114 +++--------- 3 files changed, 86 insertions(+), 243 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index 91a180ade5..b4f5c55f23 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -10,13 +10,15 @@ import { createCustomCachedSelector } from '../../../../state/create_selector'; import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; import { withTextMeasure } from '../../../../utils/bbox/canvas_text_bbox_calculator'; -import { Range } from '../../../../utils/domain'; import { AxisId } from '../../../../utils/ids'; import { Logger } from '../../../../utils/logger'; import { isVerticalAxis } from '../../utils/axis_type_utils'; -import { AxisViewModel, computeRotatedLabelDimensions, defaultTickFormatter, isYDomain } from '../../utils/axis_utils'; -import { computeXScale, computeYScales } from '../../utils/scales'; -import { AxisSpec } from '../../utils/specs'; +import { + AxisViewModel, + computeRotatedLabelDimensions, + defaultTickFormatter, + getScaleForAxisSpec, +} from '../../utils/axis_utils'; import { computeSeriesDomainsSelector } from './compute_series_domains'; import { countBarsInClusterSelector } from './count_bars_in_cluster'; import { getAxesStylesSelector } from './get_axis_styles'; @@ -24,40 +26,32 @@ import { getBarPaddingsSelector } from './get_bar_paddings'; import { getAxisSpecsSelector, getSeriesSpecsSelector } from './get_specs'; import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; -const RANGE: Range = [0, 1]; - /** @internal */ export type AxesTicksDimensions = Map; -/** @internal */ -export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( +const getScaleFunction = createCustomCachedSelector( [ + computeSeriesDomainsSelector, + getSettingsSpecSelector, + countBarsInClusterSelector, getBarPaddingsSelector, isHistogramModeEnabledSelector, + ], + getScaleForAxisSpec, +); + +/** @internal */ +export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( + [ + getScaleFunction, getAxisSpecsSelector, getChartThemeSelector, - getSettingsSpecSelector, - computeSeriesDomainsSelector, - countBarsInClusterSelector, getSeriesSpecsSelector, getAxesStylesSelector, + computeSeriesDomainsSelector, ], - ( - barsPadding, - enableHistogramMode, - axesSpecs, - chartTheme, - { rotation: chartRotation }, - { xDomain, yDomains }, - totalBarsInCluster, - seriesSpecs, - axesStyles, - ): AxesTicksDimensions => { + (getScale, axesSpecs, chartTheme, seriesSpecs, axesStyles, { xDomain: { timeZone } }): AxesTicksDimensions => { const fallBackTickFormatter = seriesSpecs.find(({ tickFormat }) => tickFormat)?.tickFormat ?? defaultTickFormatter; - const getScale = ({ groupId, integersOnly, position }: AxisSpec) => - isYDomain(position, chartRotation) - ? computeYScales({ yDomains, range: RANGE, integersOnly }).get(groupId) ?? null - : computeXScale({ xDomain, totalBarsInCluster, range: RANGE, barsPadding, enableHistogramMode, integersOnly }); return withTextMeasure( (textMeasure): AxesTicksDimensions => axesSpecs.reduce((axesTicksDimensions, axisSpec) => { @@ -65,10 +59,10 @@ export const computeAxisTicksDimensionsSelector = createCustomCachedSelector( const { gridLine, tickLabel } = axesStyles.get(id) ?? chartTheme.axes; const gridLineVisible = isVerticalAxis(position) ? gridLine.vertical.visible : gridLine.horizontal.visible; if (gridLineVisible || !hide) { - const scale = getScale(axisSpec); + const scale = getScale(axisSpec, [0, 1]); if (scale) { const tickFormat = axisLabelFormat ?? axisTickFormat ?? fallBackTickFormatter; - const tickLabels = scale.ticks().map((d) => tickFormat(d, { timeZone: xDomain.timeZone })); + const tickLabels = scale.ticks().map((d) => tickFormat(d, { timeZone })); const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( (sizes, labelText) => { const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 6df48fd468..35dbd1e147 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -18,7 +18,6 @@ import { MockXDomain, MockYDomain } from '../../../mocks/xy/domains'; import { Scale } from '../../../scales'; import { ScaleType } from '../../../scales/constants'; import { SpecType } from '../../../specs/constants'; -import { withTextMeasure } from '../../../utils/bbox/canvas_text_bbox_calculator'; import { Position, mergePartial } from '../../../utils/common'; import { niceTimeFormatter } from '../../../utils/data/formatters'; import { OrdinalDomain } from '../../../utils/domain'; @@ -37,19 +36,18 @@ import { mergeYCustomDomainsByGroupId } from '../state/selectors/merge_y_custom_ import { AxisTick, AxisViewModel, - axisViewModel, computeRotatedLabelDimensions, getAvailableTicks, getAxisPosition, getAxesGeometries, getHorizontalAxisTickLineProps, getMinMaxRange, - getScaleForAxisSpec, getTickLabelProps, getVerticalAxisTickLineProps, getVisibleTicks, isYDomain, enableDuplicatedTicks, + getScaleForAxisSpec, } from './axis_utils'; import { computeXScale } from './scales'; import { AxisSpec, DomainRange, DEFAULT_GLOBAL_ID } from './specs'; @@ -149,22 +147,6 @@ describe('Axis computational utils', () => { showGridLines: true, integersOnly: false, }); - const xAxisWithTime = MockGlobalSpec.axis({ - chartType: ChartType.XYAxis, - specType: SpecType.Axis, - id: 'axis_1', - groupId: 'group_1', - title: 'v axis', - hide: false, - showOverlappingTicks: false, - showOverlappingLabels: false, - position: Position.Bottom, - style, - tickFormat: niceTimeFormatter([1551438000000, 1551441300000]), - showGridLines: true, - integersOnly: false, - }); - const lineSeriesSpec = MockSeriesSpec.line({ id: 'line', groupId: 'group_1', @@ -211,101 +193,6 @@ describe('Axis computational utils', () => { }, }); - const { axes } = LIGHT_THEME; - - test('should compute axis dimensions', () => - withTextMeasure((textMeasure) => { - const axisDimensions = axisViewModel( - verticalAxisSpec, - xDomain, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - ); - expect(axisDimensions).toEqual({ ...axis1Dims, maxLabelBboxWidth: 16, maxLabelTextWidth: 16 }); // textMeasure defaults - - const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: 'foo' }; - const result = axisViewModel( - ungroupedAxisSpec, - xDomain, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - undefined, - false, - ); - - expect(result).toBeNull(); - })); - - test('should not compute axis dimensions when spec is configured to hide', () => - withTextMeasure((textMeasure) => { - verticalAxisSpec.hide = true; - const axisDimensions = axisViewModel( - verticalAxisSpec, - xDomain, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - ); - expect(axisDimensions).toBe(null); - })); - - test('should compute axis dimensions with timeZone', () => { - withTextMeasure((textMeasure) => { - const xDomain = MockXDomain.fromScaleType(ScaleType.Time, { - domain: [1551438000000, 1551441300000], - isBandScale: false, - minInterval: 0, - timeZone: 'utc', - }); - let axisDimensions = axisViewModel( - xAxisWithTime, - xDomain, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - ); - expect(axisDimensions).not.toBeNull(); - - axisDimensions = axisViewModel( - xAxisWithTime, - { ...xDomain, timeZone: 'utc+3' }, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - ); - expect(axisDimensions).not.toBeNull(); - - axisDimensions = axisViewModel( - xAxisWithTime, - { ...xDomain, timeZone: 'utc-3' }, - [yDomain], - 1, - textMeasure, - NO_ROTATION, - axes, - (v) => `${v}`, - ); - expect(axisDimensions).not.toBeNull(); - }); - }); - test('should compute dimensions for the bounding box containing a rotated label', () => { expect(computeRotatedLabelDimensions({ width: 1, height: 2 }, 0)).toEqual({ width: 1, @@ -322,7 +209,11 @@ describe('Axis computational utils', () => { }); test('should generate a valid scale', () => { - const yScale = getScaleForAxisSpec(verticalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); + const yScale = getScaleForAxisSpec( + { xDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 0, + )(verticalAxisSpec, [100, 0]); expect(yScale).toBeDefined(); expect(yScale?.bandwidth).toBe(0); expect(yScale?.domain).toEqual([0, 1]); @@ -330,10 +221,18 @@ describe('Axis computational utils', () => { expect(yScale?.ticks()).toEqual([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]); const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: 'foo' }; - const nullYScale = getScaleForAxisSpec(ungroupedAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); + const nullYScale = getScaleForAxisSpec( + { xDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 0, + )(ungroupedAxisSpec, [100, 0]); expect(nullYScale).toBe(null); - const xScale = getScaleForAxisSpec(horizontalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); + const xScale = getScaleForAxisSpec( + { xDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 0, + )(horizontalAxisSpec, [100, 0]); expect(xScale).toBeDefined(); }); @@ -352,7 +251,11 @@ describe('Axis computational utils', () => { describe('getAvailableTicks', () => { test('should compute to end of domain when histogram mode not enabled', () => { - const scale = getScaleForAxisSpec(verticalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); + const scale = getScaleForAxisSpec( + { xDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 0, + )(verticalAxisSpec, [100, 0]); const axisPositions = getAvailableTicks(verticalAxisSpec, scale!, 0, false, (v) => `${v}`, 0); const expectedAxisPositions = [ { label: '0', axisTickLabel: '0', position: 100, value: 0 }, @@ -372,7 +275,11 @@ describe('Axis computational utils', () => { test('should compute positions with rotational offset', () => { const rotationalOffset = 2; - const scale = getScaleForAxisSpec(verticalAxisSpec, xDomain, [yDomain], 0, 0, [100, 0]); + const scale = getScaleForAxisSpec( + { xDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 0, + )(verticalAxisSpec, [100, 0]); const axisPositions = getAvailableTicks(verticalAxisSpec, scale!, 0, false, (v) => `${v}`, rotationalOffset); const expectedAxisPositions = [ { label: '0', axisTickLabel: '0', position: 100 + rotationalOffset, value: 0 }, @@ -397,7 +304,11 @@ describe('Axis computational utils', () => { isBandScale: true, minInterval: 10, }); - const xScale = getScaleForAxisSpec(horizontalAxisSpec, xBandDomain, [yDomain], 1, 0, [100, 0]); + const xScale = getScaleForAxisSpec( + { xDomain: xBandDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 1, + )(horizontalAxisSpec, [100, 0]); const histogramAxisPositions = getAvailableTicks( horizontalAxisSpec, xScale!, @@ -417,7 +328,11 @@ describe('Axis computational utils', () => { isBandScale: true, minInterval: 90000, }); - const xScale = getScaleForAxisSpec(horizontalAxisSpec, xBandDomain, [yDomain], 1, 0, [100, 0]); + const xScale = getScaleForAxisSpec( + { xDomain: xBandDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 1, + )(horizontalAxisSpec, [100, 0]); const histogramAxisPositions = getAvailableTicks( horizontalAxisSpec, xScale!, @@ -454,7 +369,11 @@ describe('Axis computational utils', () => { isBandScale: true, minInterval: 90000, }); - const xScale = getScaleForAxisSpec(horizontalAxisSpec, xBandDomain, [yDomain], 1, 0, [100, 0]); + const xScale = getScaleForAxisSpec( + { xDomain: xBandDomain, yDomains: [yDomain] }, + { rotation: 0 }, + 1, + )(horizontalAxisSpec, [100, 0]); const histogramAxisPositions = getAvailableTicks( horizontalAxisSpec, xScale!, @@ -981,7 +900,7 @@ describe('Axis computational utils', () => { x: 10, }); expect(verticalAxisSpecWTitleGeoms?.size).toEqual({ - width: 30, + width: 50, height: 100, }); }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index b2e5805cba..9318398129 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -8,7 +8,8 @@ import { Line } from '../../../geoms/types'; import { Scale } from '../../../scales'; -import { BBox, TextMeasure } from '../../../utils/bbox/canvas_text_bbox_calculator'; +import { SettingsSpec } from '../../../specs'; +import { BBox } from '../../../utils/bbox/canvas_text_bbox_calculator'; import { degToRad, getPercentageValue, @@ -21,7 +22,6 @@ import { import { Dimensions, innerPad, Margins, outerPad, Size } from '../../../utils/dimensions'; import { Range } from '../../../utils/domain'; import { AxisId } from '../../../utils/ids'; -import { Logger } from '../../../utils/logger'; import { Point } from '../../../utils/point'; import { AxisStyle, TextAlignment, TextOffset, Theme } from '../../../utils/themes/theme'; import { XDomain, YDomain } from '../domains/types'; @@ -29,6 +29,7 @@ import { MIN_STROKE_WIDTH } from '../renderer/canvas/primitives/line'; import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; import { SmallMultipleScales } from '../state/selectors/compute_small_multiple_scales'; import { getSpecsById } from '../state/utils/spec'; +import { SeriesDomainsAndData } from '../state/utils/types'; import { isHorizontalAxis, isVerticalAxis } from './axis_type_utils'; import { getPanelSize, hasSMDomain } from './panel'; import { computeXScale, computeYScales } from './scales'; @@ -74,66 +75,6 @@ export interface TickLabelProps { /** @internal */ export const defaultTickFormatter = (tick: unknown) => `${tick}`; -/** - * Compute the ticks values and identify max width and height of the labels - * so we can compute the max space occupied by the axis component. - * @internal - */ -export function axisViewModel( - axisSpec: AxisSpec, - xDomain: XDomain, - yDomains: YDomain[], - totalBarsInCluster: number, - textMeasure: TextMeasure, - chartRotation: Rotation, - { gridLine, tickLabel }: AxisStyle, - fallBackTickFormatter: TickFormatter, - barsPadding?: number, - isHistogramMode?: boolean, -): AxisViewModel | null { - const gridLineVisible = isVerticalAxis(axisSpec.position) ? gridLine.vertical.visible : gridLine.horizontal.visible; - - // don't compute anything on this axis if grid is hidden and axis is hidden - if (axisSpec.hide && !gridLineVisible) { - return null; - } - - const scale = getScaleForAxisSpec( - axisSpec, - xDomain, - yDomains, - totalBarsInCluster, - chartRotation, - [0, 1], - barsPadding, - isHistogramMode, - ); - - if (!scale) { - Logger.warn(`Cannot compute scale for axis spec ${axisSpec.id}. Axis will not be displayed.`); - return null; - } - - const tickFormat = axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter; - const tickFormatOptions = { timeZone: xDomain.timeZone }; - const tickLabels = scale.ticks().map((d) => tickFormat(d, tickFormatOptions)); - - const maxLabelSizes = (tickLabel.visible ? tickLabels : []).reduce( - (sizes, labelText) => { - const bbox = textMeasure(labelText, 0, tickLabel.fontSize, tickLabel.fontFamily); - const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabel.rotation); - sizes.maxLabelBboxWidth = Math.max(sizes.maxLabelBboxWidth, Math.ceil(rotatedBbox.width)); - sizes.maxLabelBboxHeight = Math.max(sizes.maxLabelBboxHeight, Math.ceil(rotatedBbox.height)); - sizes.maxLabelTextWidth = Math.max(sizes.maxLabelTextWidth, Math.ceil(bbox.width)); - sizes.maxLabelTextHeight = Math.max(sizes.maxLabelTextHeight, Math.ceil(bbox.height)); - return sizes; - }, - { maxLabelBboxWidth: 0, maxLabelBboxHeight: 0, maxLabelTextWidth: 0, maxLabelTextHeight: 0 }, - ); - - return { ...maxLabelSizes, isHidden: axisSpec.hide && gridLineVisible }; -} - /** @internal */ export function isYDomain(position: Position, chartRotation: Rotation): boolean { return isVerticalAxis(position) === (chartRotation % 180 === 0); @@ -141,18 +82,16 @@ export function isYDomain(position: Position, chartRotation: Rotation): boolean /** @internal */ export function getScaleForAxisSpec( - { groupId, integersOnly, position }: AxisSpec, - xDomain: XDomain, - yDomains: YDomain[], + { xDomain, yDomains }: Pick, + { rotation: chartRotation }: Pick, totalBarsInCluster: number, - chartRotation: Rotation, - range: Range, barsPadding?: number, enableHistogramMode?: boolean, -): Scale | null { - return isYDomain(position, chartRotation) - ? computeYScales({ yDomains, range, integersOnly }).get(groupId) ?? null - : computeXScale({ xDomain, totalBarsInCluster, range, barsPadding, enableHistogramMode, integersOnly }); +) { + return ({ groupId, integersOnly, position }: Pick, range: Range) => + isYDomain(position, chartRotation) + ? computeYScales({ yDomains, range, integersOnly }).get(groupId) ?? null + : computeXScale({ xDomain, totalBarsInCluster, range, barsPadding, enableHistogramMode, integersOnly }); } /** @internal */ @@ -161,18 +100,11 @@ export function computeRotatedLabelDimensions(unrotatedDims: BBox, degreesRotati const radians = degToRad(degreesRotation); const rotatedHeight = Math.abs(width * Math.sin(radians)) + Math.abs(height * Math.cos(radians)); const rotatedWidth = Math.abs(width * Math.cos(radians)) + Math.abs(height * Math.sin(radians)); - - return { - width: rotatedWidth, - height: rotatedHeight, - }; + return { width: rotatedWidth, height: rotatedHeight }; } function getUserTextOffsets(dimensions: AxisViewModel, offset: TextOffset) { - const defaults = { - x: 0, - y: 0, - }; + const defaults = { x: 0, y: 0 }; if (offset.reference === 'global') { return { @@ -722,6 +654,14 @@ export function getAxesGeometries( }, ).pos; + const getScaleFunction = getScaleForAxisSpec( + { xDomain, yDomains }, + { rotation: chartRotation }, + totalGroupsCount, + barsPadding, + enableHistogramMode, + ); + axisDimensions.forEach((axisDim, id) => { const axisSpec = getSpecsById(axisSpecs, id); const anchorPoint = anchorPointByAxisGroups.get(id); @@ -732,18 +672,8 @@ export function getAxesGeometries( } const isVertical = isVerticalAxis(axisSpec.position); - const minMaxRanges = getMinMaxRange(axisSpec.position, chartRotation, panel); - - const scale = getScaleForAxisSpec( - axisSpec, - xDomain, - yDomains, - totalGroupsCount, - chartRotation, - [minMaxRanges.minRange, minMaxRanges.maxRange], - barsPadding, - enableHistogramMode, - ); + const { minRange, maxRange } = getMinMaxRange(axisSpec.position, chartRotation, panel); + const scale = getScaleFunction(axisSpec, [minRange, maxRange]); if (!scale) { throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); From b934e24477ebbc24f3e905d3ed227b719254830b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 23:06:22 +0200 Subject: [PATCH 46/75] refactor: minor if and switch reduction --- .../chart_types/xy_chart/utils/axis_utils.ts | 64 ++++++++----------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 9318398129..b569c6d22e 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -103,26 +103,22 @@ export function computeRotatedLabelDimensions(unrotatedDims: BBox, degreesRotati return { width: rotatedWidth, height: rotatedHeight }; } -function getUserTextOffsets(dimensions: AxisViewModel, offset: TextOffset) { - const defaults = { x: 0, y: 0 }; - - if (offset.reference === 'global') { - return { - local: defaults, - global: { - x: getPercentageValue(offset.x, dimensions.maxLabelBboxWidth, 0), - y: getPercentageValue(offset.y, dimensions.maxLabelBboxHeight, 0), - }, - }; - } - - return { - global: defaults, - local: { - x: getPercentageValue(offset.x, dimensions.maxLabelTextWidth, 0), - y: getPercentageValue(offset.y, dimensions.maxLabelTextHeight, 0), - }, - }; +function getUserTextOffsets(dimensions: AxisViewModel, { x, y, reference }: TextOffset) { + return reference === 'global' + ? { + local: { x: 0, y: 0 }, + global: { + x: getPercentageValue(x, dimensions.maxLabelBboxWidth, 0), + y: getPercentageValue(y, dimensions.maxLabelBboxHeight, 0), + }, + } + : { + local: { + x: getPercentageValue(x, dimensions.maxLabelTextWidth, 0), + y: getPercentageValue(y, dimensions.maxLabelTextHeight, 0), + }, + global: { x: 0, y: 0 }, + }; } function getHorizontalTextOffset( @@ -132,15 +128,11 @@ function getHorizontalTextOffset( typeof HorizontalAlignment.Left | typeof HorizontalAlignment.Center | typeof HorizontalAlignment.Right >, ): number { - switch (alignment) { - case HorizontalAlignment.Left: - return -width / 2; - case HorizontalAlignment.Right: - return width / 2; - case HorizontalAlignment.Center: - default: - return 0; - } + return { + [HorizontalAlignment.Left]: -width / 2, + [HorizontalAlignment.Right]: width / 2, + [HorizontalAlignment.Center]: 0, + }[alignment]; } function getVerticalTextOffset( @@ -150,15 +142,11 @@ function getVerticalTextOffset( typeof VerticalAlignment.Top | typeof VerticalAlignment.Middle | typeof VerticalAlignment.Bottom >, ): number { - switch (alignment) { - case VerticalAlignment.Top: - return -height / 2; - case VerticalAlignment.Bottom: - return height / 2; - case VerticalAlignment.Middle: - default: - return 0; - } + return { + [VerticalAlignment.Top]: -height / 2, + [VerticalAlignment.Bottom]: height / 2, + [VerticalAlignment.Middle]: 0, + }[alignment]; } function getHorizontalAlign( From 8bf0136ff252f08bc05d2e8ab17d7acb7a558960 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 23:11:17 +0200 Subject: [PATCH 47/75] refactor: ternary --- .../chart_types/xy_chart/utils/axis_utils.ts | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index b569c6d22e..37eaed593b 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -257,34 +257,27 @@ export function getTickLabelProps( userOffsets.local.x; const textOffsetY = getVerticalTextOffset(maxLabelTextHeight, verticalAlign) + userOffsets.local.y; - if (isVerticalAxis(position)) { - const x = isLeftAxis ? axisSize.width - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding; - const offsetX = (isLeftAxis ? -1 : 1) * (maxLabelBboxWidth / 2); - - return { - x, - y: tickPosition, - offsetX: offsetX + userOffsets.global.x, - offsetY: userOffsets.global.y, - textOffsetY, - textOffsetX, - horizontalAlign, - verticalAlign, - }; - } - - const offsetY = isAxisTop ? -maxLabelBboxHeight / 2 : maxLabelBboxHeight / 2; - - return { - x: tickPosition, - y: isAxisTop ? axisSize.height - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding, - offsetX: userOffsets.global.x, - offsetY: offsetY + userOffsets.global.y, - textOffsetX, - textOffsetY, - horizontalAlign, - verticalAlign, - }; + return isVerticalAxis(position) + ? { + x: isLeftAxis ? axisSize.width - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding, + y: tickPosition, + offsetX: (isLeftAxis ? -1 : 1) * (maxLabelBboxWidth / 2) + userOffsets.global.x, + offsetY: userOffsets.global.y, + textOffsetY, + textOffsetX, + horizontalAlign, + verticalAlign, + } + : { + x: tickPosition, + y: isAxisTop ? axisSize.height - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding, + offsetX: userOffsets.global.x, + offsetY: (isAxisTop ? -maxLabelBboxHeight / 2 : maxLabelBboxHeight / 2) + userOffsets.global.y, + textOffsetX, + textOffsetY, + horizontalAlign, + verticalAlign, + }; } /** @internal */ @@ -298,7 +291,6 @@ export function getVerticalAxisTickLineProps( const y = tickPosition; const x1 = isLeftAxis ? axisWidth : 0; const x2 = isLeftAxis ? axisWidth - tickSize : tickSize; - return { x1, y1: y, x2, y2: y }; } @@ -313,7 +305,6 @@ export function getHorizontalAxisTickLineProps( const x = tickPosition; const y1 = isTopAxis ? axisHeight - tickSize : 0; const y2 = isTopAxis ? axisHeight : tickSize; - return { x1: x, y1, x2: x, y2 }; } From 7d5ab2829ffa50e86e100b89a36004919cba65a7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 23:17:26 +0200 Subject: [PATCH 48/75] refactor: getMinMaxRange --- .../chart_types/xy_chart/utils/axis_utils.ts | 57 +++---------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 37eaed593b..878be55391 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -313,55 +313,14 @@ export function getMinMaxRange( axisPosition: Position, chartRotation: Rotation, { width, height }: Size, -): { - minRange: number; - maxRange: number; -} { - switch (axisPosition) { - case Position.Bottom: - case Position.Top: - return getBottomTopAxisMinMaxRange(chartRotation, width); - case Position.Left: - case Position.Right: - default: - return getLeftAxisMinMaxRange(chartRotation, height); - } -} - -function getBottomTopAxisMinMaxRange(chartRotation: Rotation, width: number) { - switch (chartRotation) { - case 90: - // dealing with y domain - return { minRange: 0, maxRange: width }; - case -90: - // dealing with y domain - return { minRange: width, maxRange: 0 }; - case 180: - // dealing with x domain - return { minRange: width, maxRange: 0 }; - case 0: - default: - // dealing with x domain - return { minRange: 0, maxRange: width }; - } -} - -function getLeftAxisMinMaxRange(chartRotation: Rotation, height: number) { - switch (chartRotation) { - case 90: - // dealing with x domain - return { minRange: 0, maxRange: height }; - case -90: - // dealing with x domain - return { minRange: height, maxRange: 0 }; - case 180: - // dealing with y domain - return { minRange: 0, maxRange: height }; - case 0: - default: - // dealing with y domain - return { minRange: height, maxRange: 0 }; - } +): { minRange: number; maxRange: number } { + const horizontal = isHorizontalAxis(axisPosition); + const flipped = horizontal + ? chartRotation === -90 || chartRotation === 180 + : chartRotation === 90 || chartRotation === 180; + return horizontal + ? { minRange: flipped ? width : 0, maxRange: flipped ? 0 : width } + : { minRange: flipped ? 0 : height, maxRange: flipped ? height : 0 }; } /** @internal */ From 6fc9bbb4f7d0677fb1636e200374f72a1caa1956 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 23:44:49 +0200 Subject: [PATCH 49/75] refactor: flipped to more sensible order isYDomain to isXDomain --- .../state/selectors/merge_y_custom_domains.ts | 4 ++-- .../chart_types/xy_chart/utils/axis_utils.test.ts | 10 +++++----- .../src/chart_types/xy_chart/utils/axis_utils.ts | 13 ++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts index 939e02dc58..244c65ffb2 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts @@ -9,7 +9,7 @@ import { Rotation } from '../../../../utils/common'; import { GroupId } from '../../../../utils/ids'; import { isBounded, isCompleteBound, isLowerBound, isUpperBound } from '../../utils/axis_type_utils'; -import { isYDomain } from '../../utils/axis_utils'; +import { isXDomain } from '../../utils/axis_utils'; import { AxisSpec, YDomainRange } from '../../utils/specs'; /** @internal */ @@ -26,7 +26,7 @@ export function mergeYCustomDomainsByGroupId( return; } - if (!isYDomain(spec.position, chartRotation)) { + if (isXDomain(spec.position, chartRotation)) { const errorMessage = `[Axis ${id}]: custom domain for xDomain should be defined in Settings`; throw new Error(errorMessage); } diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 35dbd1e147..a7c17e3998 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -45,7 +45,7 @@ import { getTickLabelProps, getVerticalAxisTickLineProps, getVisibleTicks, - isYDomain, + isXDomain, enableDuplicatedTicks, getScaleForAxisSpec, } from './axis_utils'; @@ -1171,16 +1171,16 @@ describe('Axis computational utils', () => { }); test('should determine if axis belongs to yDomain', () => { - const verticalY = isYDomain(Position.Left, 0); + const verticalY = !isXDomain(Position.Left, 0); expect(verticalY).toBe(true); - const verticalX = isYDomain(Position.Left, 90); + const verticalX = !isXDomain(Position.Left, 90); expect(verticalX).toBe(false); - const horizontalX = isYDomain(Position.Top, 0); + const horizontalX = !isXDomain(Position.Top, 0); expect(horizontalX).toBe(false); - const horizontalY = isYDomain(Position.Top, 90); + const horizontalY = !isXDomain(Position.Top, 90); expect(horizontalY).toBe(true); }); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 878be55391..cc802cbdae 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -54,8 +54,7 @@ export interface AxisViewModel { isHidden: boolean; } -/** @internal */ -export interface TickLabelProps { +interface TickLabelProps { x: number; y: number; offsetX: number; @@ -76,8 +75,8 @@ export interface TickLabelProps { export const defaultTickFormatter = (tick: unknown) => `${tick}`; /** @internal */ -export function isYDomain(position: Position, chartRotation: Rotation): boolean { - return isVerticalAxis(position) === (chartRotation % 180 === 0); +export function isXDomain(position: Position, chartRotation: Rotation): boolean { + return isHorizontalAxis(position) === (chartRotation % 180 === 0); } /** @internal */ @@ -89,9 +88,9 @@ export function getScaleForAxisSpec( enableHistogramMode?: boolean, ) { return ({ groupId, integersOnly, position }: Pick, range: Range) => - isYDomain(position, chartRotation) - ? computeYScales({ yDomains, range, integersOnly }).get(groupId) ?? null - : computeXScale({ xDomain, totalBarsInCluster, range, barsPadding, enableHistogramMode, integersOnly }); + isXDomain(position, chartRotation) + ? computeXScale({ xDomain, totalBarsInCluster, range, barsPadding, enableHistogramMode, integersOnly }) + : computeYScales({ yDomains, range, integersOnly }).get(groupId) ?? null; } /** @internal */ From f9af8143103586215f0355fb0d9b5a629f54c8de Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 6 Sep 2021 23:52:39 +0200 Subject: [PATCH 50/75] refactor: rest --- .../src/chart_types/xy_chart/utils/axis_utils.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index cc802cbdae..cd32d9dd91 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -255,27 +255,21 @@ export function getTickLabelProps( (isHorizontalAxis(position) && rotation === 0 ? 0 : getHorizontalTextOffset(maxLabelTextWidth, horizontalAlign)) + userOffsets.local.x; const textOffsetY = getVerticalTextOffset(maxLabelTextHeight, verticalAlign) + userOffsets.local.y; - + const rest = { textOffsetX, textOffsetY, horizontalAlign, verticalAlign }; return isVerticalAxis(position) ? { x: isLeftAxis ? axisSize.width - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding, y: tickPosition, offsetX: (isLeftAxis ? -1 : 1) * (maxLabelBboxWidth / 2) + userOffsets.global.x, offsetY: userOffsets.global.y, - textOffsetY, - textOffsetX, - horizontalAlign, - verticalAlign, + ...rest, } : { x: tickPosition, y: isAxisTop ? axisSize.height - tickDimension - labelInnerPadding : tickDimension + labelInnerPadding, offsetX: userOffsets.global.x, offsetY: (isAxisTop ? -maxLabelBboxHeight / 2 : maxLabelBboxHeight / 2) + userOffsets.global.y, - textOffsetX, - textOffsetY, - horizontalAlign, - verticalAlign, + ...rest, }; } From 1e9432a143e9ef63c76ef86f2a0e51efa0bc6764 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 00:00:30 +0200 Subject: [PATCH 51/75] chore: removed unused getVerticalAxisTickLineProps and getHorizontalAxisTickLineProps --- .../xy_chart/utils/axis_utils.test.ts | 35 ------------------- .../chart_types/xy_chart/utils/axis_utils.ts | 29 --------------- 2 files changed, 64 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index a7c17e3998..d53ed2d754 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -40,10 +40,8 @@ import { getAvailableTicks, getAxisPosition, getAxesGeometries, - getHorizontalAxisTickLineProps, getMinMaxRange, getTickLabelProps, - getVerticalAxisTickLineProps, getVisibleTicks, isXDomain, enableDuplicatedTicks, @@ -803,39 +801,6 @@ describe('Axis computational utils', () => { }); }); - test('should compute axis tick line positions', () => { - const tickPadding = 5; - const tickSize = 10; - const tickPosition = 10; - const axisHeight = 20; - - const leftAxisTickLinePositions = getVerticalAxisTickLineProps(Position.Left, tickPadding, tickSize, tickPosition); - - expect(leftAxisTickLinePositions).toEqual({ x1: 5, y1: 10, x2: -5, y2: 10 }); - - const rightAxisTickLinePositions = getVerticalAxisTickLineProps( - Position.Right, - tickPadding, - tickSize, - tickPosition, - ); - - expect(rightAxisTickLinePositions).toEqual({ x1: 0, y1: 10, x2: 10, y2: 10 }); - - const topAxisTickLinePositions = getHorizontalAxisTickLineProps(Position.Top, axisHeight, tickSize, tickPosition); - - expect(topAxisTickLinePositions).toEqual({ x1: 10, y1: 10, x2: 10, y2: 20 }); - - const bottomAxisTickLinePositions = getHorizontalAxisTickLineProps( - Position.Bottom, - axisHeight, - tickSize, - tickPosition, - ); - - expect(bottomAxisTickLinePositions).toEqual({ x1: 10, y1: 0, x2: 10, y2: 10 }); - }); - test('should compute axis ticks positions with title', () => { // validate assumptions for test expect(verticalAxisSpec.id).toEqual(verticalAxisSpecWTitle.id); diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index cd32d9dd91..44e59cd376 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { Line } from '../../../geoms/types'; import { Scale } from '../../../scales'; import { SettingsSpec } from '../../../specs'; import { BBox } from '../../../utils/bbox/canvas_text_bbox_calculator'; @@ -273,34 +272,6 @@ export function getTickLabelProps( }; } -/** @internal */ -export function getVerticalAxisTickLineProps( - position: Position, - axisWidth: number, - tickSize: number, - tickPosition: number, -): Line { - const isLeftAxis = position === Position.Left; - const y = tickPosition; - const x1 = isLeftAxis ? axisWidth : 0; - const x2 = isLeftAxis ? axisWidth - tickSize : tickSize; - return { x1, y1: y, x2, y2: y }; -} - -/** @internal */ -export function getHorizontalAxisTickLineProps( - position: Position, - axisHeight: number, - tickSize: number, - tickPosition: number, -): Line { - const isTopAxis = position === Position.Top; - const x = tickPosition; - const y1 = isTopAxis ? axisHeight - tickSize : 0; - const y2 = isTopAxis ? axisHeight : tickSize; - return { x1: x, y1, x2: x, y2 }; -} - /** @internal */ export function getMinMaxRange( axisPosition: Position, From b3fe50036aac675d579bdf1fc9695ce80668696e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 00:02:44 +0200 Subject: [PATCH 52/75] chore: unexported single-use utility function axisExtent --- .../xy_chart/utils/axis_utils.test.ts | 50 ------------------- .../chart_types/xy_chart/utils/axis_utils.ts | 5 +- 2 files changed, 2 insertions(+), 53 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index d53ed2d754..cbeb4fc6a3 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -40,7 +40,6 @@ import { getAvailableTicks, getAxisPosition, getAxesGeometries, - getMinMaxRange, getTickLabelProps, getVisibleTicks, isXDomain, @@ -541,55 +540,6 @@ describe('Axis computational utils', () => { ]; expect(visibleOverlappingTicksAndLabels).toIncludeSameMembers(expectedVisibleOverlappingTicksAndLabels); }); - test('should compute min max range for on 0 deg bottom', () => { - const minMax = getMinMaxRange(Position.Bottom, 0, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 0, maxRange: 100 }); - }); - test('should compute min max range for on 90 deg bottom', () => { - const minMax = getMinMaxRange(Position.Bottom, 90, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 0, maxRange: 100 }); - }); - test('should compute min max range for on 180 deg bottom', () => { - const minMax = getMinMaxRange(Position.Bottom, 180, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 100, maxRange: 0 }); - }); - test('should compute min max range for on -90 deg bottom', () => { - const minMax = getMinMaxRange(Position.Bottom, -90, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 100, maxRange: 0 }); - }); - test('should compute min max range for on 90 deg Left', () => { - const minMax = getMinMaxRange(Position.Left, 90, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 0, maxRange: 50 }); - }); - test('should compute min max range for on 180 deg Left', () => { - const minMax = getMinMaxRange(Position.Left, 180, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 0, maxRange: 50 }); - }); - test('should compute min max range for on -90 deg Right', () => { - const minMax = getMinMaxRange(Position.Right, -90, { - width: 100, - height: 50, - }); - expect(minMax).toEqual({ minRange: 50, maxRange: 0 }); - }); test('should compute positions and alignment of tick labels along a vertical axis', () => { const tickPosition = 0; diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 44e59cd376..bc6c8ee5bf 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -272,8 +272,7 @@ export function getTickLabelProps( }; } -/** @internal */ -export function getMinMaxRange( +function axisExtent( axisPosition: Position, chartRotation: Rotation, { width, height }: Size, @@ -574,7 +573,7 @@ export function getAxesGeometries( } const isVertical = isVerticalAxis(axisSpec.position); - const { minRange, maxRange } = getMinMaxRange(axisSpec.position, chartRotation, panel); + const { minRange, maxRange } = axisExtent(axisSpec.position, chartRotation, panel); const scale = getScaleFunction(axisSpec, [minRange, maxRange]); if (!scale) { From fb012bc0639d3fefbc7a0f992bf58b00fe3d0e94 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 07:49:06 +0200 Subject: [PATCH 53/75] refactor: getVerticalAlign --- .../chart_types/xy_chart/utils/axis_utils.ts | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index bc6c8ee5bf..c88efe575f 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -202,27 +202,20 @@ function getVerticalAlign( } if ([0, 180].includes(rotation)) { - if (position === Position.Bottom || position === Position.Top) { - return VerticalAlignment.Middle; - } - if (position === Position.Left) { return rotation === 0 ? VerticalAlignment.Bottom : VerticalAlignment.Top; + } else if (position === Position.Right) { + return rotation === 180 ? VerticalAlignment.Bottom : VerticalAlignment.Top; + } + } else { + if (position === Position.Top) { + return alignment === VerticalAlignment.Near ? VerticalAlignment.Bottom : VerticalAlignment.Top; + } else if (position === Position.Bottom) { + return alignment === VerticalAlignment.Near ? VerticalAlignment.Top : VerticalAlignment.Bottom; } - - return rotation === 180 ? VerticalAlignment.Bottom : VerticalAlignment.Top; - } - - if (position === Position.Top) { - return alignment === VerticalAlignment.Near ? VerticalAlignment.Bottom : VerticalAlignment.Top; - } - - if (position === Position.Bottom) { - return alignment === VerticalAlignment.Near ? VerticalAlignment.Top : VerticalAlignment.Bottom; } - // fallback for near/far on left/right axis - return VerticalAlignment.Middle; + return VerticalAlignment.Middle; // fallback for near/far on left/right axis } /** From a5587d140315a11072f76d137a4267b79beb7a3c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 08:20:07 +0200 Subject: [PATCH 54/75] refactor: getHorizontalAlign --- .../chart_types/xy_chart/utils/axis_utils.ts | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index c88efe575f..b68ed3a08d 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -161,31 +161,20 @@ function getHorizontalAlign( } if ([-90, 90].includes(rotation)) { - if (position === Position.Left || position === Position.Right) { - return HorizontalAlignment.Center; - } - if (position === Position.Top) { return rotation === 90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; + } else if (position === Position.Bottom) { + return rotation === -90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; + } + } else { + if (position === Position.Left) { + return alignment === HorizontalAlignment.Near ? HorizontalAlignment.Right : HorizontalAlignment.Left; + } else if (position === Position.Right) { + return alignment === HorizontalAlignment.Near ? HorizontalAlignment.Left : HorizontalAlignment.Right; } - - return rotation === -90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; - } - - if ([0, 180].includes(rotation) && (position === Position.Bottom || position === Position.Top)) { - return HorizontalAlignment.Center; - } - - if (position === Position.Left) { - return alignment === HorizontalAlignment.Near ? HorizontalAlignment.Right : HorizontalAlignment.Left; - } - - if (position === Position.Right) { - return alignment === HorizontalAlignment.Near ? HorizontalAlignment.Left : HorizontalAlignment.Right; } - // fallback for near/far on top/bottom axis - return HorizontalAlignment.Center; + return HorizontalAlignment.Center; // fallback for near/far on top/bottom axis } function getVerticalAlign( From 937c2d340a8640d61e2308e8b2c73f305f6a8012 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 08:24:35 +0200 Subject: [PATCH 55/75] refactor: align checks --- packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index b68ed3a08d..bb59391df8 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -160,7 +160,7 @@ function getHorizontalAlign( return alignment; } - if ([-90, 90].includes(rotation)) { + if (Math.abs(rotation) === 90) { if (position === Position.Top) { return rotation === 90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; } else if (position === Position.Bottom) { @@ -190,7 +190,7 @@ function getVerticalAlign( return alignment; } - if ([0, 180].includes(rotation)) { + if (rotation % 180 === 0) { if (position === Position.Left) { return rotation === 0 ? VerticalAlignment.Bottom : VerticalAlignment.Top; } else if (position === Position.Right) { From c7e73bfd3622b8f62cd2a0ad35a37d986a207b16 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 08:54:24 +0200 Subject: [PATCH 56/75] refactor: extract out multiplier --- .../chart_types/xy_chart/utils/axis_utils.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index bb59391df8..c02123e8c6 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -119,6 +119,18 @@ function getUserTextOffsets(dimensions: AxisViewModel, { x, y, reference }: Text }; } +const horizontalOffsetMultiplier = { + [HorizontalAlignment.Left]: -1, + [HorizontalAlignment.Right]: 1, + [HorizontalAlignment.Center]: 0, +}; + +const verticalOffsetMultiplier = { + [VerticalAlignment.Top]: -1, + [VerticalAlignment.Bottom]: 1, + [VerticalAlignment.Middle]: 0, +}; + function getHorizontalTextOffset( width: number, alignment: Extract< @@ -126,25 +138,14 @@ function getHorizontalTextOffset( typeof HorizontalAlignment.Left | typeof HorizontalAlignment.Center | typeof HorizontalAlignment.Right >, ): number { - return { - [HorizontalAlignment.Left]: -width / 2, - [HorizontalAlignment.Right]: width / 2, - [HorizontalAlignment.Center]: 0, - }[alignment]; + return (width / 2) * horizontalOffsetMultiplier[alignment]; } function getVerticalTextOffset( height: number, - alignment: Extract< - VerticalAlignment, - typeof VerticalAlignment.Top | typeof VerticalAlignment.Middle | typeof VerticalAlignment.Bottom - >, + alignment: typeof VerticalAlignment.Top | typeof VerticalAlignment.Middle | typeof VerticalAlignment.Bottom, ): number { - return { - [VerticalAlignment.Top]: -height / 2, - [VerticalAlignment.Bottom]: height / 2, - [VerticalAlignment.Middle]: 0, - }[alignment]; + return (height / 2) * verticalOffsetMultiplier[alignment]; } function getHorizontalAlign( From 469ca41c8060349d062ff5265fed627e4f3358ac Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 09:00:53 +0200 Subject: [PATCH 57/75] refactor: discontinue high noise ratio too simple function --- .../chart_types/xy_chart/utils/axis_utils.ts | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index c02123e8c6..80ed70864c 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -131,23 +131,6 @@ const verticalOffsetMultiplier = { [VerticalAlignment.Middle]: 0, }; -function getHorizontalTextOffset( - width: number, - alignment: Extract< - HorizontalAlignment, - typeof HorizontalAlignment.Left | typeof HorizontalAlignment.Center | typeof HorizontalAlignment.Right - >, -): number { - return (width / 2) * horizontalOffsetMultiplier[alignment]; -} - -function getVerticalTextOffset( - height: number, - alignment: typeof VerticalAlignment.Top | typeof VerticalAlignment.Middle | typeof VerticalAlignment.Bottom, -): number { - return (height / 2) * verticalOffsetMultiplier[alignment]; -} - function getHorizontalAlign( position: Position, rotation: number, @@ -232,11 +215,11 @@ export function getTickLabelProps( const verticalAlign = getVerticalAlign(position, rotation, textAlignment?.vertical); const userOffsets = getUserTextOffsets(tickDimensions, textOffset); - // getHorizontalTextOffset needs to be used for vertical axis labels, and vertical labels of horizontal axes const textOffsetX = - (isHorizontalAxis(position) && rotation === 0 ? 0 : getHorizontalTextOffset(maxLabelTextWidth, horizontalAlign)) + - userOffsets.local.x; - const textOffsetY = getVerticalTextOffset(maxLabelTextHeight, verticalAlign) + userOffsets.local.y; + (isHorizontalAxis(position) && rotation === 0 + ? 0 + : (maxLabelTextWidth / 2) * horizontalOffsetMultiplier[horizontalAlign]) + userOffsets.local.x; + const textOffsetY = (maxLabelTextHeight / 2) * verticalOffsetMultiplier[verticalAlign] + userOffsets.local.y; const rest = { textOffsetX, textOffsetY, horizontalAlign, verticalAlign }; return isVerticalAxis(position) ? { @@ -297,7 +280,6 @@ export function getAvailableTicks( } } const shift = totalBarsInCluster > 0 ? totalBarsInCluster : 1; - const band = scale.bandwidth / (1 - scale.barsPadding); const halfPadding = (band - scale.bandwidth) / 2; const offset = @@ -340,7 +322,6 @@ export function enableDuplicatedTicks( const allTicks: AxisTick[] = scale.ticks().map((tick) => ({ value: tick, // TODO handle empty string tick formatting - // Nick is this ^^^ now handled here? vvv Or you meant sg else? label: (axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), axisTickLabel: (axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), position: (scale.scale(tick) ?? 0) + offset, From 9a0b49a34bed1bfb2cd2bd80d07e0bc6f997f601 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 09:18:03 +0200 Subject: [PATCH 58/75] refactor: removed costly includes checks for equality --- .../chart_types/xy_chart/utils/axis_utils.ts | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 80ed70864c..3f34bcc56b 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -18,7 +18,7 @@ import { Rotation, VerticalAlignment, } from '../../../utils/common'; -import { Dimensions, innerPad, Margins, outerPad, Size } from '../../../utils/dimensions'; +import { Dimensions, innerPad, Margins, outerPad, PerSideDistance, Size } from '../../../utils/dimensions'; import { Range } from '../../../utils/domain'; import { AxisId } from '../../../utils/ids'; import { Point } from '../../../utils/point'; @@ -488,12 +488,7 @@ export function getAxesGeometries( ); acc.pos.set(axisId, { - anchor: { - top: acc.top, - left: acc.left, - right: acc.right, - bottom: acc.bottom, - }, + anchor: { top: acc.top, left: acc.left, right: acc.right, bottom: acc.bottom }, dimensions, }); return { @@ -509,13 +504,7 @@ export function getAxesGeometries( bottom: chartPaddings.bottom, left: computedChartDims.leftMargin, right: chartPaddings.right, - pos: new Map< - AxisId, - { - anchor: { left: number; right: number; top: number; bottom: number }; - dimensions: Dimensions; - } - >(), + pos: new Map(), }, ).pos; @@ -543,14 +532,9 @@ export function getAxesGeometries( if (!scale) { throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); } - const tickFormatOptions = { - timeZone: xDomain.timeZone, - }; - // TODO: Find the true cause of the this offset error const rotationOffset = - enableHistogramMode && - ((isVertical && [-90].includes(chartRotation)) || (!isVertical && [180].includes(chartRotation))) + enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) ? scale.step : 0; @@ -561,7 +545,7 @@ export function getAxesGeometries( enableHistogramMode, isVertical ? fallBackTickFormatter : defaultTickFormatter, rotationOffset, - tickFormatOptions, + { timeZone: xDomain.timeZone }, ); const visibleTicks = getVisibleTicks(allTicks, axisSpec, axisDim); @@ -572,19 +556,10 @@ export function getAxesGeometries( height: isVertical ? panel.height : anchorPoint.dimensions.height, }; axesGeometries.push({ - axis: { - id: axisSpec.id, - position: axisSpec.position, - }, - anchorPoint: { - x: anchorPoint.dimensions.left, - y: anchorPoint.dimensions.top, - }, + axis: { id: axisSpec.id, position: axisSpec.position }, + anchorPoint: { x: anchorPoint.dimensions.left, y: anchorPoint.dimensions.top }, size, - parentSize: { - height: anchorPoint.dimensions.height, - width: anchorPoint.dimensions.width, - }, + parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, dimension: axisDim, ticks: allTicks, visibleTicks, From a60787285cec52cb0b41e703e0402c7f8c999bec Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 09:32:31 +0200 Subject: [PATCH 59/75] refactor: shorter param list for getAxisPosition --- .../xy_chart/utils/axis_utils.test.ts | 41 ++++--------------- .../chart_types/xy_chart/utils/axis_utils.ts | 20 +++------ 2 files changed, 14 insertions(+), 47 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index cbeb4fc6a3..682fa74cca 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -835,15 +835,11 @@ describe('Axis computational utils', () => { verticalAxisSpec, axis1Dims, emptySmScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, ); - const expectedLeftAxisPosition = { dimensions: { height: 100, @@ -876,10 +872,7 @@ describe('Axis computational utils', () => { verticalAxisSpec, axis1Dims, emptySmScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -917,10 +910,7 @@ describe('Axis computational utils', () => { horizontalAxisSpec, axis1Dims, emptySmScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -959,10 +949,7 @@ describe('Axis computational utils', () => { horizontalAxisSpec, axis1Dims, emptySmScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -1456,10 +1443,7 @@ describe('Axis computational utils', () => { { ...verticalAxisSpec, title }, axis1Dims, smScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -1491,10 +1475,7 @@ describe('Axis computational utils', () => { { ...verticalAxisSpec, title }, axis1Dims, smScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -1526,10 +1507,7 @@ describe('Axis computational utils', () => { { ...horizontalAxisSpec, title }, axis1Dims, smScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, @@ -1561,10 +1539,7 @@ describe('Axis computational utils', () => { { ...horizontalAxisSpec, title }, axis1Dims, smScales, - cumTopSum, - cumBottomSum, - cumLeftSum, - cumRightSum, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, 10, 0, true, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 3f34bcc56b..5ff918972c 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -366,21 +366,16 @@ export function getAxisPosition( axisTitle: AxisStyle['axisTitle'], axisPanelTitle: AxisStyle['axisPanelTitle'], axisSpec: AxisSpec, - axisDim: AxisViewModel, + { maxLabelBboxHeight, maxLabelBboxWidth }: AxisViewModel, smScales: SmallMultipleScales, - cumTopSum: number, - cumBottomSum: number, - cumLeftSum: number, - cumRightSum: number, + { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }: PerSideDistance, tickDimension: number, labelPaddingSum: number, showLabels: boolean, ) { const titleDimension = axisSpec.title ? getTitleDimension(axisTitle) : 0; const { position } = axisSpec; - const { maxLabelBboxHeight, maxLabelBboxWidth } = axisDim; - const { top, left, height, width } = chartDimensions; - const dimensions = { top, left, width, height }; + const dimensions = { ...chartDimensions }; let topIncrement = 0; let bottomIncrement = 0; let leftIncrement = 0; @@ -395,7 +390,7 @@ export function getAxisPosition( dimensions.left = cumLeftSum + chartMargins.left; } else { rightIncrement = dimWidth + chartMargins.right; - dimensions.left = left + width + cumRightSum; + dimensions.left = chartDimensions.left + chartDimensions.width + cumRightSum; } dimensions.width = dimWidth; } else { @@ -407,7 +402,7 @@ export function getAxisPosition( dimensions.top = cumTopSum + chartMargins.top; } else { bottomIncrement = dimHeight + chartMargins.bottom; - dimensions.top = top + height + cumBottomSum; + dimensions.top = chartDimensions.top + chartDimensions.height + cumBottomSum; } dimensions.height = dimHeight; } @@ -478,10 +473,7 @@ export function getAxesGeometries( axisSpec, dimension, smScales, - acc.top, - acc.bottom, - acc.left, - acc.right, + acc, tickDimension, labelPaddingSum, tickLabel.visible, From 8c67f512e87366799988173bdaa75c0b9d14a963 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 11:34:56 +0200 Subject: [PATCH 60/75] refactor: hoist common constants --- .../chart_types/xy_chart/utils/axis_utils.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 5ff918972c..b1c24cae0d 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -381,30 +381,29 @@ export function getAxisPosition( let leftIncrement = 0; let rightIncrement = 0; - if (isVerticalAxis(position)) { - const panelTitleDimension = hasSMDomain(smScales.vertical) ? getTitleDimension(axisPanelTitle) : 0; - const dimWidth = - labelPaddingSum + (showLabels ? maxLabelBboxWidth : 0) + tickDimension + titleDimension + panelTitleDimension; + const vertical = isVerticalAxis(position); + const scaleBand = vertical ? smScales.vertical : smScales.horizontal; + const panelTitleDimension = hasSMDomain(scaleBand) ? getTitleDimension(axisPanelTitle) : 0; + const shownLabelSize = showLabels ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; + const parallelSize = labelPaddingSum + shownLabelSize + tickDimension + titleDimension + panelTitleDimension; + if (vertical) { if (position === Position.Left) { - leftIncrement = chartMargins.left + dimWidth; + leftIncrement = chartMargins.left + parallelSize; dimensions.left = cumLeftSum + chartMargins.left; } else { - rightIncrement = dimWidth + chartMargins.right; + rightIncrement = parallelSize + chartMargins.right; dimensions.left = chartDimensions.left + chartDimensions.width + cumRightSum; } - dimensions.width = dimWidth; + dimensions.width = parallelSize; } else { - const panelTitleDimension = hasSMDomain(smScales.horizontal) ? getTitleDimension(axisPanelTitle) : 0; - const dimHeight = - labelPaddingSum + (showLabels ? maxLabelBboxHeight : 0) + tickDimension + titleDimension + panelTitleDimension; if (position === Position.Top) { - topIncrement = dimHeight + chartMargins.top; + topIncrement = parallelSize + chartMargins.top; dimensions.top = cumTopSum + chartMargins.top; } else { - bottomIncrement = dimHeight + chartMargins.bottom; + bottomIncrement = parallelSize + chartMargins.bottom; dimensions.top = chartDimensions.top + chartDimensions.height + cumBottomSum; } - dimensions.height = dimHeight; + dimensions.height = parallelSize; } return { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement }; From b547899fa702339f9a53f98a2d4c8819dbb5b129 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 12:16:41 +0200 Subject: [PATCH 61/75] refactor: getAxisPosition is now a well shaped function --- .../chart_types/xy_chart/utils/axis_utils.ts | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index b1c24cae0d..4a2ffb977f 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -365,7 +365,7 @@ export function getAxisPosition( chartMargins: Margins, axisTitle: AxisStyle['axisTitle'], axisPanelTitle: AxisStyle['axisPanelTitle'], - axisSpec: AxisSpec, + { title, position }: AxisSpec, { maxLabelBboxHeight, maxLabelBboxWidth }: AxisViewModel, smScales: SmallMultipleScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }: PerSideDistance, @@ -373,40 +373,30 @@ export function getAxisPosition( labelPaddingSum: number, showLabels: boolean, ) { - const titleDimension = axisSpec.title ? getTitleDimension(axisTitle) : 0; - const { position } = axisSpec; - const dimensions = { ...chartDimensions }; - let topIncrement = 0; - let bottomIncrement = 0; - let leftIncrement = 0; - let rightIncrement = 0; - + const titleDimension = title ? getTitleDimension(axisTitle) : 0; const vertical = isVerticalAxis(position); const scaleBand = vertical ? smScales.vertical : smScales.horizontal; const panelTitleDimension = hasSMDomain(scaleBand) ? getTitleDimension(axisPanelTitle) : 0; const shownLabelSize = showLabels ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; const parallelSize = labelPaddingSum + shownLabelSize + tickDimension + titleDimension + panelTitleDimension; - if (vertical) { - if (position === Position.Left) { - leftIncrement = chartMargins.left + parallelSize; - dimensions.left = cumLeftSum + chartMargins.left; - } else { - rightIncrement = parallelSize + chartMargins.right; - dimensions.left = chartDimensions.left + chartDimensions.width + cumRightSum; - } - dimensions.width = parallelSize; - } else { - if (position === Position.Top) { - topIncrement = parallelSize + chartMargins.top; - dimensions.top = cumTopSum + chartMargins.top; - } else { - bottomIncrement = parallelSize + chartMargins.bottom; - dimensions.top = chartDimensions.top + chartDimensions.height + cumBottomSum; - } - dimensions.height = parallelSize; - } - - return { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement }; + return { + leftIncrement: position === Position.Left ? parallelSize + chartMargins.left : 0, + rightIncrement: position === Position.Right ? parallelSize + chartMargins.right : 0, + topIncrement: position === Position.Top ? parallelSize + chartMargins.top : 0, + bottomIncrement: position === Position.Bottom ? parallelSize + chartMargins.bottom : 0, + dimensions: { + left: + position === Position.Left + ? chartMargins.left + cumLeftSum + : chartDimensions.left + (position === Position.Right ? chartDimensions.width + cumRightSum : 0), + top: + position === Position.Top + ? chartMargins.top + cumTopSum + : chartDimensions.top + (position === Position.Bottom ? chartDimensions.height + cumBottomSum : 0), + width: vertical ? parallelSize : chartDimensions.width, + height: vertical ? chartDimensions.height : parallelSize, + }, + }; } /** @internal */ From 3358b60445932b8631069c00e5269abca71c436d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 14:14:04 +0200 Subject: [PATCH 62/75] refactor: getAxesGeometries flow simplification --- .../chart_types/xy_chart/utils/axis_utils.ts | 42 +++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 4a2ffb977f..1f0f32e3d1 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -438,8 +438,7 @@ export function getAxesGeometries( enableHistogramMode: boolean, fallBackTickFormatter: TickFormatter, barsPadding?: number, -): Array { - const axesGeometries: Array = []; +): AxisGeometry[] { const panel = getPanelSize(smScales); const anchorPointByAxisGroups = [...axisDimensions.entries()].reduce( @@ -497,13 +496,11 @@ export function getAxesGeometries( enableHistogramMode, ); - axisDimensions.forEach((axisDim, id) => { + return [...axisDimensions].reduce((axesGeometries: AxisGeometry[], [id, axisDim]) => { const axisSpec = getSpecsById(axisSpecs, id); const anchorPoint = anchorPointByAxisGroups.get(id); - // Consider refactoring this so this condition can be tested - // Given some of the values that get passed around, maybe re-write as a reduce instead of forEach? if (!axisSpec || !anchorPoint) { - return; + return axesGeometries; } const isVertical = isVerticalAxis(axisSpec.position); @@ -513,38 +510,31 @@ export function getAxesGeometries( if (!scale) { throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); } - // TODO: Find the true cause of the this offset error - const rotationOffset = - enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) - ? scale.step - : 0; - const allTicks = getAvailableTicks( axisSpec, scale, totalGroupsCount, enableHistogramMode, isVertical ? fallBackTickFormatter : defaultTickFormatter, - rotationOffset, + enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) + ? scale.step // TODO: Find the true cause of the this offset error + : 0, { timeZone: xDomain.timeZone }, ); - const visibleTicks = getVisibleTicks(allTicks, axisSpec, axisDim); - - const size = axisDim.isHidden - ? { width: 0, height: 0 } - : { - width: isVertical ? anchorPoint.dimensions.width : panel.width, - height: isVertical ? panel.height : anchorPoint.dimensions.height, - }; axesGeometries.push({ axis: { id: axisSpec.id, position: axisSpec.position }, anchorPoint: { x: anchorPoint.dimensions.left, y: anchorPoint.dimensions.top }, - size, - parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, dimension: axisDim, ticks: allTicks, - visibleTicks, + visibleTicks: getVisibleTicks(allTicks, axisSpec, axisDim), + parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, + size: axisDim.isHidden + ? { width: 0, height: 0 } + : { + width: isVertical ? anchorPoint.dimensions.width : panel.width, + height: isVertical ? panel.height : anchorPoint.dimensions.height, + }, }); - }); - return axesGeometries; + return axesGeometries; + }, []); } From 5109cc02cf5442c96f5010aaed3b3f69e0a3c85d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 14:20:14 +0200 Subject: [PATCH 63/75] refactor: getAxesGeometries reduction simplification --- .../chart_types/xy_chart/utils/axis_utils.ts | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 1f0f32e3d1..97e4b1495a 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -499,42 +499,39 @@ export function getAxesGeometries( return [...axisDimensions].reduce((axesGeometries: AxisGeometry[], [id, axisDim]) => { const axisSpec = getSpecsById(axisSpecs, id); const anchorPoint = anchorPointByAxisGroups.get(id); - if (!axisSpec || !anchorPoint) { - return axesGeometries; - } - - const isVertical = isVerticalAxis(axisSpec.position); - const { minRange, maxRange } = axisExtent(axisSpec.position, chartRotation, panel); - const scale = getScaleFunction(axisSpec, [minRange, maxRange]); - - if (!scale) { - throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); + if (axisSpec && anchorPoint) { + const isVertical = isVerticalAxis(axisSpec.position); + const { minRange, maxRange } = axisExtent(axisSpec.position, chartRotation, panel); + const scale = getScaleFunction(axisSpec, [minRange, maxRange]); + if (!scale) { + throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); + } + const allTicks = getAvailableTicks( + axisSpec, + scale, + totalGroupsCount, + enableHistogramMode, + isVertical ? fallBackTickFormatter : defaultTickFormatter, + enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) + ? scale.step // TODO: Find the true cause of the this offset error + : 0, + { timeZone: xDomain.timeZone }, + ); + axesGeometries.push({ + axis: { id: axisSpec.id, position: axisSpec.position }, + anchorPoint: { x: anchorPoint.dimensions.left, y: anchorPoint.dimensions.top }, + dimension: axisDim, + ticks: allTicks, + visibleTicks: getVisibleTicks(allTicks, axisSpec, axisDim), + parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, + size: axisDim.isHidden + ? { width: 0, height: 0 } + : { + width: isVertical ? anchorPoint.dimensions.width : panel.width, + height: isVertical ? panel.height : anchorPoint.dimensions.height, + }, + }); } - const allTicks = getAvailableTicks( - axisSpec, - scale, - totalGroupsCount, - enableHistogramMode, - isVertical ? fallBackTickFormatter : defaultTickFormatter, - enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) - ? scale.step // TODO: Find the true cause of the this offset error - : 0, - { timeZone: xDomain.timeZone }, - ); - axesGeometries.push({ - axis: { id: axisSpec.id, position: axisSpec.position }, - anchorPoint: { x: anchorPoint.dimensions.left, y: anchorPoint.dimensions.top }, - dimension: axisDim, - ticks: allTicks, - visibleTicks: getVisibleTicks(allTicks, axisSpec, axisDim), - parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, - size: axisDim.isHidden - ? { width: 0, height: 0 } - : { - width: isVertical ? anchorPoint.dimensions.width : panel.width, - height: isVertical ? panel.height : anchorPoint.dimensions.height, - }, - }); return axesGeometries; }, []); } From 7e73ac1a1cb7f70448434d27988796aa697ae525 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 14:29:29 +0200 Subject: [PATCH 64/75] refactor: single use util function compatible in result shape --- .../src/chart_types/xy_chart/utils/axis_utils.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 97e4b1495a..fe90e77f36 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -238,18 +238,12 @@ export function getTickLabelProps( }; } -function axisExtent( - axisPosition: Position, - chartRotation: Rotation, - { width, height }: Size, -): { minRange: number; maxRange: number } { +function axisMinMax(axisPosition: Position, chartRotation: Rotation, { width, height }: Size): [number, number] { const horizontal = isHorizontalAxis(axisPosition); const flipped = horizontal ? chartRotation === -90 || chartRotation === 180 : chartRotation === 90 || chartRotation === 180; - return horizontal - ? { minRange: flipped ? width : 0, maxRange: flipped ? 0 : width } - : { minRange: flipped ? 0 : height, maxRange: flipped ? height : 0 }; + return horizontal ? [flipped ? width : 0, flipped ? 0 : width] : [flipped ? 0 : height, flipped ? height : 0]; } /** @internal */ @@ -263,7 +257,7 @@ export function getAvailableTicks( tickFormatOptions?: TickFormatterOptions, ): AxisTick[] { const ticks = scale.ticks(); - const isSingleValueScale = scale.domain[0] - scale.domain[1] === 0; + const isSingleValueScale = scale.domain[0] === scale.domain[1]; const hasAdditionalTicks = enableHistogramMode && scale.bandwidth > 0; if (hasAdditionalTicks) { @@ -501,8 +495,7 @@ export function getAxesGeometries( const anchorPoint = anchorPointByAxisGroups.get(id); if (axisSpec && anchorPoint) { const isVertical = isVerticalAxis(axisSpec.position); - const { minRange, maxRange } = axisExtent(axisSpec.position, chartRotation, panel); - const scale = getScaleFunction(axisSpec, [minRange, maxRange]); + const scale = getScaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); if (!scale) { throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); } From 46d02215816f3ebf5e1766c1a2ebc1dda2e169a6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 15:24:40 +0200 Subject: [PATCH 65/75] refactor: avoid reducing over the same thing twice --- .../chart_types/xy_chart/utils/axis_utils.ts | 145 ++++++++---------- 1 file changed, 61 insertions(+), 84 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index fe90e77f36..b2b873afc7 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -434,97 +434,74 @@ export function getAxesGeometries( barsPadding?: number, ): AxisGeometry[] { const panel = getPanelSize(smScales); - - const anchorPointByAxisGroups = [...axisDimensions.entries()].reduce( - (acc, [axisId, dimension]) => { + const getScaleFunction = getScaleForAxisSpec( + { xDomain, yDomains }, + { rotation: chartRotation }, + totalGroupsCount, + barsPadding, + enableHistogramMode, + ); + return [...axisDimensions].reduce( + (acc: PerSideDistance & { axesGeometries: AxisGeometry[] }, [axisId, axisDim]: [string, AxisViewModel]) => { const axisSpec = getSpecsById(axisSpecs, axisId); - - if (!axisSpec) { - return acc; + if (axisSpec) { + const scale = getScaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); + if (!scale) throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); + + const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; + const labelPaddingSum = tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; + const isVertical = isVerticalAxis(axisSpec.position); + const allTicks = getAvailableTicks( + axisSpec, + scale, + totalGroupsCount, + enableHistogramMode, + isVertical ? fallBackTickFormatter : defaultTickFormatter, + enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) + ? scale.step // TODO: Find the true cause of the this offset error + : 0, + { timeZone: xDomain.timeZone }, + ); + const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = getAxisPosition( + computedChartDims.chartDimensions, + chartMargins, + axisTitle, + axisPanelTitle, + axisSpec, + axisDim, + smScales, + acc, + shouldShowTicks(tickLine, axisSpec.hide) ? tickLine.size + tickLine.padding : 0, + labelPaddingSum, + tickLabel.visible, + ); + acc.axesGeometries.push({ + axis: { id: axisSpec.id, position: axisSpec.position }, + anchorPoint: { x: dimensions.left, y: dimensions.top }, + dimension: axisDim, + ticks: allTicks, + visibleTicks: getVisibleTicks(allTicks, axisSpec, axisDim), + parentSize: { height: dimensions.height, width: dimensions.width }, + size: axisDim.isHidden + ? { width: 0, height: 0 } + : { + width: isVertical ? dimensions.width : panel.width, + height: isVertical ? panel.height : dimensions.height, + }, + }); + acc.top += topIncrement; + acc.bottom += bottomIncrement; + acc.left += leftIncrement; + acc.right += rightIncrement; } - - const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; - const tickDimension = shouldShowTicks(tickLine, axisSpec.hide) ? tickLine.size + tickLine.padding : 0; - const labelPaddingSum = tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; - - const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = getAxisPosition( - computedChartDims.chartDimensions, - chartMargins, - axisTitle, - axisPanelTitle, - axisSpec, - dimension, - smScales, - acc, - tickDimension, - labelPaddingSum, - tickLabel.visible, - ); - - acc.pos.set(axisId, { - anchor: { top: acc.top, left: acc.left, right: acc.right, bottom: acc.bottom }, - dimensions, - }); - return { - top: acc.top + topIncrement, - bottom: acc.bottom + bottomIncrement, - left: acc.left + leftIncrement, - right: acc.right + rightIncrement, - pos: acc.pos, - }; + return acc; }, { + axesGeometries: [], top: 0, bottom: chartPaddings.bottom, left: computedChartDims.leftMargin, right: chartPaddings.right, - pos: new Map(), }, - ).pos; - - const getScaleFunction = getScaleForAxisSpec( - { xDomain, yDomains }, - { rotation: chartRotation }, - totalGroupsCount, - barsPadding, - enableHistogramMode, - ); - - return [...axisDimensions].reduce((axesGeometries: AxisGeometry[], [id, axisDim]) => { - const axisSpec = getSpecsById(axisSpecs, id); - const anchorPoint = anchorPointByAxisGroups.get(id); - if (axisSpec && anchorPoint) { - const isVertical = isVerticalAxis(axisSpec.position); - const scale = getScaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); - if (!scale) { - throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); - } - const allTicks = getAvailableTicks( - axisSpec, - scale, - totalGroupsCount, - enableHistogramMode, - isVertical ? fallBackTickFormatter : defaultTickFormatter, - enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) - ? scale.step // TODO: Find the true cause of the this offset error - : 0, - { timeZone: xDomain.timeZone }, - ); - axesGeometries.push({ - axis: { id: axisSpec.id, position: axisSpec.position }, - anchorPoint: { x: anchorPoint.dimensions.left, y: anchorPoint.dimensions.top }, - dimension: axisDim, - ticks: allTicks, - visibleTicks: getVisibleTicks(allTicks, axisSpec, axisDim), - parentSize: { height: anchorPoint.dimensions.height, width: anchorPoint.dimensions.width }, - size: axisDim.isHidden - ? { width: 0, height: 0 } - : { - width: isVertical ? anchorPoint.dimensions.width : panel.width, - height: isVertical ? panel.height : anchorPoint.dimensions.height, - }, - }); - } - return axesGeometries; - }, []); + ).axesGeometries; } From ed1caff796e0414209570ec20948b53bfd93cfca Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 15:59:58 +0200 Subject: [PATCH 66/75] refactor: avoid reducing over the same thing twice 2 --- .../chart_types/xy_chart/utils/axis_utils.ts | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index b2b873afc7..8753af9d35 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -434,7 +434,7 @@ export function getAxesGeometries( barsPadding?: number, ): AxisGeometry[] { const panel = getPanelSize(smScales); - const getScaleFunction = getScaleForAxisSpec( + const scaleFunction = getScaleForAxisSpec( { xDomain, yDomains }, { rotation: chartRotation }, totalGroupsCount, @@ -442,10 +442,10 @@ export function getAxesGeometries( enableHistogramMode, ); return [...axisDimensions].reduce( - (acc: PerSideDistance & { axesGeometries: AxisGeometry[] }, [axisId, axisDim]: [string, AxisViewModel]) => { + (acc: PerSideDistance & { geoms: AxisGeometry[] }, [axisId, axisDim]: [string, AxisViewModel]) => { const axisSpec = getSpecsById(axisSpecs, axisId); if (axisSpec) { - const scale = getScaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); + const scale = scaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); if (!scale) throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; @@ -475,7 +475,12 @@ export function getAxesGeometries( labelPaddingSum, tickLabel.visible, ); - acc.axesGeometries.push({ + + acc.top += topIncrement; + acc.bottom += bottomIncrement; + acc.left += leftIncrement; + acc.right += rightIncrement; + acc.geoms.push({ axis: { id: axisSpec.id, position: axisSpec.position }, anchorPoint: { x: dimensions.left, y: dimensions.top }, dimension: axisDim, @@ -489,19 +494,9 @@ export function getAxesGeometries( height: isVertical ? panel.height : dimensions.height, }, }); - acc.top += topIncrement; - acc.bottom += bottomIncrement; - acc.left += leftIncrement; - acc.right += rightIncrement; } return acc; }, - { - axesGeometries: [], - top: 0, - bottom: chartPaddings.bottom, - left: computedChartDims.leftMargin, - right: chartPaddings.right, - }, - ).axesGeometries; + { geoms: [], top: 0, bottom: chartPaddings.bottom, left: computedChartDims.leftMargin, right: chartPaddings.right }, + ).geoms; } From 83c77f28acf3559f845973880360295769cb5dcc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 16:09:12 +0200 Subject: [PATCH 67/75] refactor: type has shifted in meaning --- .../xy_chart/renderer/canvas/axes/index.ts | 4 ++-- .../selectors/compute_axis_ticks_dimensions.ts | 4 ++-- .../chart_types/xy_chart/utils/axis_utils.test.ts | 4 ++-- .../src/chart_types/xy_chart/utils/axis_utils.ts | 14 +++++++------- .../chart_types/xy_chart/utils/dimensions.test.ts | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/index.ts b/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/index.ts index 6541c5b099..7a06064d28 100644 --- a/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/index.ts +++ b/packages/charts/src/chart_types/xy_chart/renderer/canvas/axes/index.ts @@ -10,7 +10,7 @@ import { Dimensions, Size } from '../../../../../utils/dimensions'; import { Point } from '../../../../../utils/point'; import { AxisStyle } from '../../../../../utils/themes/theme'; import { PerPanelAxisGeoms } from '../../../state/selectors/compute_per_panel_axes_geoms'; -import { AxisTick, AxisViewModel, shouldShowTicks } from '../../../utils/axis_utils'; +import { AxisTick, TickLabelBounds, shouldShowTicks } from '../../../utils/axis_utils'; import { AxisSpec } from '../../../utils/specs'; import { renderAxisLine } from './line'; import { renderTick } from './tick'; @@ -25,7 +25,7 @@ export interface AxisProps { axisSpec: AxisSpec; size: Size; anchorPoint: Point; - dimension: AxisViewModel; + dimension: TickLabelBounds; ticks: AxisTick[]; debug: boolean; renderingArea: Dimensions; diff --git a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts index b4f5c55f23..cbad1e9ee1 100644 --- a/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts +++ b/packages/charts/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -14,7 +14,7 @@ import { AxisId } from '../../../../utils/ids'; import { Logger } from '../../../../utils/logger'; import { isVerticalAxis } from '../../utils/axis_type_utils'; import { - AxisViewModel, + TickLabelBounds, computeRotatedLabelDimensions, defaultTickFormatter, getScaleForAxisSpec, @@ -27,7 +27,7 @@ import { getAxisSpecsSelector, getSeriesSpecsSelector } from './get_specs'; import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; /** @internal */ -export type AxesTicksDimensions = Map; +export type AxesTicksDimensions = Map; const getScaleFunction = createCustomCachedSelector( [ diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 682fa74cca..40ff8c1a9b 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -35,7 +35,7 @@ import { computeGridLinesSelector } from '../state/selectors/get_grid_lines'; import { mergeYCustomDomainsByGroupId } from '../state/selectors/merge_y_custom_domains'; import { AxisTick, - AxisViewModel, + TickLabelBounds, computeRotatedLabelDimensions, getAvailableTicks, getAxisPosition, @@ -233,7 +233,7 @@ describe('Axis computational utils', () => { expect(xScale).toBeDefined(); }); - const axisDimensions: AxisViewModel = { + const axisDimensions: TickLabelBounds = { maxLabelBboxWidth: 100, maxLabelBboxHeight: 100, maxLabelTextHeight: 100, diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 8753af9d35..adaefd99b5 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -45,7 +45,7 @@ export interface AxisTick { } /** @internal */ -export interface AxisViewModel { +export interface TickLabelBounds { maxLabelBboxWidth: number; maxLabelBboxHeight: number; maxLabelTextWidth: number; @@ -101,7 +101,7 @@ export function computeRotatedLabelDimensions(unrotatedDims: BBox, degreesRotati return { width: rotatedWidth, height: rotatedHeight }; } -function getUserTextOffsets(dimensions: AxisViewModel, { x, y, reference }: TextOffset) { +function getUserTextOffsets(dimensions: TickLabelBounds, { x, y, reference }: TextOffset) { return reference === 'global' ? { local: { x: 0, y: 0 }, @@ -201,7 +201,7 @@ export function getTickLabelProps( position: Position, rotation: number, axisSize: Size, - tickDimensions: AxisViewModel, + tickDimensions: TickLabelBounds, showTicks: boolean, textOffset: TextOffset, textAlignment?: TextAlignment, @@ -324,7 +324,7 @@ export function enableDuplicatedTicks( } /** @internal */ -export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: AxisViewModel): AxisTick[] { +export function getVisibleTicks(allTicks: AxisTick[], axisSpec: AxisSpec, axisDim: TickLabelBounds): AxisTick[] { const { showOverlappingTicks, showOverlappingLabels, position } = axisSpec; const requiredSpace = isVerticalAxis(position) ? axisDim.maxLabelBboxHeight / 2 : axisDim.maxLabelBboxWidth / 2; return showOverlappingLabels @@ -360,7 +360,7 @@ export function getAxisPosition( axisTitle: AxisStyle['axisTitle'], axisPanelTitle: AxisStyle['axisPanelTitle'], { title, position }: AxisSpec, - { maxLabelBboxHeight, maxLabelBboxWidth }: AxisViewModel, + { maxLabelBboxHeight, maxLabelBboxWidth }: TickLabelBounds, smScales: SmallMultipleScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }: PerSideDistance, tickDimension: number, @@ -409,7 +409,7 @@ export interface AxisGeometry { panelTitle?: string; // defined later per panel secondary?: boolean; // defined later per panel }; - dimension: AxisViewModel; + dimension: TickLabelBounds; ticks: AxisTick[]; visibleTicks: AxisTick[]; } @@ -442,7 +442,7 @@ export function getAxesGeometries( enableHistogramMode, ); return [...axisDimensions].reduce( - (acc: PerSideDistance & { geoms: AxisGeometry[] }, [axisId, axisDim]: [string, AxisViewModel]) => { + (acc: PerSideDistance & { geoms: AxisGeometry[] }, [axisId, axisDim]: [string, TickLabelBounds]) => { const axisSpec = getSpecsById(axisSpecs, axisId); if (axisSpec) { const scale = scaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); diff --git a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts index 74d83e49af..32c99bac48 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -14,7 +14,7 @@ import { AxisId } from '../../../utils/ids'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { LegendStyle } from '../../../utils/themes/theme'; import { AxesTicksDimensions } from '../state/selectors/compute_axis_ticks_dimensions'; -import { AxisViewModel } from './axis_utils'; +import { TickLabelBounds } from './axis_utils'; import { computeChartDimensions } from './dimensions'; import { AxisSpec } from './specs'; @@ -38,7 +38,7 @@ describe('Computed chart dimensions', () => { bottom: 10, }; - const axis1Dims: AxisViewModel = { + const axis1Dims: TickLabelBounds = { maxLabelBboxWidth: 10, maxLabelBboxHeight: 10, maxLabelTextWidth: 10, From 39a55b9f896c862eba87b46aa1f187ba88faeffe Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 16:21:28 +0200 Subject: [PATCH 68/75] chore: minor reorder for better flow --- .../src/chart_types/xy_chart/utils/axis_utils.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index adaefd99b5..6f3f209cd0 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -448,20 +448,19 @@ export function getAxesGeometries( const scale = scaleFunction(axisSpec, axisMinMax(axisSpec.position, chartRotation, panel)); if (!scale) throw new Error(`Cannot compute scale for axis spec ${axisSpec.id}`); - const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; - const labelPaddingSum = tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; - const isVertical = isVerticalAxis(axisSpec.position); + const vertical = isVerticalAxis(axisSpec.position); const allTicks = getAvailableTicks( axisSpec, scale, totalGroupsCount, enableHistogramMode, - isVertical ? fallBackTickFormatter : defaultTickFormatter, - enableHistogramMode && ((isVertical && chartRotation === -90) || (!isVertical && chartRotation === 180)) + vertical ? fallBackTickFormatter : defaultTickFormatter, + enableHistogramMode && ((vertical && chartRotation === -90) || (!vertical && chartRotation === 180)) ? scale.step // TODO: Find the true cause of the this offset error : 0, { timeZone: xDomain.timeZone }, ); + const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = getAxisPosition( computedChartDims.chartDimensions, chartMargins, @@ -472,7 +471,7 @@ export function getAxesGeometries( smScales, acc, shouldShowTicks(tickLine, axisSpec.hide) ? tickLine.size + tickLine.padding : 0, - labelPaddingSum, + tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0, tickLabel.visible, ); @@ -490,8 +489,8 @@ export function getAxesGeometries( size: axisDim.isHidden ? { width: 0, height: 0 } : { - width: isVertical ? dimensions.width : panel.width, - height: isVertical ? panel.height : dimensions.height, + width: vertical ? dimensions.width : panel.width, + height: vertical ? panel.height : dimensions.height, }, }); } From fee714822ce020a37fa9cfe4f6c5804443544287 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 16:38:39 +0200 Subject: [PATCH 69/75] refactor: updated utility function boundary --- .../chart_types/xy_chart/utils/axis_utils.ts | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 6f3f209cd0..a72355e99a 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -353,6 +353,46 @@ export function getTitleDimension({ return visible && fontSize > 0 ? innerPad(padding) + fontSize + outerPad(padding) : 0; } +function getPosition( + computedChartDims: { chartDimensions: Dimensions; leftMargin: number }, + chartMargins: PerSideDistance, + { axisTitle, axisPanelTitle, tickLine, tickLabel }: AxisStyle, + { title, position, hide }: AxisSpec, + { maxLabelBboxHeight, maxLabelBboxWidth }: TickLabelBounds, + smScales: SmallMultipleScales, + acc: PerSideDistance, +) { + const { chartDimensions } = computedChartDims; + const tickDimension = shouldShowTicks(tickLine, hide) ? tickLine.size + tickLine.padding : 0; + const showLabels = tickLabel.visible; + const labelPaddingSum = showLabels ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; + const { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum } = acc; + const titleDimension = title ? getTitleDimension(axisTitle) : 0; + const vertical = isVerticalAxis(position); + const scaleBand = vertical ? smScales.vertical : smScales.horizontal; + const panelTitleDimension = hasSMDomain(scaleBand) ? getTitleDimension(axisPanelTitle) : 0; + const shownLabelSize = showLabels ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; + const parallelSize = labelPaddingSum + shownLabelSize + tickDimension + titleDimension + panelTitleDimension; + return { + leftIncrement: position === Position.Left ? parallelSize + chartMargins.left : 0, + rightIncrement: position === Position.Right ? parallelSize + chartMargins.right : 0, + topIncrement: position === Position.Top ? parallelSize + chartMargins.top : 0, + bottomIncrement: position === Position.Bottom ? parallelSize + chartMargins.bottom : 0, + dimensions: { + left: + position === Position.Left + ? chartMargins.left + cumLeftSum + : chartDimensions.left + (position === Position.Right ? chartDimensions.width + cumRightSum : 0), + top: + position === Position.Top + ? chartMargins.top + cumTopSum + : chartDimensions.top + (position === Position.Bottom ? chartDimensions.height + cumBottomSum : 0), + width: vertical ? parallelSize : chartDimensions.width, + height: vertical ? chartDimensions.height : parallelSize, + }, + }; +} + /** @internal */ export function getAxisPosition( chartDimensions: Dimensions, @@ -416,10 +456,7 @@ export interface AxisGeometry { /** @internal */ export function getAxesGeometries( - computedChartDims: { - chartDimensions: Dimensions; - leftMargin: number; - }, + chartDims: { chartDimensions: Dimensions; leftMargin: number }, { chartPaddings, chartMargins, axes: sharedAxesStyle }: Theme, chartRotation: Rotation, axisSpecs: AxisSpec[], @@ -460,20 +497,9 @@ export function getAxesGeometries( : 0, { timeZone: xDomain.timeZone }, ); - const { tickLine, tickLabel, axisTitle, axisPanelTitle } = axesStyles.get(axisId) ?? sharedAxesStyle; - const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = getAxisPosition( - computedChartDims.chartDimensions, - chartMargins, - axisTitle, - axisPanelTitle, - axisSpec, - axisDim, - smScales, - acc, - shouldShowTicks(tickLine, axisSpec.hide) ? tickLine.size + tickLine.padding : 0, - tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0, - tickLabel.visible, - ); + const axisStyle = axesStyles.get(axisId) ?? sharedAxesStyle; + const axisPositionData = getPosition(chartDims, chartMargins, axisStyle, axisSpec, axisDim, smScales, acc); + const { dimensions, topIncrement, bottomIncrement, leftIncrement, rightIncrement } = axisPositionData; acc.top += topIncrement; acc.bottom += bottomIncrement; @@ -496,6 +522,6 @@ export function getAxesGeometries( } return acc; }, - { geoms: [], top: 0, bottom: chartPaddings.bottom, left: computedChartDims.leftMargin, right: chartPaddings.right }, + { geoms: [], top: 0, bottom: chartPaddings.bottom, left: chartDims.leftMargin, right: chartPaddings.right }, ).geoms; } From d9944a4c6083e1ef34e021d0104cb982b72afed3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 17:27:40 +0200 Subject: [PATCH 70/75] test: updates for the new utility function --- .../xy_chart/utils/axis_utils.test.ts | 114 +++++++----------- .../chart_types/xy_chart/utils/axis_utils.ts | 5 +- 2 files changed, 44 insertions(+), 75 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts index 40ff8c1a9b..fa607e25b3 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -38,7 +38,7 @@ import { TickLabelBounds, computeRotatedLabelDimensions, getAvailableTicks, - getAxisPosition, + getPosition, getAxesGeometries, getTickLabelProps, getVisibleTicks, @@ -827,29 +827,25 @@ describe('Axis computational utils', () => { const cumLeftSum = 10; const cumRightSum = 10; - const leftAxisPosition = getAxisPosition( - chartDim, + const leftAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisTitleStyles(axisTitleHeight).axisTitle, - axisTitleStyles(axisTitleHeight).axisPanelTitle, + axisTitleStyles(axisTitleHeight), verticalAxisSpec, axis1Dims, emptySmScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedLeftAxisPosition = { dimensions: { height: 100, - width: 40, + width: 50, left: 20, top: 0, }, topIncrement: 0, bottomIncrement: 0, - leftIncrement: 50, + leftIncrement: 60, rightIncrement: 0, }; @@ -864,31 +860,27 @@ describe('Axis computational utils', () => { const cumRightSum = 10; verticalAxisSpec.position = Position.Right; - const rightAxisPosition = getAxisPosition( - chartDim, + const rightAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisTitleStyles(axisTitleHeight).axisTitle, - axisTitleStyles(axisTitleHeight).axisPanelTitle, + axisTitleStyles(axisTitleHeight), verticalAxisSpec, axis1Dims, emptySmScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedRightAxisPosition = { dimensions: { height: 100, - width: 40, + width: 50, left: 110, top: 0, }, topIncrement: 0, bottomIncrement: 0, leftIncrement: 0, - rightIncrement: 50, + rightIncrement: 60, }; expect(rightAxisPosition).toEqual(expectedRightAxisPosition); @@ -902,29 +894,25 @@ describe('Axis computational utils', () => { const cumRightSum = 10; horizontalAxisSpec.position = Position.Top; - const topAxisPosition = getAxisPosition( - chartDim, + const topAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisTitleStyles(axisTitleHeight).axisTitle, - axisTitleStyles(axisTitleHeight).axisPanelTitle, + axisTitleStyles(axisTitleHeight), horizontalAxisSpec, axis1Dims, emptySmScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const { size: tickSize, padding: tickPadding } = LIGHT_THEME.axes.tickLine; const expectedTopAxisPosition = { dimensions: { - height: axis1Dims.maxLabelBboxHeight + axisTitleHeight + tickSize + tickPadding, + height: 50 || axis1Dims.maxLabelBboxHeight + axisTitleHeight + tickSize + tickPadding, width: 100, left: 0, top: cumTopSum + LIGHT_THEME.chartMargins.top, }, - topIncrement: 50, + topIncrement: 60, bottomIncrement: 0, leftIncrement: 0, rightIncrement: 0, @@ -941,29 +929,25 @@ describe('Axis computational utils', () => { const cumRightSum = 10; horizontalAxisSpec.position = Position.Bottom; - const bottomAxisPosition = getAxisPosition( - chartDim, + const bottomAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisTitleStyles(axisTitleHeight).axisTitle, - axisTitleStyles(axisTitleHeight).axisPanelTitle, + axisTitleStyles(axisTitleHeight), horizontalAxisSpec, axis1Dims, emptySmScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedBottomAxisPosition = { dimensions: { - height: 40, + height: 50, width: 100, left: 0, top: 110, }, topIncrement: 0, - bottomIncrement: 50, + bottomIncrement: 60, leftIncrement: 0, rightIncrement: 0, }; @@ -1435,31 +1419,27 @@ describe('Axis computational utils', () => { describe.each(['test', ''])('Axes title positions - title is "%s"', (title) => { test('should compute left axis position', () => { - const leftAxisPosition = getAxisPosition( - chartDim, + const leftAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisStyles.axisTitle, - axisStyles.axisPanelTitle, + axisStyles, { ...verticalAxisSpec, title }, axis1Dims, smScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedLeftAxisPosition = { dimensions: { height: 100, - width: title ? 56 : 36, + width: title ? 66 : 46, left: 110, top: 0, }, topIncrement: 0, bottomIncrement: 0, leftIncrement: 0, - rightIncrement: title ? 66 : 46, + rightIncrement: title ? 76 : 56, }; expect(leftAxisPosition).toEqual(expectedLeftAxisPosition); @@ -1467,31 +1447,27 @@ describe('Axis computational utils', () => { test('should compute right axis position', () => { verticalAxisSpec.position = Position.Right; - const rightAxisPosition = getAxisPosition( - chartDim, + const rightAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisStyles.axisTitle, - axisStyles.axisPanelTitle, + axisStyles, { ...verticalAxisSpec, title }, axis1Dims, smScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedRightAxisPosition = { dimensions: { height: 100, - width: title ? 56 : 36, + width: title ? 66 : 46, left: 110, top: 0, }, topIncrement: 0, bottomIncrement: 0, leftIncrement: 0, - rightIncrement: title ? 66 : 46, + rightIncrement: title ? 76 : 56, }; expect(rightAxisPosition).toEqual(expectedRightAxisPosition); @@ -1499,28 +1475,24 @@ describe('Axis computational utils', () => { test('should compute top axis position', () => { horizontalAxisSpec.position = Position.Top; - const topAxisPosition = getAxisPosition( - chartDim, + const topAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisStyles.axisTitle, - axisStyles.axisPanelTitle, + axisStyles, { ...horizontalAxisSpec, title }, axis1Dims, smScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedTopAxisPosition = { dimensions: { - height: title ? 56 : 36, + height: title ? 66 : 46, width: 100, left: 0, top: 20, }, - topIncrement: title ? 66 : 46, + topIncrement: title ? 76 : 56, bottomIncrement: 0, leftIncrement: 0, rightIncrement: 0, @@ -1531,29 +1503,25 @@ describe('Axis computational utils', () => { test('should compute bottom axis position', () => { horizontalAxisSpec.position = Position.Bottom; - const bottomAxisPosition = getAxisPosition( - chartDim, + const bottomAxisPosition = getPosition( + { chartDimensions: chartDim }, LIGHT_THEME.chartMargins, - axisStyles.axisTitle, - axisStyles.axisPanelTitle, + axisStyles, { ...horizontalAxisSpec, title }, axis1Dims, smScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }, - 10, - 0, - true, ); const expectedBottomAxisPosition = { dimensions: { - height: title ? 56 : 36, + height: title ? 66 : 46, width: 100, left: 0, top: 110, }, topIncrement: 0, - bottomIncrement: title ? 66 : 46, + bottomIncrement: title ? 76 : 56, leftIncrement: 0, rightIncrement: 0, }; diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index a72355e99a..62350b34a6 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -353,8 +353,9 @@ export function getTitleDimension({ return visible && fontSize > 0 ? innerPad(padding) + fontSize + outerPad(padding) : 0; } -function getPosition( - computedChartDims: { chartDimensions: Dimensions; leftMargin: number }, +/** @internal */ +export function getPosition( + computedChartDims: { chartDimensions: Dimensions }, chartMargins: PerSideDistance, { axisTitle, axisPanelTitle, tickLine, tickLabel }: AxisStyle, { title, position, hide }: AxisSpec, From f777a9438cab786eb1e09c4715943fe5309b72d2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 18:18:32 +0200 Subject: [PATCH 71/75] chore: removing the replaced function --- .../chart_types/xy_chart/utils/axis_utils.ts | 53 ++----------------- 1 file changed, 5 insertions(+), 48 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 62350b34a6..996cfb4dbd 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -18,7 +18,7 @@ import { Rotation, VerticalAlignment, } from '../../../utils/common'; -import { Dimensions, innerPad, Margins, outerPad, PerSideDistance, Size } from '../../../utils/dimensions'; +import { Dimensions, innerPad, outerPad, PerSideDistance, Size } from '../../../utils/dimensions'; import { Range } from '../../../utils/domain'; import { AxisId } from '../../../utils/ids'; import { Point } from '../../../utils/point'; @@ -355,64 +355,21 @@ export function getTitleDimension({ /** @internal */ export function getPosition( - computedChartDims: { chartDimensions: Dimensions }, + { chartDimensions }: { chartDimensions: Dimensions }, chartMargins: PerSideDistance, { axisTitle, axisPanelTitle, tickLine, tickLabel }: AxisStyle, { title, position, hide }: AxisSpec, { maxLabelBboxHeight, maxLabelBboxWidth }: TickLabelBounds, smScales: SmallMultipleScales, - acc: PerSideDistance, -) { - const { chartDimensions } = computedChartDims; - const tickDimension = shouldShowTicks(tickLine, hide) ? tickLine.size + tickLine.padding : 0; - const showLabels = tickLabel.visible; - const labelPaddingSum = showLabels ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; - const { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum } = acc; - const titleDimension = title ? getTitleDimension(axisTitle) : 0; - const vertical = isVerticalAxis(position); - const scaleBand = vertical ? smScales.vertical : smScales.horizontal; - const panelTitleDimension = hasSMDomain(scaleBand) ? getTitleDimension(axisPanelTitle) : 0; - const shownLabelSize = showLabels ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; - const parallelSize = labelPaddingSum + shownLabelSize + tickDimension + titleDimension + panelTitleDimension; - return { - leftIncrement: position === Position.Left ? parallelSize + chartMargins.left : 0, - rightIncrement: position === Position.Right ? parallelSize + chartMargins.right : 0, - topIncrement: position === Position.Top ? parallelSize + chartMargins.top : 0, - bottomIncrement: position === Position.Bottom ? parallelSize + chartMargins.bottom : 0, - dimensions: { - left: - position === Position.Left - ? chartMargins.left + cumLeftSum - : chartDimensions.left + (position === Position.Right ? chartDimensions.width + cumRightSum : 0), - top: - position === Position.Top - ? chartMargins.top + cumTopSum - : chartDimensions.top + (position === Position.Bottom ? chartDimensions.height + cumBottomSum : 0), - width: vertical ? parallelSize : chartDimensions.width, - height: vertical ? chartDimensions.height : parallelSize, - }, - }; -} - -/** @internal */ -export function getAxisPosition( - chartDimensions: Dimensions, - chartMargins: Margins, - axisTitle: AxisStyle['axisTitle'], - axisPanelTitle: AxisStyle['axisPanelTitle'], - { title, position }: AxisSpec, - { maxLabelBboxHeight, maxLabelBboxWidth }: TickLabelBounds, - smScales: SmallMultipleScales, { top: cumTopSum, bottom: cumBottomSum, left: cumLeftSum, right: cumRightSum }: PerSideDistance, - tickDimension: number, - labelPaddingSum: number, - showLabels: boolean, ) { + const tickDimension = shouldShowTicks(tickLine, hide) ? tickLine.size + tickLine.padding : 0; + const labelPaddingSum = tickLabel.visible ? innerPad(tickLabel.padding) + outerPad(tickLabel.padding) : 0; const titleDimension = title ? getTitleDimension(axisTitle) : 0; const vertical = isVerticalAxis(position); const scaleBand = vertical ? smScales.vertical : smScales.horizontal; const panelTitleDimension = hasSMDomain(scaleBand) ? getTitleDimension(axisPanelTitle) : 0; - const shownLabelSize = showLabels ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; + const shownLabelSize = tickLabel.visible ? (vertical ? maxLabelBboxWidth : maxLabelBboxHeight) : 0; const parallelSize = labelPaddingSum + shownLabelSize + tickDimension + titleDimension + panelTitleDimension; return { leftIncrement: position === Position.Left ? parallelSize + chartMargins.left : 0, From b22c647a1fce16c8e5f47ecaf003e64f6962a4f1 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 18:25:28 +0200 Subject: [PATCH 72/75] fix: sort the right thing ht @markov00 --- packages/charts/src/chart_types/xy_chart/utils/series.ts | 4 ++-- packages/charts/src/specs/settings.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/series.ts b/packages/charts/src/chart_types/xy_chart/utils/series.ts index a135bb1c41..dd943533bf 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/series.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/series.ts @@ -299,9 +299,9 @@ const getSortedDataSeries = ( xValues: Set, xScaleType: ScaleType, ): DataSeries[] => - [...dataSeries].map(({ data, ...rest }) => ({ + dataSeries.map(({ data, ...rest }) => ({ ...rest, - data: data.sort(datumXSortPredicate(xScaleType, [...xValues.values()])), + data: [...data].sort(datumXSortPredicate(xScaleType, [...xValues.values()])), })); /** @internal */ diff --git a/packages/charts/src/specs/settings.tsx b/packages/charts/src/specs/settings.tsx index 001d59d4b1..5c1317bdb5 100644 --- a/packages/charts/src/specs/settings.tsx +++ b/packages/charts/src/specs/settings.tsx @@ -49,7 +49,7 @@ import { /** @public */ export interface LayerValue { /** - * The category value as retrieved by the `groupByRollup` callback§ + * The category value as retrieved by the `groupByRollup` callback */ groupByRollup: PrimitiveValue; /** From 448babf69f288e5b9f9295daab2bbe40a65881f1 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 7 Sep 2021 23:59:47 +0200 Subject: [PATCH 73/75] test: tooltip to match color ht Marco --- storybook/stories/area/21_with_time_timeslip.story.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/storybook/stories/area/21_with_time_timeslip.story.tsx b/storybook/stories/area/21_with_time_timeslip.story.tsx index e24a494466..81a4d3dd9b 100644 --- a/storybook/stories/area/21_with_time_timeslip.story.tsx +++ b/storybook/stories/area/21_with_time_timeslip.story.tsx @@ -166,10 +166,8 @@ export const Example = () => { xAccessor={0} yAccessors={[1]} yNice - areaSeriesStyle={{ - area: { fill: dataInk, opacity: 0.3 }, - line: { stroke: dataInk, opacity: 1 }, - }} + color={dataInk} + areaSeriesStyle={{ area: { opacity: 0.3 }, line: { opacity: 1 } }} data={data.map(([t, v]) => [t0 + (t - t0) * 4, v])} /> From 5a587c5947bbb6aa9d466d375e4f2d6af4bdbe96 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 8 Sep 2021 01:15:35 +0200 Subject: [PATCH 74/75] fix: showDuplicatedTicks looks for render candidate rather than theoretical tick duplicates --- .../chart_types/xy_chart/utils/axis_utils.ts | 2 +- .../area/21_with_time_timeslip.story.tsx | 47 +++++++++---------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts index 996cfb4dbd..967d3b7258 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/axis_utils.ts @@ -320,7 +320,7 @@ export function enableDuplicatedTicks( axisTickLabel: (axisSpec.labelFormat ?? axisSpec.tickFormat ?? fallBackTickFormatter)(tick, tickFormatOptions), position: (scale.scale(tick) ?? 0) + offset, })); - return axisSpec.showDuplicatedTicks ? allTicks : getUniqueValues(allTicks, 'label', true); + return axisSpec.showDuplicatedTicks ? allTicks : getUniqueValues(allTicks, 'axisTickLabel', true); } /** @internal */ diff --git a/storybook/stories/area/21_with_time_timeslip.story.tsx b/storybook/stories/area/21_with_time_timeslip.story.tsx index 81a4d3dd9b..867f22d603 100644 --- a/storybook/stories/area/21_with_time_timeslip.story.tsx +++ b/storybook/stories/area/21_with_time_timeslip.story.tsx @@ -23,6 +23,14 @@ const tickLabelStyle = { fontSize: 11, fontFamily, fill: 'rgba(0,0,0,0.8)' }; const axisTitleColor = 'rgb(112,112,112)'; const axisTitleFontSize = 15; const dataInk = 'rgba(96, 146, 192, 1)'; +const tooltipDateFormatter = (d: any) => + new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + }).format(d); const xAxisStyle = { tickLine: { size: 0.0001, padding: -6, ...gridStyle }, @@ -44,24 +52,17 @@ export const Example = () => { const shortWhiskers = boolean('Shorter X axis minor whiskers', true); const minorGridLines = boolean('Minor grid lines', true); const horizontalAxisTitle = boolean('Horizontal axis title', false); - const topAxisLabelFormat = (d: any) => { - // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; - return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }) - .format(d) - .padStart(2, '0')}′ `; - }; - const midAxisLabelFormatter = (d: any) => { - return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }) - .format(d) - .padStart(2, '0')} `; - }; - const bottomAxisLabelFormatter = (d: any) => { - return `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { + // const chartWidth = document.querySelector('.echContainer')?.getBoundingClientRect().width ?? 0; + const topAxisLabelFormat = (d: any) => + `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { minute: 'numeric' }).format(d).padStart(2, '0')}′ `; + const midAxisLabelFormatter = (d: any) => + `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { hour: 'numeric' }).format(d).padStart(2, '0')} `; + const bottomAxisLabelFormatter = (d: any) => + `${whiskers ? ' ' : ''}${new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', }).format(d)} `; - }; const yAxisTitle = 'CPU utilization'; return ( @@ -91,9 +92,8 @@ export const Example = () => { { id="x_major" title="timestamp per 1 minute" position={Position.Bottom} - showOverlappingTicks={boolean('showOverlappingTicks bottom axis', false)} - showOverlappingLabels={boolean('showOverlappingLabels bottom axis', false)} + showOverlappingTicks={boolean('showOverlappingTicks time axis', false)} + showOverlappingLabels={boolean('showOverlappingLabels time axis', false)} showDuplicatedTicks={false} - tickFormat={midAxisLabelFormatter} ticks={1} showGridLines gridLine={gridStyle} @@ -132,10 +131,10 @@ export const Example = () => { id="x_context" title="time (1-minute measurements)" position={Position.Bottom} - showOverlappingTicks={boolean('showOverlappingTicks bottom axis', false)} - showOverlappingLabels={boolean('showOverlappingLabels bottom axis', false)} + showOverlappingTicks={boolean('showOverlappingTicks time axis', false)} + showOverlappingLabels={boolean('showOverlappingLabels time axis', false)} showDuplicatedTicks={false} - tickFormat={bottomAxisLabelFormatter} + tickFormat={tooltipDateFormatter} ticks={2} showGridLines gridLine={gridStyle} @@ -160,7 +159,7 @@ export const Example = () => { tickFormat={(d) => `${Number(d).toFixed(0)}%`} /> Date: Wed, 8 Sep 2021 13:51:18 +0200 Subject: [PATCH 75/75] fix: abstractGeoms were meant to be spread ht @nickofthyme --- .../src/chart_types/goal_chart/layout/viewmodel/geoms.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts index 13d957e4a3..45dcbd51e2 100644 --- a/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts +++ b/packages/charts/src/chart_types/goal_chart/layout/viewmodel/geoms.ts @@ -405,7 +405,7 @@ export function geoms( const angleScale = (x: number) => angleStart + (angleRange * (x - domain[0])) / domainExtent; const clockwise = angleStart > angleEnd; // todo refine this crude approach - const [...geomObjects] = abstractGeoms + return [...abstractGeoms] .sort((a, b) => a.order - b.order) .map(({ landmarks, aes }) => { const at = get(landmarks, 'at', ''); @@ -464,5 +464,4 @@ export function geoms( return new Section(x0, y0, x1, y1, lineWidth, strokeStyle); } }); - return geomObjects; }