From 21b5af6047a02ab6d65753d52292661415ec9c58 Mon Sep 17 00:00:00 2001 From: Nicolas Frugoni Date: Fri, 22 Dec 2023 14:42:54 +0000 Subject: [PATCH] Add dragging state for leading and trailing thumbs in BPKRangeSlider (#1845) --- .../Slider/Classes/BPKRangeSlider.swift | 106 ++++++++++-------- .../Tests/Slider/SliderTests.swift | 15 --- ...ngeSliderWithThumbnailLabels.dark-mode.png | Bin 7715 -> 0 bytes ...geSliderWithThumbnailLabels.light-mode.png | Bin 8444 -> 0 bytes ...testRangeSliderWithThumbnailLabels.rtl.png | Bin 8392 -> 0 bytes 5 files changed, 60 insertions(+), 61 deletions(-) delete mode 100644 Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.dark-mode.png delete mode 100644 Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.light-mode.png delete mode 100644 Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.rtl.png diff --git a/Backpack-SwiftUI/Slider/Classes/BPKRangeSlider.swift b/Backpack-SwiftUI/Slider/Classes/BPKRangeSlider.swift index 2078480bc..87d882ac9 100644 --- a/Backpack-SwiftUI/Slider/Classes/BPKRangeSlider.swift +++ b/Backpack-SwiftUI/Slider/Classes/BPKRangeSlider.swift @@ -44,6 +44,8 @@ public struct BPKRangeSlider: View { private let flareHeight: CGFloat = 6 private var trailingAccessibilityLabel = "" private var leadingAccessibilityLabel = "" + @State private var isDraggingLeadingThumb = false + @State private var isDraggingTrailingThumb = false @State var height: CGFloat = .zero @@ -100,57 +102,68 @@ public struct BPKRangeSlider: View { // swiftlint:disable closure_body_length // swiftlint:disable function_body_length @ViewBuilder private func sliderView(sliderSize: CGSize) -> some View { - ZStack(alignment: .bottom) { - Capsule() - .fill(Color(.lineColor)) - .frame(width: sliderSize.width, height: sliderHeight) - .padding(.bottom, (thumbSize / 2) - (sliderHeight / 2)) - Rectangle() - .fill(Color(.coreAccentColor)) - .frame(width: fillLineWidth(sliderSize: sliderSize), height: sliderHeight) - .offset(x: fillLineOffset(sliderSize: sliderSize)) - .padding(.bottom, (thumbSize / 2) - (sliderHeight / 2)) - SliderThumbView( - size: thumbSize, - offset: trailingThumbOffset(sliderSize: sliderSize), - onDrag: { value in - handleTrailingThumbDrag(value: value, sliderSize: sliderSize) - }, - onDragEnded: { onDragEnded(selectedRange) } - ) - - .accessibilityLabel(trailingAccessibilityLabel) - .accessibility(value: Text("\(selectedRange.upperBound)")) - .accessibilityAdjustableAction { direction in - switch direction { - case .increment: incrementTrailing() - case .decrement: decrementTrailing() - @unknown default: break + ZStack(alignment: .center) { + ZStack(alignment: .bottom) { + Capsule() + .fill(Color(.lineColor)) + .frame(width: sliderSize.width, height: sliderHeight) + .padding(.bottom, (thumbSize / 2) - (sliderHeight / 2)) + Rectangle() + .fill(Color(.coreAccentColor)) + .frame(width: fillLineWidth(sliderSize: sliderSize), height: sliderHeight) + .offset(x: fillLineOffset(sliderSize: sliderSize)) + .padding(.bottom, (thumbSize / 2) - (sliderHeight / 2)) + SliderThumbView( + size: thumbSize, + offset: trailingThumbOffset(sliderSize: sliderSize), + onDrag: { value in + isDraggingTrailingThumb = true + handleTrailingThumbDrag(value: value, sliderSize: sliderSize) + }, + onDragEnded: { + onDragEnded(selectedRange) + isDraggingTrailingThumb = false + } + ) + + .accessibilityLabel(trailingAccessibilityLabel) + .accessibility(value: Text("\(selectedRange.upperBound)")) + .accessibilityAdjustableAction { direction in + switch direction { + case .increment: incrementTrailing() + case .decrement: decrementTrailing() + @unknown default: break + } + } + + SliderThumbView( + size: thumbSize, + offset: leadingThumbOffset(sliderSize: sliderSize), + onDrag: { value in + isDraggingLeadingThumb = true + handleLeadingThumbDrag(value: value, sliderSize: sliderSize) + }, + onDragEnded: { + isDraggingLeadingThumb = false + onDragEnded(selectedRange) + } + ) + .accessibilityLabel(leadingAccessibilityLabel) + .accessibility(value: Text("\(selectedRange.lowerBound)")) + .accessibilityAdjustableAction { direction in + switch direction { + case .increment: incrementLeading() + case .decrement: decrementLeading() + @unknown default: break + } } } - if let thumbnailLabels = thumbnailLabels { + if let thumbnailLabels = thumbnailLabels, isDraggingTrailingThumb { thumbLabel(thumbnailLabels.upperThumbnail) .offset(x: trailingThumbOffset(sliderSize: sliderSize)) .accessibilityHidden(true) } - SliderThumbView( - size: thumbSize, - offset: leadingThumbOffset(sliderSize: sliderSize), - onDrag: { value in - handleLeadingThumbDrag(value: value, sliderSize: sliderSize) - }, - onDragEnded: { onDragEnded(selectedRange) } - ) - .accessibilityLabel(leadingAccessibilityLabel) - .accessibility(value: Text("\(selectedRange.lowerBound)")) - .accessibilityAdjustableAction { direction in - switch direction { - case .increment: incrementLeading() - case .decrement: decrementLeading() - @unknown default: break - } - } - if let thumbnailLabels = thumbnailLabels { + if let thumbnailLabels = thumbnailLabels, isDraggingLeadingThumb { thumbLabel(thumbnailLabels.lowerThumbnail) .offset(x: leadingThumbOffset(sliderSize: sliderSize)) .accessibilityHidden(true) @@ -167,7 +180,8 @@ public struct BPKRangeSlider: View { .padding(.bottom, flareHeight) .background(.coreAccentColor) .clipShape(LabelFlareShape(flareHeight: flareHeight)) - .padding(.bottom, thumbSize + BPKSpacing.sm.value) + .frame(height: thumbSize) + .offset(y: -(thumbSize + flareHeight + BPKSpacing.sm.value)) } /// Sets the accessibility label for the trailing thumb. diff --git a/Backpack-SwiftUI/Tests/Slider/SliderTests.swift b/Backpack-SwiftUI/Tests/Slider/SliderTests.swift index 919b5cd99..6d9dd27e8 100644 --- a/Backpack-SwiftUI/Tests/Slider/SliderTests.swift +++ b/Backpack-SwiftUI/Tests/Slider/SliderTests.swift @@ -42,21 +42,6 @@ class SliderTests: XCTestCase { .padding() ) } - - func testRangeSliderWithThumbnailLabels() { - assertSnapshot( - BPKRangeSlider( - selectedRange: .constant(-5...5), - sliderBounds: -20...20, - thumbnailLabels: .init( - lowerThumbnail: "BPK", - upperThumbnail: "OK" - ) - ) - .frame(width: 200, height: 70) - .padding() - ) - } func testCanCalculateNewValueFromDrag() { let newValue = BPKSliderHelpers.calculateNewValueFromDrag( diff --git a/Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.dark-mode.png b/Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.dark-mode.png deleted file mode 100644 index 0a0a29e6b5935392af060c6e32dc1ee18a15166c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7715 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 diff --git a/Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.light-mode.png b/Backpack-SwiftUI/Tests/Slider/__Snapshots__/SliderTests/testRangeSliderWithThumbnailLabels.light-mode.png deleted file mode 100644 index 5dfaf98d581d3eb9b005afe24f0f33ca591fe381..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8444 zcmeG?2U}Ciwn+@qMA{KidhZ|t(lH1~Gc*YxMMQcBA+!(-NEJaqiqZrNy@Lco6_6qw z1cZP{4K4H{{cX=V_kQ=>fAHS-@_n;s_RN}DYgV7xiPF}8;S2UOC>ybQef*_vqD!Qmi5piKsXg0F)}euDr-3C#5G_FXVP z=)#}<5D+NB5d{4kMhB>W|Kfo1d(L0=g)H#j&_G`nfvgMvYJ+-yPkX1PvJX_` z9vTn4Kp+O5-vz8`z`Y4{GCQj3{-zc{_~*|Kc=7|~cMTNkk=*^Osz9Bssj6(~2VTqY ze_^A>(&2mMJ!9$Ki@dE!y7%uAHY4ocwTC(=(7^}%DD#->aBG|u`d7bP(5s9LVW*%2 zTQyX)<$b0S;^&X3xO@2lIbpr0uZOj=uCNM68(UiHKd1g42zY^4h zQ$pOI&Oazv5qTm*1_ME8Fd%3MxiCenGW1`s%n&U;pqCv4CR3$>!ML($N&W<5$6$s? zfA<2@XrVL%WDcsqe}S=Q?f%(IgMmT8P)W#j{lCG;_|bo%V5d=Z#qNmctAS&&z3&TO`{D8AKX0JYHDorq6I=FqiG?#tfXVm8A$XDJwW< zx>647(S8&$on1cHkDf8?4g zB^a8hM56}FtV9aZwe_>@DqdZc(4Tn68ms@5O!c}GgltJq`f1>T?O-(9(pER=rioI^ z_gRPNCuc^n45Qy+FnSnFimJs9Qt?F6h%wSw=_l%MfXx2_a6t&LRW*?L%u-rMzZdz6 zZ}~dda-E6H0Ya9Sqx}6|7QGd_+aad((B!%*p1#lCc_xwydWW1nE4!`Co#s(iA6wq) z;^SpEB%zjOxYDETA|xB&liuU+(qzJI%GGSEHp_0OChI{$ufn))(U9?AFyVBqjmlZm z7dyjDS+#x5@{pyK4;f;=!`Kr+kn38PjxPqwkxCBPl*x|>OJ+&(l=lZ&M+NBCpnQFz`Pcb#h{^0e&nR8Z;*Pk2^MA zbh1i5n^Kpd_IqXDl-u0K=S)n$6p+Xo3zR~$x*NgR#>Mf;ql+1pI(Cs0Ea@3urAJzF zA{Hf_VDvsgebT}V$CueaGa&sGHEHWlDe=bj>x)x$rku$pX*QRhUB%Y%P{MO(--YK( z?4G-OpCd3yAczxBn8kCLG_*=1kAbg$=HXlBqM)vrmmj~fV;PaM6_BF@iRzpZ6rK<5 z7A>zxdx03_=^T*!Kx*^0gugwZiIrI5*N4R@%}AI{K7D02_#^7ZR|(yI_;IPcbCLM* zx9ZZq6MD}5XKjOHBy12PV3$dM_y|A(ZVwjoz z79xy&sAh8dsp5$um%rQ5%Lp^9%xa_SYBzi17sq3rmRt+@@gAMF9rW$*Kj!08*0o`a zUxE%6gm$clN4G|&WT$#&+e1qmjjkx|j1`kS7}D7;n&=oL;y0MnKxD9H4G>r=q(vCs zOdXeT6o7#f;?Cir+IH{6dSvf$2xV0)+_5t{^7?!vzz2y(c37l8yz#zUYHVoSQ1St6 zXLtUML++)ov$;2ge;F`L2f#}kdzH*ewB}m7ioJ;s_dlN4cb)d>j|Ja=3PWl1D0y5a z$PB3pMpsSqZ1!)ay7cr1*;EFN5>u7teVG9{wbNb+YM9c*CcCmt8;%JBtR*`X&J-+n(N$B05;5LG_+rV7tmwUS z`N5_RL+Mg69|uJ6v51-e50rAiNM31*XiC5P_{gjEtu9*MCm*tWkeLeeI|q$@x%_Lc z@>>hHYJI10VXMP{&>I7P(Uj4_V8tKGv}u=Y%0@ju=_Qfpz2qVlbU4WGHf1`kgam9S zy;^^E)m0a*dc(5Z$r=A*ICleWAzHiVw}N=pJH8&TdD5`*W^LW(mbtgXGhMOKF{B7Z zM^5ovMj?Y?7rD-nDZ)gIbHbz|GH+UzVQayc>*v{nh}(UnecgO@F+3=3 zRGiGp5&eI#ss6L%qO@YODT!ed$2{SwGf{pm8MBzAz5k)4iSJawdk?oe7$UAv;W^Pv zIEjm)-?1=~>b^H2zp6~}wvYM4<{2AZqVvZ90I%j15Vt1*mKCBCt$n}WqUBc`|ZA| z{mM~A#}TeXZRUGb<<`8<+Ow6tC!Ft&u2oh)C9agWJ2_hNjz8ok?Qv!zH^XDuWR7tE z>4)U?+JnX}6xH|LyL`X%_#V-H`h`HWv3Fwwjb7I|_S~iT(G?AUtRPZWrA1(g#PZHi zVFmiwm)F34Rx7z8Z)s)TRjPvGsD&x#x_dV5=Up8J(qaQ&h&L+^U0Ac5`o5G}30efG zy^z3~0d$vrT+@WQEdP>LV`tA&#eCbl)>m_T-ai`X1_*&x+(_1ezZ94a5TdQEEg0GQwLmT>?W1_JdRXm zsQaq9HuW8W1l;RrdK-cvvaNfk*k@cuZ^26J##Bv<$EC#Tg|@_{a=~j z6E~+)61!}I*q_5!^@P+Zon6?ofLt&2qLoDO`&U=Z#Js_)$kWjBFM|vV5T^wPs~9S% zBp7Nq%FbTR*Nx}H8rum0EUCWBa&pKv@(MJA4l%c7YF6P zETaMd8Y9D>T(XK40W|3dCK;TMj+jiaeTL+9Y9h0FARC(hCr}-x-Q(Xt>QI}XcKgFh zektTO<5E`F1T!1Kj?qT)-YtVWZ4t05U})8InlU(ZUiOvnXxx>TE`<(M^R|x##zK>B z(EA`23z^!hmoBQ`@91#I1NNmdb@B{x7=7zrZEM1qGa|}hYK%v>3uQ9dIbS5dxVGg_ z5GL{-YMsfDU4j7lI*n=6&0FL}P4-P@72ao=by^P-2xYa)7rfSMqOtvjky=3sVwWM$ zfPl@CnEWms4oPdbn~X24_Cb53C~%irA-$rKGd{Ut%>wWE+Mgyg&T}2ku;0)CR7u%M zF9#_7?aLOMw+bl2HdWLXmj&?^{x4%`8ppTo{I>OmkHjo*iLVutn$X5%a2 zt^%r$!3GtQlqMW)sVu@=pCM5!b@eO)A?%U9`rOPMh5GZtilH zj=t`wNKEK=#soi?4pzKGW`tsp<%&Du#rkCa%9uBD3UwruZ#X=KILO?|DA?(*#o_|Y z9tFc@ph1oHJd+h(qAqpr&V>_tX2N?=9pQ(RmWPAOB3?%6-(n}MgJE6J>LeG1YL#ZP z`pxx^9(WbLcAa%OBiFKBK98;Km`$Q(I!jt*+x?D076!6J9S~SVG30xb&d<&K!kOro zfeKHajET!7+sZ(s1&R1m!pE}Hvq8ZiV(FZ>0wq)dxC>BJrDYo>7dEe9UH1zNa-bb) zlnb}@hV<9_iw7Qko>M6w4VrjM0?8y}&&qrkC8h{57E(Ov8;-s}U$;NlC_G0mv-^3W z%zCV=v1qS$-#Qp04WyUY$k~3mV9O0lD(qADo%*~V!}h|jI6SsbK5fSE^?iGu_hXD8 zOtT4OB72O8KvTZ5faSZty5*f`a{EOOj82OWOn7yFPSG2;h#eG%vz;Sru_Mk5WPZFD zOhBw?BSN}pGS5O;;sL}XQ&`tj=otuNdN;l72`D%RsN7e|@BXSfeG?L0DGD${v_*zV=L5O4PG@pY>BENWvwL5Y zgtFaY4hE-v0w?Vzrd{+drwM*}9p$NYI3hlZS`Grb7mJ=`Chc@pz9q{eEXi$)=u{*J zid^f^oS-{g=uT<9QAlLNS`kfedrrs3jpFEzoz9qEzK-`~3NPO;Kb^Z(WU=~rNC-4FAs~IA7?Qx4YVxq&Pu!uwW9H8E$bRMAxA0GV`qe?) z+`NM2aC#5%Xx_(fdvp(7&Z5ISgS{9yS|jfPJa_|zNZg{+cokqyHNxXf-;=*SlTyQ2J)=@fvY6@0z?fh|}jKX)XT3U9g~3*VCD zFna6AlWLS*fj?OyIH$aQgRZ#JXK^04D|E8ZOTR=>!m+pPlnw4uXuDTCb7X`ZlKJZSNxJFdQVpWD^awsLsEWT#WQx z7(JX=KzXbuD4|h+R0CpMz(FHCNQAc$+Ns9d_9Jetx-}bb_`x>Xr6PNhu0T)bs)zWa z$ML}OoUMzkOSra7qqiGu^0(t7xIf&HS$9@+nc18)&`0p6qs_(q;@N-*-}JiYg__oy zkGjK2Gqe|Nx|grM79-^2%EFhHTA;V1-ndZFESsY7DB>^A#4xLCf%q_E)+;nINf;V> z@_ozW!0T;3O*ij2Lx0#}fCOziWi9)SN)14e@m509ziH@0uOAZb_>AO6<-2GX4luj( zhIk#0QLxTygTTGgw@O5!>FcPb+oz8cWr%0iL9JNctO^kZy>T~0Ubts(Q^_+2pH5yG zUlyvPgS*WiF%N5M7=9=|kz`ibJt#Ym!9I|%+1y@r4?~x-P@pW)mDqLJUw8eMo1JIE zPD{g^8Uk-9G#w;ue(LzqUk#b^=_j>1wn#$zvXJA~&vZYXNiQ}02-t|Q!Z)xXR?F9k zDO8GPf@wWUG5KPIr8$7`G9P;mkJ@W?~1&;_vK~tS-F0RegRUUt3rGz z^GWhN2y(O7wle zd};}Xn2y(oW<|Ikv48G2g#CrY3R2)j0`9$kW6oLO%uIIteI$-v?-WZ<8r!r}KX4Cr zfHnvg6lnaVg$OPJI-Z0Dm;WX0UxON;rs{^}M-FqIA;MWcb@cQNR9-~xe|FmY|>{2+4iS8H< zMwecP6blYeK}@3@6hiSIW%k0|=QzyC>jekWAcA=8^x;ERm0qg!-*hh_vf?o-=}{zx zg!>jliw%L>!A~l&z&--=hOHrt{8=OEV{mZsA}tf0GhyREP>3{*DPeQtyxh?1CNOO~*6U`)`E+siNvH7zfO`UH+z;=-LRK z6+2iZts1s`G|07`oSfW3eLgTn?LbZU$2c#Ot@Ba0@U}oigg~?Gv@@tX5O5vnwsIM< z#7Ul;bWDmIeCQX`+uKk4W-=tkjqX;!Z?)@kB~UNVo!~BCO0SCroud8>&2H_DBRoE+ zxO!F1*{ZU#*TmL&+ca{ACbqG4IjG0F9AtOn4G6L#i@SE5%)7svV#587(EpbDw%?JV z41p=4~_~_sskRC8ky+Gf8jGh0n8|T$4-gq!`$LDsQNSckALZI1p z>-!zHN7O+%basRg=G34(e%e56}dl_Y(4LqwpwfIr9pQWB@V>Z}%Jo&DT5|q$bs6#TD-adnXcPhc;`WM9 zk1wlWKDA)rP=e6Ha$8m$NsD;9g3{Z2(|zHOA&t+nJT1;-_rgICxofdiH+h3`^P=FG zLOsMgoTEC#XM4BBP|a{QUkR>YtF3VG2DRsC663G9ZadkIJWgKk3TXN>(J;ORwxT2-n|>o$KcOz%n+I5;_-u}1b{S9bA zg`=LX&0ap8P%*`uS0%ZR^D{aE3eQGSNB52$ELq-L&lTKvEu=1f*f!ikV$b!N0b<65 z!MMe+sq4mJczj%kvnOllV%&ud!Wb#@3)IQ8q57-imG;iY$L7bTUj)RB%$$Y=b@x85 z7^`%h3hIuVe}xbXIKwh(0nPP#Iq+iKzN^74Q#7;iRayScDnaop28fSzcj*nuKNjyd z?hjt4%>9&GZM|hUyzLN>hrA|-l+*E>w^8p`K`kyQ2s%8n);!CSPjO3B$BVu`T zjNWLm4`%&mC43ofA^Vf~IY1ja=Gyf|=*#9yim3=W(pN{w9R+g= z_^qv^va1eUVk>oIexozBo=J55DCQvwoGPYyfE-!-Xm=_FmO2U7K#;eOI0%18E&Vo7 zNVTQKm}Z36?P%LcFZZ~G$Y5<7{@FUNQ5M$h0EF^Ezw(1ba!DTF!n<${soRcs3Ydb{ zj^FdfBF*q(jmn*ivT&K=m0ctM9IMd3qy?BhOHZWYP4*l2LUg|vhR8X@xL+RHs^m>~ zbeKt}n~{R10(RW%@{3yn;`wB3x`4vX!=i%4OiCmWVSD)vKr?cm{0}B z0HZMqehV*PsWrq;64LU%9W^=lKB`s_Sru^JaitZ7tNi|eim?Rrdiwk9wLibg{{PVb dZf=~D@)wz_X*UOR0e=PnX{za{mfU$1@;`_m=IH{8Zd(t?z(`$XMNmOM^D0pBw0f*+t*Hs(2g)!I6wC-B`%MBQIWW_Il^=j_ zfiC>j4grBe?Lg3fXtaR*_Y(`G-(&vHFQkM2p$6L0A^%AY9!$URpJh<*?_r;n?(GBF zB^MPVBnZU7{X2nGb#HD0jm&oUwSUhR5ct<)4ZLpw>30sKE1xz~KR*F-N7efZdY<65 z6rV^lC6>+{Mp|6d1L}_}Y$4gjL&t~rqGIF^JKGM!3ftPQDWzkc2H0lX+Hu_a$WN>A z5UhY;fBQwIOplEAHRNL6cB~qxoa9j%GwV?~d$8__Ho?zH;`?V4MDWE2Ge;UFKqdL8 zuNN;ajg!XrCip~hB0vxte-M;CHmT{)YGf?_2>o9R!8}{a`4~AjtN406+ya zu&3|-)k@=!0D+;RAV#Bq$Y8g8|KUXg^icahVE8>4U=C4Z`z-+&3#CCIE~LLD`&)>= z|1kMKWB*^o|NVuEy8|()h{?k+k&hK;t?Tw^&E-Ug|InW1BVjz$Pa;CD--sL1{=R?j zq5Qi>dBBX$<~viJ+9%tRjfN#2t-4LdL?g)-B}F*=K2?5GDl>*fA(6(MZ)u zB7>YSIz^HFl_@wRW#;?3x*Xc&D12Aq5_`JqaebUY4`HN)ycS);` zVD`Ur>}y&>qw#J~s#&TY%b))qcH@FcBi1Eg{b2tQImw*mWzyIyw}HsxnSslKHQ}xJ zLaCxy3x_Tov9ZBsh&WKaWJx$CPfOLkeWJFdxlIzX?Tl;RT&)+$IVO78!~}*~W6DS; z*pAUlcq(_Rg=fwao8P97SAve$#~-4Gm+K8oG`H?yxsnyqH36-a{`mGBVnuzP$&%ox z)$jhWU*oK>;a8E=y8DTfiiHYvlq%vpT@Iy=hM*iTEn-)5;Yw6I9=RAVyZ=;7Ec<@3zAx}# z%+5o%ax2G+=;+Gk!*#r;z{FI}W9fenC3cP94o*ZbN9d&RsH^?RoZdtHrLCi_3*wwMO&al+1T*o>)vKp_{w z&{6+pyK3m0%g0i`A`CWkYn81{Ftzx!_i797H6+hwQmFAnPj~HYMm4hy#wu>Ji#{y5 zG}<|p0+Z7Wba(;JrzQ%HOd6>Ks_r$z!95}GUM^4FabIa36aCV@ z$2-&SvF%bb4l}g2Z`j;tB^8^14V5S=aT|jeQn0{_lj9s?G|TSmWWAJ5MIn!mmYDic zIH?bYPpqSq1N8f3P$_0jdnlzCFQ|5d?dbu+r{h1--d>{lGo9Vlz~KFl4`w0V%_>PH;m0_jjZNYV2}2fPE`;%YGk9l z%=pSXrRb9Eb}F{IwsW~p`BVw2ni`dC&r?tG0?o+R%f+L!SEu&Nbu)WC`mhZZci(g* zIF_bdD=*whdVMfD7+J&P)y{juJ0N8>mVen#Wv<+JtVV0=kEBdltdP0cI_3M@2$OTE z0!?9N`GnqWl(zxGXY5MO#Z55e7cXGo^!!}uF!h zawp{5hz9d$q7$PX^*;PWX|cD&0k1?No@V}-`rh5q{msJqb0MiD;kBK%IsI{eq4FcY zYrKUFX7S(lXQf|gtiD%d#md$fsi;om@u9o6=S84F01}YTj`U}}8Np1X)1jUZ53no8 zTb>-HIq(!c4fGk(wPiw8&qjapC_U0>es8pl817h0n{qNs3tU7JWN})BmJHZTS>Jr( zp+-qUD^~ogku{kfc128n#oIN=A6Qf|I~Q~QfHij3Z7-|vN|%Y-Zj^?M=bm?^z4vOs zd-H5->aMXj#woQ-PRkQwD^ytxVdY7EHWYJDD@`p9%E8NX~bX zLY>W3RCq?zOP?>xU)ZGZY+A#D0jMFt3z?w_kzdXvo3P4{|y; z0-OS^RZipIN6q%JHyRzi5l-sv*-;ajIqvc#>}Pz~kap==;4m6}8Y0$xyDX@zIj*zJ zUb=GWQg{!SX9>Zh)AFREdX(s!aGTw0O~?S3dDy(nw7~uwa`JN(O*SQnYdUqmp-EIQ z|Fim+#e2#Pw(nG{`_DZ*f4Cgi-}AbnXAo!Iv%^xwjgy8`fAtuCJAs&UH$O&2e)Gi* zSo=8O8$3)W5?=Gl+wdguO`dn~V43(QTIqeWF7{74Nn^)X&fH6A)hUgPm6UBIVk=)+dtMVqUvR(gciGxZmM2$ z%PqsZAuv|YYR`5&gymx|gPDMM@*ucM7j_3xNxtGFXqsNT#5LCkzryuz(6dctS!_;( zun5H0U`hW5FSCJ`S9_2FPEV5(AKUzURH8)exS7qhl^Wtzd#``XYm>T;x2vRdXEiZp zIyW6%A|K|k0AF-J@Lz{e-xF`Wd;Q;#r%2Fit3I+h-@*~bX6XN9&$p}d zUx9$|OuKvoGFtfhW2M>uj_m5)o|VGIx&-`{3a`l(fLaM;qyK}25LVic>}&SQ?j!X4 zBE_9=<_O=@AKO<~T>UtF1$CRbwgm zpILE*vwcrFpDAEAX@na9>` zEQyuhhHg^!Zr+?%^WeLg%W-aBPp`MoA4KvU&GyxC>hF5m}{JcEWSp4=8ITz|Cuhs@-K&|O~O^|0QIgv|V zIg@{2p)gTQ(=Xuc{p;7qm-4`=okr#N!JCw#9?5J-AL7V&|0!6vM3nL|M_VF`AXhUa zoTavoh3_?c*vp4EnK_CJnZIUdKXW#h~Jj+{$HGTxY zyd8{XmHHEI!;%Mo%>E+)1R-#|IUMA2$rx^!^)siyZm{L64WCPCb(T``xEzj-ZMG}R zu^Qb+MMhf%_+JAK0`V#fol*fdb9L9{&VFotqO02;1%L&g=VjK6`7Y6(gDi04HJpe9Jzisg}1O$YR}u zTK=5q=A1Vn_@2ASd-cI#kF@=K)`0MV!CC$R@QDe)CrZ{F8q8jI&+s7Ydw!|Ot3<{w zp9(m5-EeLB4u&Su9cFJ_S+QQ0XT{izoQqtc0|^7$N4P~INlTO)Pn;+WeK?-!Vf~(9 zU6^zj+4A@VUS3+QJQskt0hsaKg&+)VfGBNN_~~@H{gV%3vT}~{1n&cv942=gz4u;(O$Znk1l5SmDf?l!T$AklN);p>a{qY7 z)4{i7*!g(l>&X<*T>9P1pr3aD&6%E>LF}rO=r-Oif6mNnr~Whkw#DVvZxwzsA?5aG zZNAcq#zeKXyd!6srw=+DuXjv$?#Ez@Jo3}3HjEcNuR;<4jfhafmK|==@an6V#d!+d zFmW^Z+~B@Cd|Xpe!El_v)qql+J1#~)Gl3f$o##!8?@XMAB9FG(13iExA-Q}VyF_EF zMsQWEq)>Tk`_yY|p*?-CC79CJ5IYe4h-p0a{?zf?*pJz5aLuN6!Nf4%yYfq=N4FU| z$oh?fsJQL|9>CQIw&x8hl~ z7f?Ny+qjo1HzGG}*s0<$7SdLxrIPP=Ny7pAAg{-V{)7|Ps~ygp+!MjepdAl_NSV#; z!l7Vw!dWgyUXX@F470`MTC_ZyT&4XE*V4r^t?cNb;ujfOD&+bZ_o_ZD3A^;)6}+xb z1Gs{8%f8n+nyO};nPT+)&$8lM`*F$Z`tgB5ZiDz--Lbf7jo{H^L#s^wzP8ylAtAVR zA!Xptb`8JG33 z1TL0wOjR2vBet&llLju#F$9^Z(DIEFV4xIa2ahako4cKpcUPvdjLt(&?9};TG=F+U zsqkWr` z0)L}A-37@HSZI!A=6f`B;Y+GP8r;DigBNWd33}|CiLo^f{_eDskydDiw%+eHka&6H z((%3`2)swv{rW8Is?RGCb-~ocn7YQA=Fa<$(`>yprl+eJUoIbrP!oXLIW%;yq;i~9?-B=cDv3S8`IV#!V zMXq8W+fiH(1aHb2z%mD@W{%T1Odh5GHpE%1&=#4duHN&cvvqdBH&anC>A8u_wM1gy zeHY=MubX-~fhedHlK<-W9Hb7a@oAJ(`e{6wB|`a%$hrhr|B{7(XY6g@REwLesu0v# zgTG?(+jz84b`o<$jZ5_ZUhx=VRjdDru|w=v&E?Ni97#WBP@*e1CU88&dw#*#^Pp?U zWpfbMdM-X^-51;3Q`ktqU+-~i&3CVFt_J^uY5wbl!r*KBjg05}+s&J&bA~MwtUmHs z3U{n5TM+4`{{AfLrbF$C{Ma!r{lJ@8&lci%fY!_Jtf{ns?>gi-+&y`o=TP9Vag=_r zk<{ZhCYg>@zz6kHr*KIbuGI}menEy4Wd>xjn7^5ROI~wzAp0Lex2FzBRcqg0a)w!6u{_suatMRz`F z#ayyX_cuVAi<6ZlDm$orOKHUAA-L1WWL9Pq$;&CqXn+aFk&Y-=lmQAUUQwwh^tT|1 zF?TK}WzY;l&V4Om;=d^EAA`>{_U~1}Y_Y$(R+v}x(_yw-^zeICWUyP}v`4gq1M;T& zs40W=n((d&|7GckZ%7ch?^hzLUa;HMhu{S}9<}>>xXU}Ayv#jY4bm-U&1RPp^MGlE zJ3;k!J}0=1O9K1Xi{%QPrf&hD)wQk5rmIo4k~&u(RvgiVHO>^W4QlxXD8+P{7#mZ_ zpWb^ZpDwGS^E}DnL;mXR(ylCK)=UuoRUue#2e=B|qwQR%({YRMQgPS~O5Xhw-P6-E zAN;caxyg-g_|$dzC>6OcF*`)5J1*-|kll^HL-UOjgZN33!Zsau_()63(~2wa;~ja@ z&(Nl|M4F~*B5bhH27n#-73(#V#K{qhr*Fej<^AMNf2=;5(*IPVTG8F1(AYJMf&p6v zx`Gn{-~rNIWM4CU_MOkjy?(LI!?{q(sk8J7hj)%!n~vRA-iIPPu2E!K0hfS%QZneM z2(mJqOg4Z0N$ROY62D$W7Z0FsXLdEb{L-@t%H-N;(3ua9zrT01Q%A!X_kPV2Q+;J+ ze18a*jc^`XZWZWIOh689Iu<}E@R7HvGz8v&AjW!CuWkqg45d_UIqQ$lM&-TP=)P9_ zOD)2|Hdl^YEf>+3#@sg2&mh5cseEt4UA>hcZ!Eg@my z5Fa$Er1X<1;C%_X12u((KY7w!Sm)cG8^Wl7iwhRIKWa5o5h?z;@9c9G@dL?}FHe8A zjVkH+=58pA*$7|JQQ;!Pe}ENo+_?dPtvr_){{9h4cvlM*El|`CCuFi*n(Q8-d_?~+ zJnL9=>x0nNjLrI3RxnxrgV#b(9^igFg<0L0F%V()G$v0+_6s}9cUf6K5B}C_#tMB4 z)V)f3d;5B|sbx82zMRla7dV{*#~n#P&d66k z7T@A9E6-sH8CB*_-7m)+`lMAy{FlIcfIuo`<0(jhL~-Xpr#@=p=4VD-OcTqIt=x=> z{+mj0#&4(dHS>S7y8v`BLUp-OF#&IwmhhmSsq;zQvy3Gj&6p zMv$O>K3em8mal+MIb4%)Yk@vcU1uD|gykxhz0g|_m-pk5IoQwHToK`I6;G3(ZP@KH z9gJPe@?a(AADe8fijXpV0mK}Yr&XRWSLRKtO?fRj3Tgs#0PgK;#L&#L3Xr(Ta?Mb; zMK#feVio$Qf?sl3xr6BL=i3aV=9`g_BzyX-w#SY+nt3u~@wpb%+y{9wR!Ba|WcBbr zJeIWp%av6Wu}>D=6Wgsm1G3=lj#C7e>yczzca|-`C=fM_|e#kKS0CKm%%W}z%{ew zhGEK9>w-FiHYL|zlaBiD2{#6pnI~;k zqh(4Dc_PIwqgCAz{8O1opPQP5raXKvCh)I+fcXVt#yvUJ+ z7o9K59Whx-2%-I3TX%qcbcbud%fIQ)B{}*>mk8-%4U#II1Bot~pMsHUK@&8#z&?hT z&cE-4wRM~M%T5;87Wg!*RkBhI>zrU!s|JYcQk4?`sWAffof0?o0ms}<~jP&6;A|K zWv2bE>o3|dLxcccCPC^WBV4gOORg5$0}FS37~}1|O%vvxi9z8&ulV*4j0nVTp<<$c zW^IOLG0{m{oazGm;O~Q~Qk5w6U;j?gfL)`XMcDlH=k@=){%^0wDchoe$qD}^k{7sK O0I4cz-7iqIeElCIb^ay*