pintura-old.js 1.3 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520
  1. /*!
  2. * Pintura Image Editor 8.13.1
  3. * (c) 2018-2021 PQINA Inc. - All Rights Reserved
  4. * License: https://pqina.nl/pintura/license/
  5. */
  6. /* eslint-disable */
  7. const JFIF_MARKER = 0xffe0;
  8. const EXIF_MARKER = 0xffe1;
  9. const SOS_MARKER = 0xffda;
  10. const Markers = {
  11. [EXIF_MARKER]: 'exif',
  12. [JFIF_MARKER]: 'jfif',
  13. [SOS_MARKER]: 'sos',
  14. };
  15. const JPEG_SOI_MARKER = 0xffd8; // start of JPEG
  16. const JPEG_MARKER_PREFIX = 0xff;
  17. var dataViewGetApplicationMarkers = (view) => {
  18. // If no SOI marker exit here because we're not going to find the APP1 header in a non-jpeg file
  19. if (view.getUint16(0) !== JPEG_SOI_MARKER)
  20. return undefined;
  21. const markerTypes = Object.keys(Markers).map((v) => parseInt(v, 10));
  22. const length = view.byteLength; // cache the length here
  23. let offset = 2; // start at 2 as we skip the SOI marker
  24. let marker; // this will hold the current marker
  25. // resulting markers
  26. let res = undefined;
  27. while (offset < length) {
  28. // test if marker is valid JPEG marker (starts with ff)
  29. if (view.getUint8(offset) !== JPEG_MARKER_PREFIX)
  30. break;
  31. // let's read the full marker
  32. marker = view.getUint16(offset);
  33. // read marker if included in marker types, don't
  34. if (markerTypes.includes(marker)) {
  35. const key = Markers[marker];
  36. if (!res)
  37. res = {};
  38. // prevent overwriting by double markers
  39. if (!res[key]) {
  40. res[key] = {
  41. offset,
  42. size: view.getUint16(offset + 2),
  43. };
  44. }
  45. }
  46. // Image stream starts here, no markers found
  47. if (marker === SOS_MARKER)
  48. break;
  49. // next offset is 2 to skip over marker type and then we add marker data size to skip to next marker
  50. offset += 2 + view.getUint16(offset + 2);
  51. }
  52. // no APP markers found
  53. return res;
  54. };
  55. const APP1_MARKER = 0xffe1;
  56. const APP1_EXIF_IDENTIFIER = 0x45786966;
  57. const TIFF_MARKER = 0x002a;
  58. const BYTE_ALIGN_MOTOROLA = 0x4d4d;
  59. const BYTE_ALIGN_INTEL = 0x4949;
  60. // offset = start of APP1_MARKER
  61. var dataViewGetExifTags = (view, offset) => {
  62. // If no APP1 marker exit here because we're not going to find the EXIF id header outside of APP1
  63. if (view.getUint16(offset) !== APP1_MARKER)
  64. return undefined;
  65. // get marker size
  66. const size = view.getUint16(offset + 2); // 14197
  67. // Let's skip over app1 marker and size marker (2 + 2 bytes)
  68. offset += 4;
  69. // We're now at the EXIF header marker (we'll only check the first 4 bytes, reads "exif"), if not there, exit
  70. if (view.getUint32(offset) !== APP1_EXIF_IDENTIFIER)
  71. return undefined;
  72. // Let's skip over 6 byte EXIF marker
  73. offset += 6;
  74. // Read byte alignment
  75. let byteAlignment = view.getUint16(offset);
  76. if (byteAlignment !== BYTE_ALIGN_INTEL && byteAlignment !== BYTE_ALIGN_MOTOROLA)
  77. return undefined;
  78. const storedAsLittleEndian = byteAlignment === BYTE_ALIGN_INTEL;
  79. // Skip over byte alignment
  80. offset += 2;
  81. // Test if valid tiff marker data, should always be 0x002a
  82. if (view.getUint16(offset, storedAsLittleEndian) !== TIFF_MARKER)
  83. return undefined;
  84. // Skip to first IDF, position of IDF is read after tiff marker (offset 2)
  85. offset += view.getUint32(offset + 2, storedAsLittleEndian);
  86. // helper method to find tag offset by marker
  87. const getTagOffsets = (marker) => {
  88. let offsets = [];
  89. let i = offset;
  90. let max = offset + size - 16;
  91. for (; i < max; i += 12) {
  92. let tagOffset = i;
  93. // see if is match, if not, next entry
  94. if (view.getUint16(tagOffset, storedAsLittleEndian) !== marker)
  95. continue;
  96. // add offset
  97. offsets.push(tagOffset);
  98. }
  99. return offsets;
  100. };
  101. return {
  102. read: (address) => {
  103. const tagOffsets = getTagOffsets(address);
  104. if (!tagOffsets.length)
  105. return undefined;
  106. // only return first found tag
  107. return view.getUint16(tagOffsets[0] + 8, storedAsLittleEndian);
  108. },
  109. write: (address, value) => {
  110. const tagOffsets = getTagOffsets(address);
  111. if (!tagOffsets.length)
  112. return false;
  113. // overwrite all found tags (sometimes images can have multiple tags with the same value, let's make sure they're all set)
  114. tagOffsets.forEach((offset) => view.setUint16(offset + 8, value, storedAsLittleEndian));
  115. return true;
  116. },
  117. };
  118. };
  119. const ORIENTATION_TAG = 0x0112;
  120. var arrayBufferImageExif = (data, key, value) => {
  121. // no data, no go!
  122. if (!data)
  123. return;
  124. const view = new DataView(data);
  125. // Get app1 header offset
  126. const markers = dataViewGetApplicationMarkers(view);
  127. if (!markers || !markers.exif)
  128. return;
  129. // Get EXIF tags read/writer
  130. const tags = dataViewGetExifTags(view, markers.exif.offset);
  131. if (!tags)
  132. return;
  133. // Read the exif orientation marker
  134. return value === undefined ? tags.read(key) : tags.write(key, value);
  135. };
  136. const backup = '__pqina_webapi__';
  137. var getNativeAPIRef = (API) => (window[backup] ? window[backup][API] : window[API]);
  138. var noop$1 = (...args) => { };
  139. const FileReaderDataFormat = {
  140. ArrayBuffer: 'readAsArrayBuffer',
  141. };
  142. var readFile = (file, onprogress = noop$1, options = {}) => new Promise((resolve, reject) => {
  143. const { dataFormat = FileReaderDataFormat.ArrayBuffer } = options;
  144. const reader = new (getNativeAPIRef('FileReader'))();
  145. reader.onload = () => resolve(reader.result);
  146. reader.onerror = reject;
  147. reader.onprogress = onprogress;
  148. reader[dataFormat](file);
  149. });
  150. var blobReadSection = async (blob, slice = [0, blob.size], onprogress) => (await readFile(blob.slice(...slice), onprogress));
  151. var getImageOrientationFromFile = async (file, onprogress) => {
  152. const head = await blobReadSection(file, [0, 64 * 1024], onprogress);
  153. return arrayBufferImageExif(head, ORIENTATION_TAG) || 1;
  154. };
  155. let result$a = null;
  156. var isBrowser = () => {
  157. if (result$a === null)
  158. result$a = typeof window !== 'undefined' && typeof window.document !== 'undefined';
  159. return result$a;
  160. };
  161. let result$9 = null;
  162. var canOrientImages = () => new Promise((resolve) => {
  163. if (result$9 === null) {
  164. // 2x1 pixel image 90CW rotated with orientation EXIF header
  165. const testSrc = 'data:image/jpg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4QA6RXhpZgAATU0AKgAAAAgAAwESAAMAAAABAAYAAAEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////wAALCAABAAIBASIA/8QAJgABAAAAAAAAAAAAAAAAAAAAAxABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAAPwBH/9k=';
  166. let testImage = isBrowser() ? new Image() : {};
  167. testImage.onload = () => {
  168. // should correct orientation if is presented in landscape,
  169. // in which case the browser doesn't autocorrect
  170. result$9 = testImage.naturalWidth === 1;
  171. testImage = undefined;
  172. resolve(result$9);
  173. };
  174. testImage.src = testSrc;
  175. return;
  176. }
  177. return resolve(result$9);
  178. });
  179. var canvasToImageData = (canvas) => {
  180. const imageData = canvas
  181. .getContext('2d')
  182. .getImageData(0, 0, canvas.width, canvas.height);
  183. return imageData;
  184. };
  185. var h = (name, attributes, children = []) => {
  186. const el = document.createElement(name);
  187. // @ts-ignore
  188. const descriptors = Object.getOwnPropertyDescriptors(el.__proto__);
  189. for (const key in attributes) {
  190. if (key === 'style') {
  191. el.style.cssText = attributes[key];
  192. }
  193. else if ((descriptors[key] && descriptors[key].set) ||
  194. /textContent|innerHTML/.test(key) ||
  195. typeof attributes[key] === 'function') {
  196. el[key] = attributes[key];
  197. }
  198. else {
  199. el.setAttribute(key, attributes[key]);
  200. }
  201. }
  202. children.forEach((child) => el.appendChild(child));
  203. return el;
  204. };
  205. const MATRICES = {
  206. 1: () => [1, 0, 0, 1, 0, 0],
  207. 2: (width) => [-1, 0, 0, 1, width, 0],
  208. 3: (width, height) => [-1, 0, 0, -1, width, height],
  209. 4: (width, height) => [1, 0, 0, -1, 0, height],
  210. 5: () => [0, 1, 1, 0, 0, 0],
  211. 6: (width, height) => [0, 1, -1, 0, height, 0],
  212. 7: (width, height) => [0, -1, -1, 0, height, width],
  213. 8: (width) => [0, -1, 1, 0, 0, width],
  214. };
  215. var getImageOrientationMatrix = (width, height, orientation = -1) => {
  216. if (orientation === -1)
  217. orientation = 1;
  218. return MATRICES[orientation](width, height);
  219. };
  220. var releaseCanvas = (canvas) => {
  221. canvas.width = 1;
  222. canvas.height = 1;
  223. const ctx = canvas.getContext('2d');
  224. ctx && ctx.clearRect(0, 0, 1, 1);
  225. };
  226. var isImageData = (obj) => 'data' in obj;
  227. var imageDataToCanvas = async (imageData, orientation = 1) => {
  228. const [width, height] = (await canOrientImages()) || orientation < 5
  229. ? [imageData.width, imageData.height]
  230. : [imageData.height, imageData.width];
  231. const canvas = h('canvas', { width, height });
  232. const ctx = canvas.getContext('2d');
  233. // transform image data ojects into in memory canvas elements so we can transform them (putImageData isn't affect by transforms)
  234. if (isImageData(imageData) && !(await canOrientImages()) && orientation > 1) {
  235. const inMemoryCanvas = h('canvas', {
  236. width: imageData.width,
  237. height: imageData.height,
  238. });
  239. const ctx = inMemoryCanvas.getContext('2d');
  240. ctx.putImageData(imageData, 0, 0);
  241. imageData = inMemoryCanvas;
  242. }
  243. // get base transformation matrix
  244. if (!(await canOrientImages()) && orientation > 1) {
  245. ctx.transform.apply(ctx, getImageOrientationMatrix(imageData.width, imageData.height, orientation));
  246. }
  247. // can't test for instanceof ImageBitmap as Safari doesn't support it
  248. // if still imageData object by this point, we'll use put
  249. if (isImageData(imageData)) {
  250. ctx.putImageData(imageData, 0, 0);
  251. }
  252. else {
  253. ctx.drawImage(imageData, 0, 0);
  254. }
  255. // if image data is of type canvas, clean it up
  256. if (imageData instanceof HTMLCanvasElement)
  257. releaseCanvas(imageData);
  258. return canvas;
  259. };
  260. var orientImageData = async (imageData, orientation = 1) => {
  261. if (orientation === 1)
  262. return imageData;
  263. // correct image data for when the browser does not correctly read exif orientation headers
  264. if (!(await canOrientImages()))
  265. return canvasToImageData(await imageDataToCanvas(imageData, orientation));
  266. return imageData;
  267. };
  268. var isObject = (v) => typeof v === 'object';
  269. const copy = (val) => (isObject(val) ? deepCopy(val) : val);
  270. const deepCopy = (src) => {
  271. let dst;
  272. if (Array.isArray(src)) {
  273. dst = [];
  274. src.forEach((val, i) => {
  275. dst[i] = copy(val);
  276. });
  277. }
  278. else {
  279. dst = {};
  280. Object.keys(src).forEach((key) => {
  281. const val = src[key];
  282. dst[key] = copy(val);
  283. });
  284. }
  285. return dst;
  286. };
  287. var isString = (v) => typeof v === 'string';
  288. var imageToCanvas = (image, canvasMemoryLimit) => {
  289. // if these are 0 it's possible that we're trying to convert an SVG that doesn't have width or height attributes
  290. // https://bugzilla.mozilla.org/show_bug.cgi?id=1328124
  291. let canvasWidth = image.naturalWidth;
  292. let canvasHeight = image.naturalHeight;
  293. // determine if requires more memory than limit, if so limit target size
  294. const requiredCanvasMemory = canvasWidth * canvasHeight;
  295. if (canvasMemoryLimit && requiredCanvasMemory > canvasMemoryLimit) {
  296. const canvasScalar = Math.sqrt(canvasMemoryLimit) / Math.sqrt(requiredCanvasMemory);
  297. canvasWidth = Math.floor(canvasWidth * canvasScalar);
  298. canvasHeight = Math.floor(canvasHeight * canvasScalar);
  299. }
  300. // create new canvas element
  301. const canvas = h('canvas');
  302. canvas.width = canvasWidth;
  303. canvas.height = canvasHeight;
  304. const ctx = canvas.getContext('2d');
  305. ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
  306. return canvas;
  307. };
  308. // turns image into canvas only after it's fully loaded
  309. var imageToCanvasSafe = (image, canvasMemoryLimit) => new Promise((resolve, reject) => {
  310. const ready = () => resolve(imageToCanvas(image, canvasMemoryLimit));
  311. if (image.complete && image.width) {
  312. // need to test for image.width, on ie11 it will be 0 for object urls
  313. ready();
  314. }
  315. else {
  316. image.onload = ready;
  317. image.onerror = reject;
  318. }
  319. });
  320. var blobToCanvas = async (imageBlob, canvasMemoryLimit) => {
  321. const imageElement = h('img', { src: URL.createObjectURL(imageBlob) });
  322. const canvas = await imageToCanvasSafe(imageElement, canvasMemoryLimit);
  323. URL.revokeObjectURL(imageElement.src);
  324. return canvas;
  325. };
  326. var canCreateImageBitmap = () => 'createImageBitmap' in window;
  327. var canCreateOffscreenCanvas = () => 'OffscreenCanvas' in window;
  328. var isSVGFile = (blob) => /svg/.test(blob.type);
  329. var getUniqueId = () => Math.random()
  330. .toString(36)
  331. .substr(2, 9);
  332. var functionToBlob = (fn) => new Blob(['(', typeof fn === 'function' ? fn.toString() : fn, ')()'], {
  333. type: 'application/javascript',
  334. });
  335. const wrapFunction = (fn) => `function () {self.onmessage = function (message) {(${fn.toString()}).apply(null, message.data.content.concat([function (err, response) {
  336. response = response || {};
  337. const transfer = 'data' in response ? [response.data.buffer] : 'width' in response ? [response] : [];
  338. return self.postMessage({ id: message.data.id, content: response, error: err }, transfer);
  339. }]))}}`;
  340. const workerPool = new Map();
  341. var thread = (fn, args, transferList) => new Promise((resolve, reject) => {
  342. let workerKey = fn.toString();
  343. let pooledWorker = workerPool.get(workerKey);
  344. if (!pooledWorker) {
  345. // create worker for this function
  346. const workerFn = wrapFunction(fn);
  347. // create a new web worker
  348. const url = URL.createObjectURL(functionToBlob(workerFn));
  349. const messages = new Map();
  350. const worker = new Worker(url);
  351. // create a pooled worker, this object will contain the worker and active messages
  352. pooledWorker = {
  353. url,
  354. worker,
  355. messages,
  356. terminate: () => {
  357. pooledWorker.worker.terminate();
  358. URL.revokeObjectURL(url);
  359. },
  360. };
  361. // handle received messages
  362. worker.onmessage = function (e) {
  363. // should receive message id and message
  364. const { id, content, error } = e.data;
  365. // message route no longer valid
  366. if (!messages.has(id))
  367. return;
  368. // get related thread and resolve with returned content
  369. const message = messages.get(id);
  370. // remove thread from threads cache
  371. messages.delete(id);
  372. // resolve or reject message based on response from worker
  373. error != null ? message.reject(error) : message.resolve(content);
  374. };
  375. // pool this worker
  376. workerPool.set(workerKey, pooledWorker);
  377. }
  378. // we need a way to remember this message so we generate a unique id and use that as a key for this request, that way we can link the response back to request in the pooledWorker.onmessage handler
  379. const messageId = getUniqueId();
  380. pooledWorker.messages.set(messageId, { resolve, reject });
  381. // use pooled worker and await response
  382. pooledWorker.worker.postMessage({ id: messageId, content: args }, transferList);
  383. });
  384. var blobToImageData = async (imageBlob, canvasMemoryLimit) => {
  385. let imageData;
  386. // if can use OffscreenCanvas let's go for it as it will mean we can run this operation on a separate thread
  387. if (canCreateImageBitmap() && !isSVGFile(imageBlob) && canCreateOffscreenCanvas()) {
  388. try {
  389. imageData = await thread((file, canvasMemoryLimit, done) => {
  390. createImageBitmap(file)
  391. .then((bitmap) => {
  392. let canvasWidth = bitmap.width;
  393. let canvasHeight = bitmap.height;
  394. // determine if requires more memory than limit, if so limit target size
  395. const requiredCanvasMemory = canvasWidth * canvasHeight;
  396. if (canvasMemoryLimit && requiredCanvasMemory > canvasMemoryLimit) {
  397. const canvasScalar = Math.sqrt(canvasMemoryLimit) / Math.sqrt(requiredCanvasMemory);
  398. canvasWidth = Math.floor(canvasWidth * canvasScalar);
  399. canvasHeight = Math.floor(canvasHeight * canvasScalar);
  400. }
  401. const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
  402. const ctx = canvas.getContext('2d');
  403. ctx.drawImage(bitmap, 0, 0, canvasWidth, canvasHeight);
  404. const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  405. done(null, imageData);
  406. })
  407. .catch((err) => {
  408. // fail silently
  409. done(err);
  410. });
  411. }, [imageBlob, canvasMemoryLimit]);
  412. }
  413. catch (err) {
  414. // fails silently on purpose, we'll try to turn the blob into image data in the main thread
  415. // console.error(err);
  416. }
  417. }
  418. // use main thread to generate ImageData
  419. if (!imageData || !imageData.width) {
  420. const canvas = await blobToCanvas(imageBlob, canvasMemoryLimit);
  421. imageData = canvasToImageData(canvas);
  422. releaseCanvas(canvas);
  423. }
  424. return imageData;
  425. };
  426. var canvasToBlob = (canvas, mimeType = undefined, quality = undefined) => new Promise((resolve, reject) => {
  427. try {
  428. canvas.toBlob((blob) => {
  429. resolve(blob);
  430. }, mimeType, quality);
  431. }
  432. catch (err) {
  433. reject(err);
  434. }
  435. });
  436. var imageDataToBlob = async (imageData, mimeType, quality) => {
  437. const canvas = await imageDataToCanvas(imageData);
  438. const blob = await canvasToBlob(canvas, mimeType, quality);
  439. releaseCanvas(canvas);
  440. return blob;
  441. };
  442. var blobWriteSection = (blob, section, slice = [0, blob.size]) => {
  443. if (!section)
  444. return blob;
  445. return new Blob([section, blob.slice(...slice)], { type: blob.type });
  446. };
  447. var getExtensionFromMimeType = (mimeType) => (mimeType.match(/\/([a-z]+)/) || [])[1];
  448. var getFilenameWithoutExtension = (name) => name.substr(0, name.lastIndexOf('.')) || name;
  449. var getExtensionFromFilename = (filename) => filename.split('.').pop();
  450. const ImageExtensionsRegex = /avif|bmp|gif|jpg|jpeg|jpe|jif|jfif|png|svg|tiff|webp/;
  451. /*
  452. Support image mime types
  453. - image/webp
  454. - image/gif
  455. - image/avif
  456. - image/jpeg
  457. - image/png
  458. - image/bmp
  459. - image/svg+xml
  460. */
  461. var getMimeTypeFromExtension = (ext) => {
  462. // empty string returned if extension not found
  463. if (!ImageExtensionsRegex.test(ext))
  464. return '';
  465. // return MimeType for this extension
  466. return 'image/' + (/jfif|jif|jpe|jpg/.test(ext) ? 'jpeg' : ext === 'svg' ? 'svg+xml' : ext);
  467. };
  468. var getMimeTypeFromFilename = (name) => name && getMimeTypeFromExtension(getExtensionFromFilename(name).toLowerCase());
  469. var matchFilenameToMimeType = (filename, mimeType) => {
  470. // get the mime type that matches this extension
  471. const fileMimeType = getMimeTypeFromFilename(filename);
  472. // test if type already matches current mime type, no need to change name
  473. if (fileMimeType === mimeType)
  474. return filename;
  475. // get the extension for this mimetype (gets all characters after the "image/" part)
  476. // if mimeType doesn't yield an extension, use the fileMimeType
  477. const targetMimeTypeExtension = getExtensionFromMimeType(mimeType) || fileMimeType;
  478. return `${getFilenameWithoutExtension(filename)}.${targetMimeTypeExtension}`;
  479. };
  480. var blobToFile = (blob, filename, mimetype) => {
  481. const lastModified = new Date().getTime();
  482. const blobHasMimeType = blob.type.length && !/null|text/.test(blob.type);
  483. const blobMimeType = blobHasMimeType ? blob.type : mimetype;
  484. const name = matchFilenameToMimeType(filename, blobMimeType);
  485. try {
  486. return new (getNativeAPIRef('File'))([blob], name, {
  487. lastModified,
  488. type: blobHasMimeType ? blob.type : blobMimeType,
  489. });
  490. }
  491. catch (err) {
  492. const file = blobHasMimeType ? blob.slice() : blob.slice(0, blob.size, blobMimeType);
  493. file.lastModified = lastModified;
  494. file.name = name;
  495. return file;
  496. }
  497. };
  498. var getAspectRatio = (w, h) => w / h;
  499. var passthrough = (v) => (v);
  500. const PI = Math.PI;
  501. const HALF_PI = Math.PI / 2;
  502. const QUART_PI = HALF_PI / 2;
  503. var isRotatedSideways = (a) => {
  504. const rotationLimited = Math.abs(a) % Math.PI;
  505. return rotationLimited > QUART_PI && rotationLimited < Math.PI - QUART_PI;
  506. };
  507. //
  508. // generic
  509. //
  510. const scale = (value, scalar, pivot) => pivot + (value - pivot) * scalar;
  511. const ellipseCreateFromRect = (rect) => ({
  512. x: rect.x + rect.width * 0.5,
  513. y: rect.y + rect.height * 0.5,
  514. rx: rect.width * 0.5,
  515. ry: rect.height * 0.5,
  516. });
  517. //
  518. // vector
  519. //
  520. const vectorCreateEmpty = () => vectorCreate(0, 0);
  521. const vectorCreate = (x, y) => ({ x, y });
  522. const vectorCreateFromSize = (size) => vectorCreate(size.width, size.height);
  523. const vectorCreateFromPointerEvent = (e) => vectorCreate(e.pageX, e.pageY);
  524. const vectorCreateFromPointerEventOffset = (e) => vectorCreate(e.offsetX, e.offsetY);
  525. const vectorClone = (v) => vectorCreate(v.x, v.y);
  526. const vectorInvert = (v) => {
  527. v.x = -v.x;
  528. v.y = -v.y;
  529. return v;
  530. };
  531. const vectorPerpendicular = (v) => {
  532. const x = v.x;
  533. v.x = -v.y;
  534. v.y = x;
  535. return v;
  536. };
  537. const vectorRotate = (v, radians, pivot = vectorCreateEmpty()) => {
  538. const cos = Math.cos(radians);
  539. const sin = Math.sin(radians);
  540. const tx = v.x - pivot.x;
  541. const ty = v.y - pivot.y;
  542. v.x = pivot.x + cos * tx - sin * ty;
  543. v.y = pivot.y + sin * tx + cos * ty;
  544. return v;
  545. };
  546. const vectorLength = (v) => Math.sqrt(v.x * v.x + v.y * v.y);
  547. const vectorNormalize = (v) => {
  548. const length = Math.sqrt(v.x * v.x + v.y * v.y);
  549. if (length === 0)
  550. return vectorCreateEmpty();
  551. v.x /= length;
  552. v.y /= length;
  553. return v;
  554. };
  555. const vectorAngle = (v) => Math.atan2(v.y, v.x);
  556. const vectorAngleBetween = (a, b) => Math.atan2(b.y - a.y, b.x - a.x);
  557. const vectorEqual = (a, b) => a.x === b.x && a.y === b.y;
  558. const vectorApply = (v, fn) => {
  559. v.x = fn(v.x);
  560. v.y = fn(v.y);
  561. return v;
  562. };
  563. const vectorAdd = (a, b) => {
  564. a.x += b.x;
  565. a.y += b.y;
  566. return a;
  567. };
  568. const vectorSubtract = (a, b) => {
  569. a.x -= b.x;
  570. a.y -= b.y;
  571. return a;
  572. };
  573. const vectorMultiply = (v, f) => {
  574. v.x *= f;
  575. v.y *= f;
  576. return v;
  577. };
  578. const vectorDot = (a, b) => a.x * b.x + a.y * b.y;
  579. const vectorDistanceSquared = (a, b = vectorCreateEmpty()) => {
  580. const x = a.x - b.x;
  581. const y = a.y - b.y;
  582. return x * x + y * y;
  583. };
  584. const vectorDistance = (a, b = vectorCreateEmpty()) => Math.sqrt(vectorDistanceSquared(a, b));
  585. const vectorCenter = (v) => {
  586. let x = 0;
  587. let y = 0;
  588. v.forEach((v) => {
  589. x += v.x;
  590. y += v.y;
  591. });
  592. return vectorCreate(x / v.length, y / v.length);
  593. };
  594. const vectorsFlip = (points, flipX, flipY, cx, cy) => {
  595. points.forEach((point) => {
  596. point.x = flipX ? cx - (point.x - cx) : point.x;
  597. point.y = flipY ? cy - (point.y - cy) : point.y;
  598. });
  599. return points;
  600. };
  601. const vectorsRotate = (points, angle, cx, cy) => {
  602. const s = Math.sin(angle);
  603. const c = Math.cos(angle);
  604. points.forEach((p) => {
  605. p.x -= cx;
  606. p.y -= cy;
  607. const rx = p.x * c - p.y * s;
  608. const ry = p.x * s + p.y * c;
  609. p.x = cx + rx;
  610. p.y = cy + ry;
  611. });
  612. return points;
  613. };
  614. //
  615. // size
  616. //
  617. const toSize = (width, height) => ({ width, height });
  618. const sizeClone = (size) => toSize(size.width, size.height);
  619. const sizeCreateFromAny = (obj) => toSize(obj.width, obj.height);
  620. const sizeCreateFromRect = (r) => toSize(r.width, r.height);
  621. const sizeCreateFromArray = (a) => toSize(a[0], a[1]);
  622. const sizeCreateFromImageNaturalSize = (image) => toSize(image.naturalWidth, image.naturalHeight);
  623. const sizeCreateFromElement = (element) => {
  624. if (/img/i.test(element.nodeName)) {
  625. return sizeCreateFromImageNaturalSize(element);
  626. }
  627. return sizeCreateFromAny(element);
  628. };
  629. const sizeCreate = (width, height) => toSize(width, height);
  630. const sizeEqual = (a, b, format = passthrough) => format(a.width) === format(b.width) && format(a.height) === format(b.height);
  631. const sizeScale = (size, scalar) => {
  632. size.width *= scalar;
  633. size.height *= scalar;
  634. return size;
  635. };
  636. const sizeCenter = (size) => vectorCreate(size.width * 0.5, size.height * 0.5);
  637. const sizeRotate = (size, radians) => {
  638. const r = Math.abs(radians);
  639. const cos = Math.cos(r);
  640. const sin = Math.sin(r);
  641. const w = cos * size.width + sin * size.height;
  642. const h = sin * size.width + cos * size.height;
  643. size.width = w;
  644. size.height = h;
  645. return size;
  646. };
  647. const sizeTurn = (size, radians) => {
  648. const w = size.width;
  649. const h = size.height;
  650. if (isRotatedSideways(radians)) {
  651. size.width = h;
  652. size.height = w;
  653. }
  654. return size;
  655. };
  656. const sizeContains = (a, b) => a.width >= b.width && a.height >= b.height;
  657. const sizeApply = (size, fn) => {
  658. size.width = fn(size.width);
  659. size.height = fn(size.height);
  660. return size;
  661. };
  662. const sizeHypotenuse = (size) => Math.sqrt(size.width * size.width + size.height * size.height);
  663. const sizeMin = (a, b) => sizeCreate(Math.min(a.width, b.width), Math.min(a.height, b.height));
  664. //
  665. // line
  666. //
  667. const lineCreate = (start, end) => ({ start, end });
  668. const lineClone = (line) => lineCreate(vectorClone(line.start), vectorClone(line.end));
  669. const lineExtend = (line, amount) => {
  670. if (amount === 0)
  671. return line;
  672. const v = vectorCreate(line.start.x - line.end.x, line.start.y - line.end.y);
  673. const n = vectorNormalize(v);
  674. const m = vectorMultiply(n, amount);
  675. line.start.x += m.x;
  676. line.start.y += m.y;
  677. line.end.x -= m.x;
  678. line.end.y -= m.y;
  679. return line;
  680. };
  681. const lineMultiply = (line, amount) => {
  682. if (amount === 0)
  683. return line;
  684. const v = vectorCreate(line.start.x - line.end.x, line.start.y - line.end.y);
  685. const n = vectorNormalize(v);
  686. const m = vectorMultiply(n, amount);
  687. line.end.x += m.x;
  688. line.end.y += m.y;
  689. return line;
  690. };
  691. const lineExtrude = ({ start, end }, amount) => {
  692. if (amount === 0)
  693. return [
  694. vectorCreate(start.x, start.y),
  695. vectorCreate(start.x, start.y),
  696. vectorCreate(end.x, end.y),
  697. vectorCreate(end.x, end.y),
  698. ];
  699. const a = Math.atan2(end.y - start.y, end.x - start.x);
  700. const sina = Math.sin(a) * amount;
  701. const cosa = Math.cos(a) * amount;
  702. return [
  703. vectorCreate(sina + start.x, -cosa + start.y),
  704. vectorCreate(-sina + start.x, cosa + start.y),
  705. vectorCreate(-sina + end.x, cosa + end.y),
  706. vectorCreate(sina + end.x, -cosa + end.y),
  707. ];
  708. };
  709. //
  710. // rect
  711. //
  712. const CornerSigns = [
  713. vectorCreate(-1, -1),
  714. vectorCreate(-1, 1),
  715. vectorCreate(1, 1),
  716. vectorCreate(1, -1),
  717. ];
  718. const toRect = (x, y, width, height) => ({
  719. x,
  720. y,
  721. width,
  722. height,
  723. });
  724. const rectClone = (rect) => toRect(rect.x, rect.y, rect.width, rect.height);
  725. const rectCreateEmpty = () => toRect(0, 0, 0, 0);
  726. const rectCreateFromDimensions = (width, height) => toRect(0, 0, width, height);
  727. const rectCreateFromSize = (size) => toRect(0, 0, size.width, size.height);
  728. const rectCreateFromAny = (obj) => toRect(obj.x || 0, obj.y || 0, obj.width || 0, obj.height || 0);
  729. const rectCreateFromPoints = (...args) => {
  730. const pts = Array.isArray(args[0]) ? args[0] : args;
  731. let xMin = pts[0].x;
  732. let xMax = pts[0].x;
  733. let yMin = pts[0].y;
  734. let yMax = pts[0].y;
  735. pts.forEach((point) => {
  736. xMin = Math.min(xMin, point.x);
  737. xMax = Math.max(xMax, point.x);
  738. yMin = Math.min(yMin, point.y);
  739. yMax = Math.max(yMax, point.y);
  740. });
  741. return toRect(xMin, yMin, xMax - xMin, yMax - yMin);
  742. };
  743. const rectCreateFromEllipse = (ellipse) => rectCreate(ellipse.x - ellipse.rx, ellipse.y - ellipse.ry, ellipse.rx * 2, ellipse.ry * 2);
  744. const rectCreateWithCenter = (center, size) => toRect(center.x - size.width * 0.5, center.y - size.height * 0.5, size.width, size.height);
  745. const rectCreate = (x, y, width, height) => toRect(x, y, width, height);
  746. const rectCenter = (rect) => vectorCreate(rect.x + rect.width * 0.5, rect.y + rect.height * 0.5);
  747. const rectTranslate = (rect, t) => {
  748. rect.x += t.x;
  749. rect.y += t.y;
  750. return rect;
  751. };
  752. const rectScale = (rect, scalar, pivot) => {
  753. pivot = pivot || rectCenter(rect);
  754. rect.x = scalar * (rect.x - pivot.x) + pivot.x;
  755. rect.y = scalar * (rect.y - pivot.y) + pivot.y;
  756. rect.width = scalar * rect.width;
  757. rect.height = scalar * rect.height;
  758. return rect;
  759. };
  760. const rectMultiply = (rect, factor) => {
  761. rect.x *= factor;
  762. rect.y *= factor;
  763. rect.width *= factor;
  764. rect.height *= factor;
  765. return rect;
  766. };
  767. const rectDivide = (rect, factor) => {
  768. rect.x /= factor;
  769. rect.y /= factor;
  770. rect.width /= factor;
  771. rect.height /= factor;
  772. return rect;
  773. };
  774. const rectSubtract = (a, b) => {
  775. a.x -= b.x;
  776. a.y -= b.y;
  777. a.width -= b.width;
  778. a.height -= b.height;
  779. return a;
  780. };
  781. const rectAdd = (a, b) => {
  782. a.x += b.x;
  783. a.y += b.y;
  784. a.width += b.width;
  785. a.height += b.height;
  786. return a;
  787. };
  788. const rectEqual = (a, b, format = passthrough) => format(a.x) === format(b.x) &&
  789. format(a.y) === format(b.y) &&
  790. format(a.width) === format(b.width) &&
  791. format(a.height) === format(b.height);
  792. const rectAspectRatio = (rect) => getAspectRatio(rect.width, rect.height);
  793. const rectUpdate = (rect, x, y, width, height) => {
  794. rect.x = x;
  795. rect.y = y;
  796. rect.width = width;
  797. rect.height = height;
  798. return rect;
  799. };
  800. const rectUpdateWithRect = (a, b) => {
  801. a.x = b.x;
  802. a.y = b.y;
  803. a.width = b.width;
  804. a.height = b.height;
  805. return a;
  806. };
  807. const rectRotate = (rect, radians, pivot) => {
  808. if (!pivot)
  809. pivot = rectCenter(rect);
  810. return rectGetCorners(rect).map((vertex) => vectorRotate(vertex, radians, pivot));
  811. };
  812. const rectCenterRect = (a, b) => toRect(a.width * 0.5 - b.width * 0.5, a.height * 0.5 - b.height * 0.5, b.width, b.height);
  813. const rectContainsPoint = (rect, point) => {
  814. if (point.x < rect.x)
  815. return false;
  816. if (point.y < rect.y)
  817. return false;
  818. if (point.x > rect.x + rect.width)
  819. return false;
  820. if (point.y > rect.y + rect.height)
  821. return false;
  822. return true;
  823. };
  824. const rectCoverRect = (rect, aspectRatio, offset = vectorCreateEmpty()) => {
  825. if (rect.width === 0 || rect.height === 0)
  826. return rectCreateEmpty();
  827. const inputAspectRatio = rectAspectRatio(rect);
  828. if (!aspectRatio)
  829. aspectRatio = inputAspectRatio;
  830. let width = rect.width;
  831. let height = rect.height;
  832. if (aspectRatio > inputAspectRatio) {
  833. // height remains the same, width is expanded
  834. width = height * aspectRatio;
  835. }
  836. else {
  837. // width remains the same, height is expanded
  838. height = width / aspectRatio;
  839. }
  840. return toRect(offset.x + (rect.width - width) * 0.5, offset.y + (rect.height - height) * 0.5, width, height);
  841. };
  842. const rectContainRect = (rect, aspectRatio = rectAspectRatio(rect), offset = vectorCreateEmpty()) => {
  843. if (rect.width === 0 || rect.height === 0)
  844. return rectCreateEmpty();
  845. let width = rect.width;
  846. let height = width / aspectRatio;
  847. if (height > rect.height) {
  848. height = rect.height;
  849. width = height * aspectRatio;
  850. }
  851. return toRect(offset.x + (rect.width - width) * 0.5, offset.y + (rect.height - height) * 0.5, width, height);
  852. };
  853. const rectToBounds = (rect) => [
  854. Math.min(rect.y, rect.y + rect.height),
  855. Math.max(rect.x, rect.x + rect.width),
  856. Math.max(rect.y, rect.y + rect.height),
  857. Math.min(rect.x, rect.x + rect.width),
  858. ];
  859. const rectGetCorners = (rect) => [
  860. vectorCreate(rect.x, rect.y),
  861. vectorCreate(rect.x + rect.width, rect.y),
  862. vectorCreate(rect.x + rect.width, rect.y + rect.height),
  863. vectorCreate(rect.x, rect.y + rect.height),
  864. ];
  865. const rectApply = (rect, fn) => {
  866. if (!rect)
  867. return;
  868. rect.x = fn(rect.x);
  869. rect.y = fn(rect.y);
  870. rect.width = fn(rect.width);
  871. rect.height = fn(rect.height);
  872. return rect;
  873. };
  874. const rectApplyPerspective = (rect, perspective, pivot = rectCenter(rect)) => rectGetCorners(rect).map((corner, index) => {
  875. const sign = CornerSigns[index];
  876. return vectorCreate(scale(corner.x, 1.0 + sign.x * perspective.x, pivot.x), scale(corner.y, 1.0 + sign.y * perspective.y, pivot.y));
  877. });
  878. const rectNormalizeOffset = (rect) => {
  879. rect.x = 0;
  880. rect.y = 0;
  881. return rect;
  882. };
  883. const convexPolyCentroid = (vertices) => {
  884. const first = vertices[0];
  885. const last = vertices[vertices.length - 1];
  886. // make sure is closed loop
  887. vertices = vectorEqual(first, last) ? vertices : [...vertices, first];
  888. let twiceArea = 0;
  889. let i = 0;
  890. let x = 0;
  891. let y = 0;
  892. let fx = first.x;
  893. let fy = first.y;
  894. let a;
  895. let b;
  896. let f;
  897. const l = vertices.length;
  898. for (; i < l; i++) {
  899. // current vertex
  900. a = vertices[i];
  901. // next vertex
  902. b = vertices[i + 1 > l - 1 ? 0 : i + 1];
  903. f = (a.y - fy) * (b.x - fx) - (b.y - fy) * (a.x - fx);
  904. twiceArea += f;
  905. x += (a.x + b.x - 2 * fx) * f;
  906. y += (a.y + b.y - 2 * fy) * f;
  907. }
  908. f = twiceArea * 3;
  909. return vectorCreate(fx + x / f, fy + y / f);
  910. };
  911. const lineLineIntersection = (a, b) => getLineLineIntersectionPoint(a.start, a.end, b.start, b.end);
  912. const getLineLineIntersectionPoint = (a, b, c, d) => {
  913. const denominator = (d.y - c.y) * (b.x - a.x) - (d.x - c.x) * (b.y - a.y);
  914. // lines are parallel
  915. if (denominator === 0)
  916. return undefined;
  917. const uA = ((d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x)) / denominator;
  918. const uB = ((b.x - a.x) * (a.y - c.y) - (b.y - a.y) * (a.x - c.x)) / denominator;
  919. // intersection is not on the line itself
  920. if (uA < 0 || uA > 1 || uB < 0 || uB > 1)
  921. return undefined;
  922. // return intersection point
  923. return vectorCreate(a.x + uA * (b.x - a.x), a.y + uA * (b.y - a.y));
  924. };
  925. // checks if line intersects with one of the lines that can be drawn between the points (in sequence)
  926. const linePointsIntersection = (line, points) => {
  927. const l = points.length;
  928. const intersections = [];
  929. for (let i = 0; i < l - 1; i++) {
  930. const intersection = getLineLineIntersectionPoint(line.start, line.end, points[i], points[i + 1]);
  931. if (!intersection)
  932. continue;
  933. intersections.push(intersection);
  934. }
  935. return intersections.length ? intersections : undefined;
  936. };
  937. // tests if a point is located in a convex polygon
  938. const pointInPoly = (point, vertices) => {
  939. let i;
  940. let a;
  941. let b;
  942. let aX;
  943. let aY;
  944. let bX;
  945. let bY;
  946. let edgeX;
  947. let edgeY;
  948. let d;
  949. const l = vertices.length;
  950. for (i = 0; i < l; i++) {
  951. // current vertex
  952. a = vertices[i];
  953. // next vertex
  954. b = vertices[i + 1 > l - 1 ? 0 : i + 1];
  955. // translate so that point is the origin of the calculation
  956. aX = a.x - point.x;
  957. aY = a.y - point.y;
  958. bX = b.x - point.x;
  959. bY = b.y - point.y;
  960. edgeX = aX - bX;
  961. edgeY = aY - bY;
  962. d = edgeX * aY - edgeY * aX;
  963. // 0 is ON the edge, but we check for -0.00001 to fix floating point errors
  964. if (d < -0.00001)
  965. return false;
  966. }
  967. return true;
  968. };
  969. // first tests if points of a are to be found in b, then does the reverse
  970. const polyIntersectsWithPoly = (a, b) => !!(a.find((point) => pointInPoly(point, b)) || b.find((point) => pointInPoly(point, a)));
  971. const quadLines = (vertices) => {
  972. const arr = [];
  973. for (let i = 0; i < vertices.length; i++) {
  974. let next = i + 1;
  975. if (next === vertices.length)
  976. next = 0;
  977. arr.push(lineCreate(vectorClone(vertices[i]), vectorClone(vertices[next])));
  978. }
  979. return arr;
  980. };
  981. const ellipseToPolygon = (center, rx, ry, rotation = 0, flipX = false, flipY = false, resolution = 12) => {
  982. const points = [];
  983. for (let i = 0; i < resolution; i++) {
  984. points.push(vectorCreate(center.x + rx * Math.cos((i * (Math.PI * 2)) / resolution), center.y + ry * Math.sin((i * (Math.PI * 2)) / resolution)));
  985. }
  986. if (flipX || flipY)
  987. vectorsFlip(points, flipX, flipY, center.x, center.y);
  988. if (rotation)
  989. vectorsRotate(points, rotation, center.x, center.y);
  990. return points;
  991. };
  992. var getImageTransformedRect = (imageSize, imageRotation) => {
  993. const imageRect = rectCreateFromSize(imageSize);
  994. const imageCenter = rectCenter(imageRect);
  995. const imageTransformedVertices = rectRotate(imageRect, imageRotation, imageCenter);
  996. return rectNormalizeOffset(rectCreateFromPoints(imageTransformedVertices));
  997. };
  998. var isElement = (v, name) => v instanceof HTMLElement && (name ? new RegExp(`^${name}$`, 'i').test(v.nodeName) : true);
  999. var isFile = (v) => v instanceof File;
  1000. var canvasToFile = async (canvas, mimeType, quality) => {
  1001. const blob = await canvasToBlob(canvas, mimeType, quality);
  1002. return blobToFile(blob, 'canvas');
  1003. };
  1004. var getFilenameFromURL = (url) => url
  1005. .split('/')
  1006. .pop()
  1007. .split(/\?|\#/)
  1008. .shift();
  1009. let isSafari = null;
  1010. var isSafari$1 = () => {
  1011. if (isSafari === null)
  1012. isSafari = isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
  1013. return isSafari;
  1014. };
  1015. var getImageElementSize = (imageElement) => new Promise((resolve, reject) => {
  1016. let shouldAutoRemove = false;
  1017. // test if image is attached to DOM, if not attached, attach so measurement is correct on Safari
  1018. if (!imageElement.parentNode && isSafari$1()) {
  1019. shouldAutoRemove = true;
  1020. // has width 0 and height 0 to prevent rendering very big SVGs (without width and height) that will for one frame overflow the window and show a scrollbar
  1021. imageElement.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;left:0;top:0;width:0;height:0;`;
  1022. document.body.appendChild(imageElement);
  1023. }
  1024. // start testing size
  1025. const measure = () => {
  1026. const width = imageElement.naturalWidth;
  1027. const height = imageElement.naturalHeight;
  1028. const hasSize = width && height;
  1029. if (!hasSize)
  1030. return;
  1031. // clean up image if was attached for measuring
  1032. if (shouldAutoRemove)
  1033. imageElement.parentNode.removeChild(imageElement);
  1034. clearInterval(intervalId);
  1035. resolve({ width, height });
  1036. };
  1037. imageElement.onerror = (err) => {
  1038. clearInterval(intervalId);
  1039. reject(err);
  1040. };
  1041. const intervalId = setInterval(measure, 1);
  1042. measure();
  1043. });
  1044. var getImageSize = async (image) => {
  1045. // the image element we'll use to load the image
  1046. let imageElement = image;
  1047. // if is not an image element, it must be a valid image source
  1048. if (!imageElement.src) {
  1049. imageElement = new Image();
  1050. imageElement.src = isString(image) ? image : URL.createObjectURL(image);
  1051. }
  1052. let size;
  1053. try {
  1054. size = await getImageElementSize(imageElement);
  1055. }
  1056. finally {
  1057. isFile(image) && URL.revokeObjectURL(imageElement.src);
  1058. }
  1059. return size;
  1060. };
  1061. const awaitComplete = (image) => new Promise((resolve, reject) => {
  1062. if (image.complete)
  1063. return resolve(image);
  1064. image.onload = () => resolve(image);
  1065. image.onerror = reject;
  1066. });
  1067. var imageToFile = async (imageElement) => {
  1068. try {
  1069. const size = await getImageSize(imageElement);
  1070. const image = await awaitComplete(imageElement);
  1071. const canvas = document.createElement('canvas');
  1072. canvas.width = size.width;
  1073. canvas.height = size.height;
  1074. const ctx = canvas.getContext('2d');
  1075. ctx.drawImage(image, 0, 0);
  1076. const blob = await canvasToBlob(canvas);
  1077. return blobToFile(blob, getFilenameFromURL(image.src));
  1078. }
  1079. catch (err) {
  1080. throw err;
  1081. }
  1082. };
  1083. var isDataURI = (str) => /^data:/.test(str);
  1084. var createProgressEvent = (loaded = 0, lengthComputable = true) => new (getNativeAPIRef('ProgressEvent'))('progress', {
  1085. loaded: loaded * 100,
  1086. total: 100,
  1087. lengthComputable,
  1088. });
  1089. var isImage = (file) => /^image/.test(file.type);
  1090. var dataURIToFile = async (dataURI, filename = 'data-uri', onprogress = noop$1) => {
  1091. // basic loader, no size info
  1092. onprogress(createProgressEvent(0));
  1093. const res = await fetch(dataURI);
  1094. onprogress(createProgressEvent(0.33));
  1095. const blob = await res.blob();
  1096. let mimeType;
  1097. if (!isImage(blob))
  1098. mimeType = `image/${dataURI.includes(',/9j/') ? 'jpeg' : 'png'}`;
  1099. onprogress(createProgressEvent(0.66));
  1100. const file = blobToFile(blob, filename, mimeType);
  1101. onprogress(createProgressEvent(1));
  1102. return file;
  1103. };
  1104. var getResponseHeader = (xhr, header, parse = (header) => header) => xhr.getAllResponseHeaders().indexOf(header) >= 0
  1105. ? parse(xhr.getResponseHeader(header))
  1106. : undefined;
  1107. var getFilenameFromContentDisposition = (header) => {
  1108. if (!header)
  1109. return null;
  1110. const matches = header.split(/filename=|filename\*=.+''/)
  1111. .splice(1)
  1112. .map(name => name.trim().replace(/^["']|[;"']{0,2}$/g, ''))
  1113. .filter(name => name.length);
  1114. return matches.length ? decodeURI(matches[matches.length - 1]) : null;
  1115. };
  1116. const EditorErrorCode = {
  1117. URL_REQUEST: 'URL_REQUEST',
  1118. DOCTYPE_MISSING: 'DOCTYPE_MISSING',
  1119. };
  1120. class EditorError extends Error {
  1121. constructor(message, code, metadata) {
  1122. super(message);
  1123. this.name = 'EditorError';
  1124. this.code = code;
  1125. this.metadata = metadata;
  1126. }
  1127. }
  1128. var fetchFile = (url, onprogress) => new Promise((resolve, reject) => {
  1129. const handleError = () => reject(new EditorError('Error fetching image', EditorErrorCode.URL_REQUEST, xhr));
  1130. const xhr = new XMLHttpRequest();
  1131. xhr.onprogress = onprogress;
  1132. (xhr.onerror = handleError),
  1133. (xhr.onload = () => {
  1134. if (!xhr.response || xhr.status >= 300 || xhr.status < 200)
  1135. return handleError();
  1136. // we store the response mime type so we can add it to the blob later on, if it's missing (happens on Safari 10)
  1137. const mimetype = getResponseHeader(xhr, 'Content-Type');
  1138. // try to get filename and any file instructions as well
  1139. const filename = getResponseHeader(xhr, 'Content-Disposition', getFilenameFromContentDisposition) || getFilenameFromURL(url);
  1140. // convert to actual file if possible
  1141. resolve(blobToFile(xhr.response, filename, mimetype || getMimeTypeFromFilename(filename)));
  1142. });
  1143. xhr.open('GET', url);
  1144. xhr.responseType = 'blob';
  1145. xhr.send();
  1146. });
  1147. var urlToFile = (url, onprogress) => {
  1148. // use fetch to create blob from data uri
  1149. if (isDataURI(url))
  1150. return dataURIToFile(url, undefined, onprogress);
  1151. // load file from url
  1152. return fetchFile(url, onprogress);
  1153. };
  1154. var isBlob = (v) => v instanceof Blob && !(v instanceof File);
  1155. var srcToFile = async (src, onprogress) => {
  1156. if (isFile(src) || isBlob(src))
  1157. return src;
  1158. else if (isString(src))
  1159. return await urlToFile(src, onprogress);
  1160. else if (isElement(src, 'canvas'))
  1161. return await canvasToFile(src);
  1162. else if (isElement(src, 'img'))
  1163. return await imageToFile(src);
  1164. else {
  1165. throw new EditorError('Invalid image source', 'invalid-image-source');
  1166. }
  1167. };
  1168. let result$8 = null;
  1169. var isMac = () => {
  1170. if (result$8 === null)
  1171. result$8 = isBrowser() && /^mac/i.test(navigator.platform);
  1172. return result$8;
  1173. };
  1174. var isUserAgent = (test) => (isBrowser() ? RegExp(test).test(window.navigator.userAgent) : undefined);
  1175. let result$7 = null;
  1176. var isIOS = () => {
  1177. if (result$7 === null)
  1178. // first part is for iPhones and iPads iOS 12 and below second part is for iPads with iOS 13 and up
  1179. result$7 =
  1180. isBrowser() &&
  1181. (isUserAgent(/iPhone|iPad|iPod/) || (isMac() && navigator.maxTouchPoints >= 1));
  1182. return result$7;
  1183. };
  1184. var orientImageSize = async (size, orientation = 1) => {
  1185. // browser can handle image orientation
  1186. if ((await canOrientImages()) || isIOS())
  1187. return size;
  1188. // no need to correct size
  1189. if (orientation < 5)
  1190. return size;
  1191. // correct image size
  1192. return sizeCreate(size.height, size.width);
  1193. };
  1194. var isJPEG = (file) => /jpeg/.test(file.type);
  1195. var isPlainObject = (obj) => typeof obj == 'object' && obj.constructor == Object;
  1196. var stringify = (value) => (!isPlainObject(value) ? value : JSON.stringify(value));
  1197. var post = (url, dataset, options) => new Promise((resolve, reject) => {
  1198. const { token = {}, beforeSend = noop$1, onprogress = noop$1 } = options;
  1199. token.cancel = () => request.abort();
  1200. const request = new XMLHttpRequest();
  1201. request.upload.onprogress = onprogress;
  1202. request.onload = () => request.status >= 200 && request.status < 300 ? resolve(request) : reject(request);
  1203. request.onerror = () => reject(request);
  1204. request.ontimeout = () => reject(request);
  1205. request.open('POST', encodeURI(url));
  1206. beforeSend(request);
  1207. request.send(dataset.reduce((formData, args) => {
  1208. // @ts-ignore
  1209. formData.append(...args.map(stringify));
  1210. return formData;
  1211. }, new FormData()));
  1212. });
  1213. var ctxRotate = (ctx, rotation = 0, pivot) => {
  1214. if (rotation === 0)
  1215. return ctx;
  1216. ctx.translate(pivot.x, pivot.y);
  1217. ctx.rotate(rotation);
  1218. ctx.translate(-pivot.x, -pivot.y);
  1219. return ctx;
  1220. };
  1221. var ctxTranslate = (ctx, x, y) => {
  1222. ctx.translate(x, y);
  1223. return ctx;
  1224. };
  1225. var ctxScale = (ctx, x, y) => {
  1226. ctx.scale(x, y);
  1227. return ctx;
  1228. };
  1229. var cropImageData = async (imageData, options = {}) => {
  1230. const { flipX, flipY, rotation, crop } = options;
  1231. const imageSize = sizeCreateFromAny(imageData);
  1232. const shouldFlip = flipX || flipY;
  1233. const shouldRotate = !!rotation;
  1234. const cropDefined = crop && (crop.x || crop.y || crop.width || crop.height);
  1235. const cropCoversImage = cropDefined && rectEqual(crop, rectCreateFromSize(imageSize));
  1236. const shouldCrop = cropDefined && !cropCoversImage;
  1237. // skip!
  1238. if (!shouldFlip && !shouldRotate && !shouldCrop)
  1239. return imageData;
  1240. // create drawing context
  1241. let imageDataOut;
  1242. let image = h('canvas', {
  1243. width: imageData.width,
  1244. height: imageData.height,
  1245. });
  1246. image.getContext('2d').putImageData(imageData, 0, 0);
  1247. // flip image data
  1248. if (shouldFlip) {
  1249. const ctx = h('canvas', {
  1250. width: image.width,
  1251. height: image.height,
  1252. }).getContext('2d');
  1253. ctxScale(ctx, flipX ? -1 : 1, flipY ? -1 : 1);
  1254. ctx.drawImage(image, flipX ? -image.width : 0, flipY ? -image.height : 0);
  1255. ctx.restore();
  1256. releaseCanvas(image);
  1257. image = ctx.canvas;
  1258. }
  1259. // rotate image data
  1260. if (shouldRotate) {
  1261. // if shouldRotate is true we also receive a crop rect
  1262. const outputSize = sizeApply(sizeCreateFromRect(rectCreateFromPoints(rectRotate(rectCreateFromAny(image), rotation))), Math.floor);
  1263. const ctx = h('canvas', {
  1264. width: crop.width,
  1265. height: crop.height,
  1266. }).getContext('2d');
  1267. ctxTranslate(ctx, -crop.x, -crop.y);
  1268. ctxRotate(ctx, rotation, sizeCenter(outputSize));
  1269. ctx.drawImage(image, (outputSize.width - image.width) * 0.5, (outputSize.height - image.height) * 0.5);
  1270. ctx.restore();
  1271. releaseCanvas(image);
  1272. image = ctx.canvas;
  1273. }
  1274. // crop image data
  1275. else if (shouldCrop) {
  1276. const ctx = image.getContext('2d');
  1277. imageDataOut = ctx.getImageData(crop.x, crop.y, crop.width, crop.height);
  1278. releaseCanvas(image);
  1279. return imageDataOut;
  1280. }
  1281. // done, return resulting image data
  1282. const ctx = image.getContext('2d');
  1283. imageDataOut = ctx.getImageData(0, 0, image.width, image.height);
  1284. releaseCanvas(image);
  1285. return imageDataOut;
  1286. };
  1287. var resizeTransform = (options, done) => {
  1288. const { imageData, width, height } = options;
  1289. const originWidth = imageData.width;
  1290. const originHeight = imageData.height;
  1291. const targetWidth = Math.round(width);
  1292. const targetHeight = Math.round(height);
  1293. const inputData = imageData.data;
  1294. const outputData = new Uint8ClampedArray(targetWidth * targetHeight * 4);
  1295. const ratioWidth = originWidth / targetWidth;
  1296. const ratioHeight = originHeight / targetHeight;
  1297. const ratioWidthHalf = Math.ceil(ratioWidth * 0.5);
  1298. const ratioHeightHalf = Math.ceil(ratioHeight * 0.5);
  1299. for (let j = 0; j < targetHeight; j++) {
  1300. for (let i = 0; i < targetWidth; i++) {
  1301. const x2 = (i + j * targetWidth) * 4;
  1302. let weight = 0;
  1303. let weights = 0;
  1304. let weightsAlpha = 0;
  1305. let r = 0;
  1306. let g = 0;
  1307. let b = 0;
  1308. let a = 0;
  1309. const centerY = (j + 0.5) * ratioHeight;
  1310. for (let yy = Math.floor(j * ratioHeight); yy < (j + 1) * ratioHeight; yy++) {
  1311. const dy = Math.abs(centerY - (yy + 0.5)) / ratioHeightHalf;
  1312. const centerX = (i + 0.5) * ratioWidth;
  1313. const w0 = dy * dy;
  1314. for (let xx = Math.floor(i * ratioWidth); xx < (i + 1) * ratioWidth; xx++) {
  1315. let dx = Math.abs(centerX - (xx + 0.5)) / ratioWidthHalf;
  1316. const w = Math.sqrt(w0 + dx * dx);
  1317. if (w >= -1 && w <= 1) {
  1318. weight = 2 * w * w * w - 3 * w * w + 1;
  1319. if (weight > 0) {
  1320. dx = 4 * (xx + yy * originWidth);
  1321. const ref = inputData[dx + 3];
  1322. a += weight * ref;
  1323. weightsAlpha += weight;
  1324. if (ref < 255) {
  1325. weight = (weight * ref) / 250;
  1326. }
  1327. r += weight * inputData[dx];
  1328. g += weight * inputData[dx + 1];
  1329. b += weight * inputData[dx + 2];
  1330. weights += weight;
  1331. }
  1332. }
  1333. }
  1334. }
  1335. outputData[x2] = r / weights;
  1336. outputData[x2 + 1] = g / weights;
  1337. outputData[x2 + 2] = b / weights;
  1338. outputData[x2 + 3] = a / weightsAlpha;
  1339. }
  1340. }
  1341. done(null, {
  1342. data: outputData,
  1343. width: targetWidth,
  1344. height: targetHeight,
  1345. });
  1346. };
  1347. var imageDataObjectToImageData = (obj) => {
  1348. if (obj instanceof ImageData) {
  1349. return obj;
  1350. }
  1351. let imageData;
  1352. try {
  1353. imageData = new ImageData(obj.width, obj.height);
  1354. }
  1355. catch (err) {
  1356. // IE + Old EDGE (tested on 12)
  1357. const canvas = h('canvas');
  1358. imageData = canvas.getContext('2d').createImageData(obj.width, obj.height);
  1359. }
  1360. imageData.data.set(obj.data);
  1361. return imageData;
  1362. };
  1363. var resizeImageData = async (imageData, options = {}) => {
  1364. const { width, height, fit, upscale } = options;
  1365. // no need to rescale
  1366. if (!width && !height)
  1367. return imageData;
  1368. let targetWidth = width;
  1369. let targetHeight = height;
  1370. if (!width) {
  1371. targetWidth = height;
  1372. }
  1373. else if (!height) {
  1374. targetHeight = width;
  1375. }
  1376. if (fit !== 'force') {
  1377. let scalarWidth = targetWidth / imageData.width;
  1378. let scalarHeight = targetHeight / imageData.height;
  1379. let scalar = 1;
  1380. if (fit === 'cover') {
  1381. scalar = Math.max(scalarWidth, scalarHeight);
  1382. }
  1383. else if (fit === 'contain') {
  1384. scalar = Math.min(scalarWidth, scalarHeight);
  1385. }
  1386. // if image is too small, exit here with original image
  1387. if (scalar > 1 && upscale === false)
  1388. return imageData;
  1389. targetWidth = Math.round(imageData.width * scalar);
  1390. targetHeight = Math.round(imageData.height * scalar);
  1391. }
  1392. // no need to resize?
  1393. if (imageData.width === targetWidth && imageData.height === targetHeight)
  1394. return imageData;
  1395. // let's resize!
  1396. imageData = await thread(resizeTransform, [{ imageData: imageData, width: targetWidth, height: targetHeight }], [imageData.data.buffer]);
  1397. // the resizer returns a plain object, not an actual image data object, lets create one
  1398. return imageDataObjectToImageData(imageData);
  1399. };
  1400. var colorEffect = (options, done) => {
  1401. const { imageData, matrix } = options;
  1402. if (!matrix)
  1403. return done(null, imageData);
  1404. const outputData = new Uint8ClampedArray(imageData.width * imageData.height * 4);
  1405. const data = imageData.data;
  1406. const l = data.length;
  1407. const m11 = matrix[0];
  1408. const m12 = matrix[1];
  1409. const m13 = matrix[2];
  1410. const m14 = matrix[3];
  1411. const m15 = matrix[4];
  1412. const m21 = matrix[5];
  1413. const m22 = matrix[6];
  1414. const m23 = matrix[7];
  1415. const m24 = matrix[8];
  1416. const m25 = matrix[9];
  1417. const m31 = matrix[10];
  1418. const m32 = matrix[11];
  1419. const m33 = matrix[12];
  1420. const m34 = matrix[13];
  1421. const m35 = matrix[14];
  1422. const m41 = matrix[15];
  1423. const m42 = matrix[16];
  1424. const m43 = matrix[17];
  1425. const m44 = matrix[18];
  1426. const m45 = matrix[19];
  1427. let index = 0;
  1428. let r = 0.0;
  1429. let g = 0.0;
  1430. let b = 0.0;
  1431. let a = 0.0;
  1432. let mr = 0.0;
  1433. let mg = 0.0;
  1434. let mb = 0.0;
  1435. let ma = 0.0;
  1436. let or = 0.0;
  1437. let og = 0.0;
  1438. let ob = 0.0;
  1439. for (; index < l; index += 4) {
  1440. r = data[index] / 255;
  1441. g = data[index + 1] / 255;
  1442. b = data[index + 2] / 255;
  1443. a = data[index + 3] / 255;
  1444. mr = r * m11 + g * m12 + b * m13 + a * m14 + m15;
  1445. mg = r * m21 + g * m22 + b * m23 + a * m24 + m25;
  1446. mb = r * m31 + g * m32 + b * m33 + a * m34 + m35;
  1447. ma = r * m41 + g * m42 + b * m43 + a * m44 + m45;
  1448. or = Math.max(0, mr * ma) + (1.0 - ma);
  1449. og = Math.max(0, mg * ma) + (1.0 - ma);
  1450. ob = Math.max(0, mb * ma) + (1.0 - ma);
  1451. outputData[index] = Math.max(0.0, Math.min(1.0, or)) * 255;
  1452. outputData[index + 1] = Math.max(0.0, Math.min(1.0, og)) * 255;
  1453. outputData[index + 2] = Math.max(0.0, Math.min(1.0, ob)) * 255;
  1454. outputData[index + 3] = a * 255;
  1455. }
  1456. done(null, {
  1457. data: outputData,
  1458. width: imageData.width,
  1459. height: imageData.height,
  1460. });
  1461. };
  1462. var convolutionEffect = (options, done) => {
  1463. const { imageData, matrix } = options;
  1464. if (!matrix)
  1465. return done(null, imageData);
  1466. // calculate kernel weight
  1467. let kernelWeight = matrix.reduce((prev, curr) => prev + curr);
  1468. kernelWeight = kernelWeight <= 0 ? 1 : kernelWeight;
  1469. // input info
  1470. const inputWidth = imageData.width;
  1471. const inputHeight = imageData.height;
  1472. const inputData = imageData.data;
  1473. let i = 0;
  1474. let x = 0;
  1475. let y = 0;
  1476. const side = Math.round(Math.sqrt(matrix.length));
  1477. const sideHalf = Math.floor(side / 2);
  1478. let r = 0, g = 0, b = 0, a = 0, cx = 0, cy = 0, scy = 0, scx = 0, srcOff = 0, weight = 0;
  1479. const outputData = new Uint8ClampedArray(inputWidth * inputHeight * 4);
  1480. for (y = 0; y < inputHeight; y++) {
  1481. for (x = 0; x < inputWidth; x++) {
  1482. // calculate the weighed sum of the source image pixels that
  1483. // fall under the convolution matrix
  1484. r = 0;
  1485. g = 0;
  1486. b = 0;
  1487. a = 0;
  1488. for (cy = 0; cy < side; cy++) {
  1489. for (cx = 0; cx < side; cx++) {
  1490. scy = y + cy - sideHalf;
  1491. scx = x + cx - sideHalf;
  1492. if (scy < 0) {
  1493. scy = inputHeight - 1;
  1494. }
  1495. if (scy >= inputHeight) {
  1496. scy = 0;
  1497. }
  1498. if (scx < 0) {
  1499. scx = inputWidth - 1;
  1500. }
  1501. if (scx >= inputWidth) {
  1502. scx = 0;
  1503. }
  1504. srcOff = (scy * inputWidth + scx) * 4;
  1505. weight = matrix[cy * side + cx];
  1506. r += inputData[srcOff] * weight;
  1507. g += inputData[srcOff + 1] * weight;
  1508. b += inputData[srcOff + 2] * weight;
  1509. a += inputData[srcOff + 3] * weight;
  1510. }
  1511. }
  1512. outputData[i] = r / kernelWeight;
  1513. outputData[i + 1] = g / kernelWeight;
  1514. outputData[i + 2] = b / kernelWeight;
  1515. outputData[i + 3] = a / kernelWeight;
  1516. i += 4;
  1517. }
  1518. }
  1519. done(null, {
  1520. data: outputData,
  1521. width: inputWidth,
  1522. height: inputHeight,
  1523. });
  1524. };
  1525. var vignetteEffect = (options, done) => {
  1526. let { imageData, strength } = options;
  1527. if (!strength)
  1528. return done(null, imageData);
  1529. const outputData = new Uint8ClampedArray(imageData.width * imageData.height * 4);
  1530. const inputWidth = imageData.width;
  1531. const inputHeight = imageData.height;
  1532. const inputData = imageData.data;
  1533. const dist = (x, y) => {
  1534. dx = x - cx;
  1535. dy = y - cy;
  1536. return Math.sqrt(dx * dx + dy * dy);
  1537. };
  1538. let x = 0;
  1539. let y = 0;
  1540. let cx = inputWidth * 0.5;
  1541. let cy = inputHeight * 0.5;
  1542. let dx;
  1543. let dy;
  1544. let dm = dist(0, 0);
  1545. let fr, fg, fb;
  1546. let br, bg, bb, ba;
  1547. let fa;
  1548. let ca;
  1549. const blend = (index, input, output, alpha) => {
  1550. br = input[index] / 255;
  1551. bg = input[index + 1] / 255;
  1552. bb = input[index + 2] / 255;
  1553. ba = input[index + 3] / 255;
  1554. fa = 1.0 - alpha;
  1555. ca = fa * ba + alpha;
  1556. output[index] = ((fa * ba * br + alpha * fr) / ca) * 255;
  1557. output[index + 1] = ((fa * ba * bg + alpha * fg) / ca) * 255;
  1558. output[index + 2] = ((fa * ba * bb + alpha * fb) / ca) * 255;
  1559. output[index + 3] = ca * 255;
  1560. };
  1561. if (strength > 0) {
  1562. fr = 0;
  1563. fg = 0;
  1564. fb = 0;
  1565. }
  1566. else {
  1567. strength = Math.abs(strength);
  1568. fr = 1;
  1569. fg = 1;
  1570. fb = 1;
  1571. }
  1572. for (y = 0; y < inputHeight; y++) {
  1573. for (x = 0; x < inputWidth; x++) {
  1574. blend(
  1575. // index
  1576. (x + y * inputWidth) * 4,
  1577. // data in
  1578. inputData,
  1579. // data out
  1580. outputData,
  1581. // opacity
  1582. (dist(x, y) * strength) / dm);
  1583. }
  1584. }
  1585. done(null, {
  1586. data: outputData,
  1587. width: imageData.width,
  1588. height: imageData.height,
  1589. });
  1590. };
  1591. var noiseEffect = (options, done) => {
  1592. const { imageData, level, monochrome = false } = options;
  1593. if (!level)
  1594. return done(null, imageData);
  1595. const outputData = new Uint8ClampedArray(imageData.width * imageData.height * 4);
  1596. const data = imageData.data;
  1597. const l = data.length;
  1598. let index = 0;
  1599. let r;
  1600. let g;
  1601. let b;
  1602. const rand = () => (-1 + Math.random() * 2) * 255 * level;
  1603. const pixel = monochrome
  1604. ? () => {
  1605. const average = rand();
  1606. return [average, average, average];
  1607. }
  1608. : () => {
  1609. return [rand(), rand(), rand()];
  1610. };
  1611. for (; index < l; index += 4) {
  1612. [r, g, b] = pixel();
  1613. outputData[index] = data[index] + r;
  1614. outputData[index + 1] = data[index + 1] + g;
  1615. outputData[index + 2] = data[index + 2] + b;
  1616. outputData[index + 3] = data[index + 3];
  1617. }
  1618. done(null, {
  1619. data: outputData,
  1620. width: imageData.width,
  1621. height: imageData.height,
  1622. });
  1623. };
  1624. var gammaEffect = (options, done) => {
  1625. const { imageData, level } = options;
  1626. if (!level)
  1627. return done(null, imageData);
  1628. const outputData = new Uint8ClampedArray(imageData.width * imageData.height * 4);
  1629. const data = imageData.data;
  1630. const l = data.length;
  1631. let index = 0;
  1632. let r;
  1633. let g;
  1634. let b;
  1635. for (; index < l; index += 4) {
  1636. r = data[index] / 255;
  1637. g = data[index + 1] / 255;
  1638. b = data[index + 2] / 255;
  1639. outputData[index] = Math.pow(r, level) * 255;
  1640. outputData[index + 1] = Math.pow(g, level) * 255;
  1641. outputData[index + 2] = Math.pow(b, level) * 255;
  1642. outputData[index + 3] = data[index + 3];
  1643. }
  1644. done(null, {
  1645. data: outputData,
  1646. width: imageData.width,
  1647. height: imageData.height,
  1648. });
  1649. };
  1650. var isIdentityMatrix = (matrix) => {
  1651. /*
  1652. [
  1653. 1, 0, 0, 0, 0
  1654. 0, 1, 0, 0, 0
  1655. 0, 0, 1, 0, 0
  1656. 0, 0, 0, 1, 0
  1657. ]
  1658. */
  1659. const l = matrix.length;
  1660. let v;
  1661. let s = l >= 20 ? 6 : l >= 16 ? 5 : 3;
  1662. for (let i = 0; i < l; i++) {
  1663. v = matrix[i];
  1664. if (v === 1 && i % s !== 0)
  1665. return false;
  1666. else if (v !== 0 && v !== 1)
  1667. return false;
  1668. }
  1669. return true;
  1670. };
  1671. var filterImageData = async (imageData, options = {}) => {
  1672. const { colorMatrix, convolutionMatrix, gamma: gammaLevel, noise: noiseLevel, vignette: vignetteStrength, } = options;
  1673. // filters
  1674. const filters = [];
  1675. // apply convolution matrix
  1676. if (convolutionMatrix) {
  1677. filters.push([convolutionEffect, { matrix: convolutionMatrix.clarity }]);
  1678. }
  1679. // apply noise
  1680. if (gammaLevel > 0) {
  1681. filters.push([gammaEffect, { level: 1.0 / gammaLevel }]);
  1682. }
  1683. // apply color matrix
  1684. if (colorMatrix && !isIdentityMatrix(colorMatrix)) {
  1685. filters.push([colorEffect, { matrix: colorMatrix }]);
  1686. }
  1687. // apply noise
  1688. if (noiseLevel > 0 || noiseLevel < 0) {
  1689. filters.push([noiseEffect, { level: noiseLevel }]);
  1690. }
  1691. // apply vignette
  1692. if (vignetteStrength > 0 || vignetteStrength < 0) {
  1693. filters.push([vignetteEffect, { strength: vignetteStrength }]);
  1694. }
  1695. // no changes
  1696. if (!filters.length)
  1697. return imageData;
  1698. // builds effect chain
  1699. const chain = (transforms, i) => `(err, imageData) => {
  1700. (${transforms[i][0].toString()})(Object.assign({ imageData: imageData }, filterInstructions[${i}]),
  1701. ${transforms[i + 1] ? chain(transforms, i + 1) : 'done'})
  1702. }`;
  1703. const filterChain = `function (options, done) {
  1704. const filterInstructions = options.filterInstructions;
  1705. const imageData = options.imageData;
  1706. (${chain(filters, 0)})(null, imageData)
  1707. }`;
  1708. imageData = await thread(filterChain, [
  1709. {
  1710. imageData: imageData,
  1711. filterInstructions: filters.map((t) => t[1]),
  1712. },
  1713. ], [imageData.data.buffer]);
  1714. // the resizer returns a plain object, not an actual image data object, lets create one
  1715. return imageDataObjectToImageData(imageData);
  1716. };
  1717. var isNumber = (v) => typeof v === 'number';
  1718. var isEmoji = (str) => isString(str) &&
  1719. str.match(/(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g) !== null;
  1720. var hasProp = (obj, key) => obj.hasOwnProperty(key);
  1721. var isFunction = (v) => typeof v === 'function';
  1722. var isArray = (arr) => Array.isArray(arr);
  1723. var isApple = () => isIOS() || isMac();
  1724. var isWindows = () => /^win/i.test(navigator.platform);
  1725. // macos: font-size: 123, x: 63.5, y: 110
  1726. // windows: font-size: 112, x: 64, y: 103
  1727. // android: font-size: 112, x: 64, y: 102
  1728. let x = 64;
  1729. let y = 102;
  1730. let fontSize = 112;
  1731. let hasSetValues = false;
  1732. var getEmojiSVG = (emoji, alt) => {
  1733. if (!hasSetValues && isBrowser()) {
  1734. if (isWindows())
  1735. y = 103;
  1736. if (isApple()) {
  1737. x = 63.5;
  1738. y = 110;
  1739. fontSize = 123;
  1740. }
  1741. hasSetValues = true;
  1742. }
  1743. return `<svg${alt ? ` aria-label="${alt}"` : ''} width="128" height="128" viewBox="0 0 128 128" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg"><text x="${x}" y="${y}" alignment-baseline="text-top" dominant-baseline="text-top" text-anchor="middle" font-size="${fontSize}px">${emoji}</text></svg>`;
  1744. };
  1745. var SVGToDataURL = (svg) => `data:image/svg+xml,${svg.replace('<', '%3C').replace('>', '%3E')}`;
  1746. var isBinary = (v) => v instanceof Blob;
  1747. var toPercentage = (value, total) => `${(value / total) * 100}%`;
  1748. var colorArrayToRGBA = (color) => `rgba(${Math.round(color[0] * 255)}, ${Math.round(color[1] * 255)}, ${Math.round(color[2] * 255)}, ${isNumber(color[3]) ? color[3] : 1})`;
  1749. const textPadding = 20;
  1750. // font offset
  1751. // font size 16 -> 2, 4
  1752. // font size 32 -> 4, 6
  1753. // font size 64 -> 8, 12
  1754. // font size 128 -> 16, 24
  1755. // font size 256 -> 32, 48
  1756. let fontOffsetBrowser = undefined;
  1757. const getBrowserFontOffset = (fontSize) => {
  1758. if (!fontOffsetBrowser) {
  1759. // size
  1760. const size = 32;
  1761. // let's calculate it
  1762. const ctx = createSimpleContext(size, size);
  1763. updateTextContext(ctx, { fontSize: 100, color: '#fff' });
  1764. ctx.fillText('F', 0, 0);
  1765. // get pixel data so we can find the white pixels
  1766. const data = ctx.getImageData(0, 0, size, size).data;
  1767. // find x offset
  1768. let p = 0;
  1769. let step = 4;
  1770. let to = data.length;
  1771. let from = to - size * 4;
  1772. for (p = from; p < to; p += step) {
  1773. if (data[p])
  1774. break;
  1775. }
  1776. const x = (p - from) / step;
  1777. // find y offset
  1778. from = (size - 1) * 4;
  1779. step = size * 4;
  1780. for (p = from; p < to; p += step) {
  1781. if (data[p])
  1782. break;
  1783. }
  1784. const y = (p - from) / step;
  1785. fontOffsetBrowser = vectorCreate(x, y);
  1786. // done with canvas
  1787. releaseCanvas(ctx.canvas);
  1788. }
  1789. return vectorCreate(-fontOffsetBrowser.x * fontSize * 0.01, -fontOffsetBrowser.y * fontSize * 0.01);
  1790. };
  1791. const createSimpleContext = (width = 1, height = 1) => {
  1792. const canvas = h('canvas');
  1793. const ctx = canvas.getContext('2d');
  1794. ctx.canvas.width = width;
  1795. ctx.canvas.height = height;
  1796. return ctx;
  1797. };
  1798. const updateTextContext = (ctx, options) => {
  1799. const { fontSize = 16, fontFamily = 'sans-serif', fontWeight = 'normal', fontVariant = 'normal', fontStyle = 'normal', textAlign = 'left', color = '#000', } = options;
  1800. ctx.font = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize}px ${fontFamily}`;
  1801. ctx.textBaseline = 'top';
  1802. ctx.textAlign = textAlign;
  1803. ctx.fillStyle = Array.isArray(color) ? colorArrayToRGBA(color) : color;
  1804. };
  1805. const createSimpleTextContext = (options) => {
  1806. const ctx = createSimpleContext();
  1807. updateTextContext(ctx, options);
  1808. return ctx;
  1809. };
  1810. const computeLineHeight = (fontSize, lineHeight) => isFunction(lineHeight) ? lineHeight(fontSize) : lineHeight;
  1811. const getMeasureVisibleWidth = (measure) => Math.abs(measure.actualBoundingBoxLeft) + Math.abs(measure.actualBoundingBoxRight);
  1812. const resizeContextToFitText = (ctx, text, options) => {
  1813. const { width, height } = measureTextContext(ctx, text, computeLineHeight(options.fontSize, options.lineHeight));
  1814. ctx.canvas.width = Math.ceil(width);
  1815. ctx.canvas.height = Math.ceil(height);
  1816. return ctx;
  1817. };
  1818. const measureTextContext = (ctx, text, computedLineHeight) => {
  1819. const storedTextAlign = ctx.textAlign;
  1820. ctx.textAlign = 'left';
  1821. // calculate width
  1822. const lines = text.split('\n');
  1823. const width = lines.reduce((prev, curr) => {
  1824. const lineWidth = getMeasureVisibleWidth(ctx.measureText(curr));
  1825. if (lineWidth > prev) {
  1826. prev = lineWidth;
  1827. }
  1828. return prev;
  1829. }, 1);
  1830. ctx.textAlign = storedTextAlign;
  1831. // calculate height
  1832. const height = computedLineHeight * lines.length;
  1833. return sizeCreate(Math.ceil(width), Math.ceil(height));
  1834. };
  1835. const TextSizeCache = new Map();
  1836. const createTextSizeHash = (text, { fontSize, fontFamily, lineHeight, fontWeight, fontStyle, fontVariant }) => `${[text, fontSize, fontWeight, fontStyle, fontVariant, fontFamily].join('_')}_${isFunction(lineHeight) ? lineHeight(fontSize) : lineHeight}`;
  1837. const textSize = (text, options) => {
  1838. const ctx = createSimpleTextContext(options);
  1839. if (options.width)
  1840. text = wrapText(ctx, text, options.width);
  1841. const hash = createTextSizeHash(text, options);
  1842. let size = TextSizeCache.get(hash);
  1843. if (size)
  1844. return { ...size };
  1845. size = measureTextContext(ctx, text, computeLineHeight(options.fontSize, options.lineHeight));
  1846. TextSizeCache.set(hash, size);
  1847. return { ...size };
  1848. };
  1849. const wrapText = (ctx, text, lineWidth) => {
  1850. // exit if no text
  1851. if (text.length === 0)
  1852. return '';
  1853. const res = [];
  1854. let lineBuffer = '';
  1855. let lineIndex = 0;
  1856. let measureWidth;
  1857. const paragraphs = text.split('\n\n');
  1858. // draw the current line
  1859. const pushLine = () => {
  1860. if (!lineBuffer.length)
  1861. return;
  1862. if (!res[lineIndex]) {
  1863. res[lineIndex] = [];
  1864. }
  1865. res[lineIndex].push(lineBuffer);
  1866. // clear buffer
  1867. lineBuffer = '';
  1868. };
  1869. const fitChar = (char) => {
  1870. const testLine = lineBuffer + char;
  1871. // measure width of entire line if adding these chars
  1872. measureWidth = ctx.measureText(testLine).width;
  1873. // fits on line?
  1874. if (measureWidth < lineWidth) {
  1875. lineBuffer = testLine;
  1876. }
  1877. else {
  1878. // doesn't fit but line buffer is empty, just print the character and move to next line
  1879. if (!lineBuffer.length) {
  1880. lineBuffer = testLine;
  1881. pushLine();
  1882. }
  1883. // fits, lets print current line and move char to next line
  1884. else {
  1885. pushLine();
  1886. lineBuffer = char;
  1887. }
  1888. lineIndex++;
  1889. }
  1890. };
  1891. const fitWord = (word) => {
  1892. const testLine = lineBuffer.length ? lineBuffer + ' ' + word : word;
  1893. // measure width of entire line if adding these chars
  1894. measureWidth = ctx.measureText(testLine).width;
  1895. // fits on line?
  1896. if (measureWidth < lineWidth) {
  1897. lineBuffer = testLine;
  1898. }
  1899. // wrap to next line
  1900. else {
  1901. // if line buffer is empty, whole word doesn't fit, need to cut it up
  1902. if (!lineBuffer.length) {
  1903. word.split('').forEach(fitChar);
  1904. }
  1905. // there are words in the buffer that do fit, let's draw the line and move this word to the next line
  1906. else {
  1907. // draw current buffer
  1908. pushLine();
  1909. lineIndex++;
  1910. // retry to fit this word
  1911. fitWord(word);
  1912. }
  1913. }
  1914. };
  1915. paragraphs.forEach((p) => {
  1916. const lines = p.split('\n');
  1917. lines.forEach((l) => {
  1918. l.split(' ').forEach(fitWord);
  1919. // end of line reached, if we have words in our buffer
  1920. // at this point we need to draw them and then move to the next line
  1921. if (lineBuffer.length)
  1922. pushLine();
  1923. // forced new line
  1924. lineIndex++;
  1925. });
  1926. // forced new line
  1927. lineIndex++;
  1928. });
  1929. return res.map((line) => line.join(' ')).join('\n');
  1930. };
  1931. const drawText$1 = (ctx, text = '', options = {}) => {
  1932. // exit if no text
  1933. if (text.length === 0)
  1934. return ctx;
  1935. const { x = 0, y = 0, lineWidth = 0, textAlign, fontSize, lineHeight } = options;
  1936. // determine where the browser will render the font and correct for browser differences
  1937. const browserFontOffset = vectorAdd(getBrowserFontOffset(fontSize), vectorCreate(fontSize / 12, fontSize / 3.75));
  1938. const fontOffsetX = x + browserFontOffset.x;
  1939. const fontOffsetY = y + browserFontOffset.y;
  1940. const lineHeightComputed = isFunction(lineHeight) ? lineHeight(fontSize) : lineHeight;
  1941. let offset = textAlign === 'right' ? lineWidth : textAlign === 'center' ? lineWidth * 0.5 : 0;
  1942. text.split('\n').forEach((line, i) => {
  1943. ctx.fillText(line, fontOffsetX + offset, fontOffsetY + i * lineHeightComputed);
  1944. });
  1945. return ctx;
  1946. };
  1947. var fixPrecision = (value, precision = 12) => parseFloat(value.toFixed(precision));
  1948. const shapeEqual = (a, b) => {
  1949. return JSON.stringify(a) === JSON.stringify(b);
  1950. };
  1951. const shapeDeepCopy = (shape) => {
  1952. const shapeShallowCopy = { ...shape };
  1953. const shapeDeepCopy = deepCopy(shapeShallowCopy);
  1954. return shapeDeepCopy;
  1955. };
  1956. const getContextSize = (context, size = {}) => {
  1957. const contextAspectRatio = rectAspectRatio(context);
  1958. let xOut;
  1959. let yOut;
  1960. const xIn = size.width || size.rx;
  1961. const yIn = size.height || size.ry;
  1962. if (xIn && yIn)
  1963. return sizeClone(size);
  1964. if (xIn || yIn) {
  1965. xOut = parseFloat(xIn || Number.MAX_SAFE_INTEGER);
  1966. yOut = parseFloat(yIn || Number.MAX_SAFE_INTEGER);
  1967. const min = Math.min(xOut, yOut);
  1968. if (isString(xIn) || isString(yIn)) {
  1969. xOut = `${min}%`;
  1970. yOut = `${min * contextAspectRatio}%`;
  1971. }
  1972. else {
  1973. xOut = min;
  1974. yOut = min;
  1975. }
  1976. }
  1977. else {
  1978. const min = 10;
  1979. xOut = `${min}%`;
  1980. yOut = `${min * contextAspectRatio}%`;
  1981. }
  1982. const xProp = size.width ? 'width' : size.rx ? 'rx' : undefined;
  1983. const yProp = size.width ? 'height' : size.rx ? 'ry' : undefined;
  1984. return {
  1985. [xProp || 'width']: xOut,
  1986. [yProp || 'height']: yOut,
  1987. };
  1988. };
  1989. const shapeCreateFromEmoji = (emoji, props = {}) => {
  1990. return {
  1991. width: undefined,
  1992. height: undefined,
  1993. ...props,
  1994. aspectRatio: 1,
  1995. backgroundImage: SVGToDataURL(getEmojiSVG(emoji)),
  1996. };
  1997. };
  1998. const shapeCreateFromImage = (src, shapeProps = {}) => {
  1999. const shapeDefaultLayout = shapeIsEllipse(shapeProps)
  2000. ? {}
  2001. : {
  2002. width: undefined,
  2003. height: undefined,
  2004. aspectRatio: undefined,
  2005. };
  2006. const shape = {
  2007. // required/default image shape props
  2008. backgroundColor: [0, 0, 0, 0],
  2009. // set default layout props
  2010. ...shapeDefaultLayout,
  2011. // merge with custom props
  2012. ...shapeProps,
  2013. // set image
  2014. backgroundImage:
  2015. // is svg or URL
  2016. isString(src) ? src : isBinary(src) ? URL.createObjectURL(src) : src,
  2017. };
  2018. return shape;
  2019. };
  2020. const shapeCreateFromPreset = (preset, parentRect) => {
  2021. let shape;
  2022. if (isString(preset) || isBinary(preset)) {
  2023. // default props for "quick" preset
  2024. const shapeOptions = {
  2025. ...getContextSize(parentRect),
  2026. backgroundSize: 'contain',
  2027. };
  2028. // if is emoji, create default markup,
  2029. if (isEmoji(preset)) {
  2030. shape = shapeCreateFromEmoji(preset, shapeOptions);
  2031. }
  2032. // is URL, create default markup for image
  2033. else {
  2034. shape = shapeCreateFromImage(preset, shapeOptions);
  2035. }
  2036. }
  2037. else {
  2038. // is using src shortcut
  2039. if (preset.src) {
  2040. const contextSize = getContextSize(parentRect, preset.shape || preset);
  2041. // shape options
  2042. const shapeOptions = {
  2043. // default shape styles
  2044. ...preset.shape,
  2045. // precalcualte size of shape in context
  2046. ...contextSize,
  2047. };
  2048. // should auto-fix aspect ratio
  2049. if (preset.width && preset.height && !hasProp(shapeOptions, 'aspectRatio')) {
  2050. const width = shapeGetPropPixelValue(contextSize, 'width', parentRect);
  2051. const height = shapeGetPropPixelValue(contextSize, 'height', parentRect);
  2052. shapeOptions.aspectRatio = getAspectRatio(width, height);
  2053. }
  2054. // should auto-contain sticker in container
  2055. if (!shapeOptions.backgroundSize && !preset.shape && (!preset.width || !preset.height))
  2056. shapeOptions.backgroundSize = 'contain';
  2057. // emoji markup
  2058. if (isEmoji(preset.src)) {
  2059. shape = shapeCreateFromEmoji(preset.src, shapeOptions);
  2060. }
  2061. // is url
  2062. else {
  2063. shape = shapeCreateFromImage(preset.src, shapeOptions);
  2064. }
  2065. }
  2066. // should have markup defined
  2067. else if (preset.shape) {
  2068. shape = shapeDeepCopy(preset.shape);
  2069. }
  2070. }
  2071. if (hasProp(shape, 'backgroundImage')) {
  2072. // set transparent background if no background color defined
  2073. if (!hasProp(shape, 'backgroundColor')) {
  2074. shape.backgroundColor = [0, 0, 0, 0];
  2075. }
  2076. // for image presets, disable styles by default
  2077. if (!hasProp(shape, 'disableStyle')) {
  2078. shape.disableStyle = ['backgroundColor', 'strokeColor', 'strokeWidth'];
  2079. }
  2080. // by default don't allow flipping
  2081. if (!hasProp(shape, 'disableFlip')) {
  2082. shape.disableFlip = true;
  2083. }
  2084. }
  2085. return parentRect ? shapeComputeDisplay(shape, parentRect) : shape;
  2086. };
  2087. const shapeLineGetStartPoint = (line) => vectorCreate(line.x1, line.y1);
  2088. const shapeLineGetEndPoint = (line) => vectorCreate(line.x2, line.y2);
  2089. const shapeTextUID = ({ text, textAlign, fontSize, fontFamily, lineHeight, fontWeight, fontStyle, fontVariant, }) => `${[text, textAlign, fontSize, fontWeight, fontStyle, fontVariant, fontFamily].join('_')}_${isFunction(lineHeight) ? lineHeight(fontSize) : lineHeight}`;
  2090. //#endregion
  2091. //#region shape testing
  2092. // shape types
  2093. const shapeIsText = (shape) => hasProp(shape, 'text');
  2094. const shapeIsTextLine = (shape) => shapeIsText(shape) && !(shapeHasRelativeSize(shape) || hasProp(shape, 'width'));
  2095. const shapeIsTextBox = (shape) => shapeIsText(shape) && (shapeHasRelativeSize(shape) || hasProp(shape, 'width'));
  2096. const shapeIsRect = (shape) => !shapeIsText(shape) && shapeHasComputedSize(shape);
  2097. const shapeIsEllipse = (shape) => hasProp(shape, 'rx');
  2098. const shapeIsLine = (shape) => hasProp(shape, 'x1') && !shapeIsTriangle(shape);
  2099. const shapeIsTriangle = (shape) => hasProp(shape, 'x3');
  2100. const shapeIsPath = (shape) => hasProp(shape, 'points');
  2101. // shape state
  2102. const shapeIsTextEmpty = (shape) => shapeIsText(shape) && !shape.text.length;
  2103. const shapeIsTextEditing = (shape) => shapeIsText(shape) && shape.isEditing;
  2104. const shapeIsVisible = (shape) => hasProp(shape, 'opacity') ? shape.opacity > 0 : true;
  2105. const shapeIsSelected = (shape) => shape.isSelected;
  2106. const shapeIsDraft = (shape) => shape._isDraft;
  2107. const shapeHasSize = (shape) => hasProp(shape, 'width') && hasProp(shape, 'height');
  2108. const shapeHasNumericStroke = (shape) => isNumber(shape.strokeWidth) && shape.strokeWidth > 0; // only relevant if is bigger than 0
  2109. const shapeHasRelativePosition = (shape) => {
  2110. const hasRight = hasProp(shape, 'right');
  2111. const hasBottom = hasProp(shape, 'bottom');
  2112. return hasRight || hasBottom;
  2113. };
  2114. const shapeHasTexture = (shape) => hasProp(shape, 'backgroundImage') || hasProp(shape, 'text');
  2115. const shapeHasRelativeSize = (shape) => ((hasProp(shape, 'x') || hasProp(shape, 'left')) && hasProp(shape, 'right')) ||
  2116. ((hasProp(shape, 'y') || hasProp(shape, 'top')) && hasProp(shape, 'bottom'));
  2117. const shapeHasComputedSize = (shape) => shapeHasSize(shape) || shapeHasRelativeSize(shape);
  2118. // actions
  2119. const shapeSelect = (shape) => {
  2120. shape.isSelected = true;
  2121. return shape;
  2122. };
  2123. const shapeMakeDraft = (shape) => {
  2124. shape._isDraft = true;
  2125. return shape;
  2126. };
  2127. const shapeMakeFinal = (shape) => {
  2128. shape._isDraft = false;
  2129. return shape;
  2130. };
  2131. // rights
  2132. const shapeCanStyle = (shape, style) => {
  2133. if (shape.disableStyle === true)
  2134. return false;
  2135. if (isArray(shape.disableStyle) && style) {
  2136. return !shape.disableStyle.includes(style);
  2137. }
  2138. return true;
  2139. };
  2140. const shapeCanSelect = (shape) => shape.disableSelect !== true && !shapeIsTriangle(shape);
  2141. const shapeCanRemove = (shape) => shape.disableRemove !== true;
  2142. const shapeCanDuplicate = (shape) => shape.disableDuplicate !== true && shapeCanMove(shape);
  2143. const shapeCanReorder = (shape) => shape.disableReorder !== true;
  2144. const shapeCanFlip = (shape) => {
  2145. if (shape.disableFlip)
  2146. return false;
  2147. if (shapeIsDraft(shape) || shapeHasRelativePosition(shape))
  2148. return false;
  2149. return shapeHasTexture(shape);
  2150. };
  2151. const shapeCanInput = (shape, input) => {
  2152. if (!shapeIsText(shape))
  2153. return false;
  2154. if (shape.disableInput === true)
  2155. return false;
  2156. if (isFunction(shape.disableInput))
  2157. return shape.disableInput(input != null ? input : shape.text);
  2158. return input || true;
  2159. };
  2160. const shapeCanChangeTextLayout = (shape, layout) => {
  2161. if (shape.disableTextLayout === true)
  2162. return false;
  2163. if (isArray(shape.disableTextLayout) && layout) {
  2164. return !shape.disableTextLayout.includes(layout);
  2165. }
  2166. return true;
  2167. };
  2168. const shapeCanManipulate = (shape) => shape.disableManipulate !== true && !shapeIsDraft(shape) && !shapeHasRelativePosition(shape);
  2169. const shapeCanMove = (shape) => shapeCanManipulate(shape) && shape.disableMove !== true;
  2170. const shapeCanResize = (shape) => shapeCanManipulate(shape) &&
  2171. shapeCanMove(shape) &&
  2172. shape.disableResize !== true &&
  2173. (shapeHasSize(shape) || shapeIsTextBox(shape) || shapeIsEllipse(shape) || shapeIsLine(shape));
  2174. const shapeCanRotate = (shape) => shapeCanManipulate(shape) &&
  2175. shape.disableRotate !== true &&
  2176. (shapeHasSize(shape) || hasProp(shape, 'text') || shapeIsEllipse(shape));
  2177. //#endregion
  2178. //#region shape formatting
  2179. const shapeDeleteRelativeProps = (shape) => {
  2180. delete shape.left;
  2181. delete shape.right;
  2182. delete shape.top;
  2183. delete shape.bottom;
  2184. return shape;
  2185. };
  2186. const shapeDeleteTransformProps = (shape) => {
  2187. delete shape.rotation;
  2188. return shape;
  2189. };
  2190. const shapeFormatStroke = (shape) => {
  2191. shape.strokeWidth = shape.strokeWidth || 1;
  2192. shape.strokeColor = shape.strokeColor || [0, 0, 0];
  2193. return shape;
  2194. };
  2195. const shapeFormatFill = (shape) => {
  2196. shape.backgroundColor = shape.backgroundColor
  2197. ? shape.backgroundColor
  2198. : shape.strokeWidth || shape.backgroundImage
  2199. ? undefined
  2200. : [0, 0, 0];
  2201. return shape;
  2202. };
  2203. const autoLineHeight = (fontSize) => fontSize * 1.2;
  2204. const shapeFormatText = (shape) => {
  2205. shape.fontSize = shape.fontSize || 16;
  2206. shape.fontFamily = shape.fontFamily || 'sans-serif';
  2207. shape.fontWeight = shape.fontWeight || 'normal';
  2208. shape.fontStyle = shape.fontStyle || 'normal';
  2209. shape.fontVariant = shape.fontVariant || 'normal';
  2210. shape.lineHeight = isNumber(shape.lineHeight) ? shape.lineHeight : autoLineHeight;
  2211. shape.color = shape.color || [0, 0, 0];
  2212. return shapeIsTextLine(shape) ? shapeFormatTextLine(shape) : shapeFormatTextBox(shape);
  2213. };
  2214. const shapeFormatTextLine = (shape) => {
  2215. delete shape.textAlign;
  2216. return shapeDeleteRelativeProps(shape);
  2217. };
  2218. const shapeFormatTextBox = (shape) => {
  2219. shape.textAlign = shape.textAlign || 'left';
  2220. return shape;
  2221. };
  2222. const shapeFormatRect = (shape) => {
  2223. shape.cornerRadius = shape.cornerRadius || 0;
  2224. shape.strokeWidth = shape.strokeWidth || 0;
  2225. shape.strokeColor = shape.strokeColor || [0, 0, 0];
  2226. return shapeFormatFill(shape);
  2227. };
  2228. const shapeFormatTriangle = (shape) => {
  2229. shape.strokeWidth = shape.strokeWidth || 0;
  2230. shape.strokeColor = shape.strokeColor || [0, 0, 0];
  2231. shapeFormatFill(shape);
  2232. return shapeDeleteRelativeProps(shape);
  2233. };
  2234. const shapeFormatEllipse = (shape) => {
  2235. shape.strokeWidth = shape.strokeWidth || 0;
  2236. shape.strokeColor = shape.strokeColor || [0, 0, 0];
  2237. return shapeFormatFill(shape);
  2238. };
  2239. const shapeFormatPath = (shape) => {
  2240. shapeFormatStroke(shape);
  2241. shapeDeleteTransformProps(shape);
  2242. return shapeDeleteRelativeProps(shape);
  2243. };
  2244. const shapeFormatLine = (shape) => {
  2245. shapeFormatStroke(shape);
  2246. shape.lineStart = shape.lineStart || undefined;
  2247. shape.lineEnd = shape.lineEnd || undefined;
  2248. shapeDeleteTransformProps(shape);
  2249. return shapeDeleteRelativeProps(shape);
  2250. };
  2251. const shapeFormatDefaults = (shape) => {
  2252. if (!isString(shape.id))
  2253. shape.id = getUniqueId();
  2254. if (!hasProp(shape, 'rotation'))
  2255. shape.rotation = 0;
  2256. if (!hasProp(shape, 'opacity'))
  2257. shape.opacity = 1;
  2258. if (!hasProp(shape, 'disableErase'))
  2259. shape.disableErase = true;
  2260. };
  2261. const shapeFormat = (shape) => {
  2262. shapeFormatDefaults(shape);
  2263. if (shapeIsText(shape)) {
  2264. shapeFormatText(shape);
  2265. }
  2266. else if (shapeIsRect(shape)) {
  2267. shapeFormatRect(shape);
  2268. }
  2269. else if (shapeIsPath(shape)) {
  2270. shapeFormatPath(shape);
  2271. }
  2272. else if (shapeIsLine(shape)) {
  2273. shapeFormatLine(shape);
  2274. }
  2275. else if (shapeIsEllipse(shape)) {
  2276. shapeFormatEllipse(shape);
  2277. }
  2278. else if (shapeIsTriangle(shape)) {
  2279. shapeFormatTriangle(shape);
  2280. }
  2281. return shape;
  2282. };
  2283. const shapeGetDescription = (shape) => {
  2284. if (shapeIsText(shape)) {
  2285. return 'text';
  2286. }
  2287. else if (shapeIsRect(shape)) {
  2288. return 'rectangle';
  2289. }
  2290. else if (shapeIsPath(shape)) {
  2291. return 'path';
  2292. }
  2293. else if (shapeIsLine(shape)) {
  2294. return 'line';
  2295. }
  2296. else if (shapeIsEllipse(shape)) {
  2297. return 'ellipse';
  2298. }
  2299. else if (shapeIsTriangle(shape)) {
  2300. return 'triangle';
  2301. }
  2302. return;
  2303. };
  2304. //#endregion
  2305. const toPixelValue = (percentage, total) => (parseFloat(percentage) / 100) * total;
  2306. //#region shape transforming
  2307. const xRegExp = new RegExp(/^x|left|^width|rx|fontSize|cornerRadius|strokeWidth/, 'i');
  2308. const yRegExp = new RegExp(/^y|top|^height|ry/, 'i');
  2309. const rightRegExp = new RegExp(/right/, 'i');
  2310. const bottomRegExp = new RegExp(/bottom/, 'i');
  2311. const compute = (key, value, { width, height }) => {
  2312. // handle array of percentage values
  2313. if (Array.isArray(value)) {
  2314. return value.map((v) => {
  2315. if (isObject(v)) {
  2316. // update the object itself
  2317. computeProps(v, { width, height });
  2318. }
  2319. return v;
  2320. });
  2321. }
  2322. // no need to compute (test with typeof instead of for perf)
  2323. if (typeof value !== 'string')
  2324. return value;
  2325. if (!value.endsWith('%'))
  2326. return value;
  2327. const f = parseFloat(value) / 100;
  2328. if (xRegExp.test(key))
  2329. return fixPrecision(width * f, 6);
  2330. if (yRegExp.test(key))
  2331. return fixPrecision(height * f, 6);
  2332. if (rightRegExp.test(key))
  2333. return fixPrecision(width - width * f, 6);
  2334. if (bottomRegExp.test(key))
  2335. return fixPrecision(height - height * f, 6);
  2336. // dont auto-compute
  2337. return value;
  2338. };
  2339. const computeProps = (obj, size) => {
  2340. return Object.entries(obj).map(([key, value]) => {
  2341. obj[key] = compute(key, value, size);
  2342. });
  2343. };
  2344. const shapeComputeDisplay = (shape, parentRect) => {
  2345. computeProps(shape, parentRect);
  2346. shapeComputeRect(shape, parentRect);
  2347. return shape;
  2348. };
  2349. const shapeGetPropPixelTotal = (prop, parentRect) => {
  2350. let total;
  2351. if (/^x|width|rx|fontSize|strokeWidth|cornerRadius/.test(prop)) {
  2352. total = parentRect.width;
  2353. }
  2354. else if (/^y|height|ry/.test(prop)) {
  2355. total = parentRect.height;
  2356. }
  2357. return total;
  2358. };
  2359. const shapeUpdateProp = (shape, prop, value, parentRect) => {
  2360. if (!isString(shape[prop])) {
  2361. shape[prop] = value;
  2362. return shape;
  2363. }
  2364. const total = shapeGetPropPixelTotal(prop, parentRect);
  2365. shape[prop] = total === undefined ? value : toPercentage(value, total);
  2366. return shape;
  2367. };
  2368. const shapeGetPropPixelValue = (shape, prop, parentRect) => {
  2369. if (!isString(shape[prop]))
  2370. return shape[prop];
  2371. return toPixelValue(shape[prop], shapeGetPropPixelTotal(prop, parentRect));
  2372. };
  2373. const shapeGetPropsPixelValues = (shape, props, parentRect) => {
  2374. return props.reduce((prev, prop) => {
  2375. const value = shapeGetPropPixelValue(shape, prop, parentRect);
  2376. prev[prop] = value;
  2377. return prev;
  2378. }, {});
  2379. };
  2380. const shapeUpdateProps = (shape, props, parentRect) => {
  2381. Object.keys(props).forEach((key) => shapeUpdateProp(shape, key, props[key], parentRect));
  2382. return shape;
  2383. };
  2384. const shapeBounds = (shape) => {
  2385. const rect = rectCreateEmpty();
  2386. const strokeWidth = shape.strokeWidth || 0;
  2387. if (shapeIsRect(shape)) {
  2388. rect.x = shape.x - strokeWidth * 0.5;
  2389. rect.y = shape.y - strokeWidth * 0.5;
  2390. rect.width = shape.width + strokeWidth;
  2391. rect.height = shape.height + strokeWidth;
  2392. }
  2393. else if (shapeIsLine(shape)) {
  2394. const { x1, y1, x2, y2 } = shape;
  2395. const left = Math.abs(Math.min(x1, x2));
  2396. const right = Math.abs(Math.max(x1, x2));
  2397. const top = Math.abs(Math.min(y1, y2));
  2398. const bottom = Math.abs(Math.min(y1, y2));
  2399. rect.x = left + strokeWidth * 0.5;
  2400. rect.y = right + strokeWidth * 0.5;
  2401. rect.width = right - left + strokeWidth;
  2402. rect.height = bottom - top + strokeWidth;
  2403. }
  2404. else if (shapeIsEllipse(shape)) {
  2405. rect.x = shape.x - shape.rx + strokeWidth * 0.5;
  2406. rect.y = shape.y - shape.ry + strokeWidth * 0.5;
  2407. rect.width = shape.rx * 2 + strokeWidth;
  2408. rect.height = shape.ry * 2 + strokeWidth;
  2409. }
  2410. if (rect && hasProp(shape, 'rotation')) {
  2411. rectRotate(rect, shape.rotation);
  2412. }
  2413. return rectToBounds(rect);
  2414. };
  2415. const shapesBounds = (shapes, parentRect) => {
  2416. const bounds = shapes
  2417. .filter((shape) => shape.x < 0 || shape.y < 0 || shape.x1 < 0 || shape.y1 < 0)
  2418. .reduce((bounds, shape) => {
  2419. const [top, right, bottom, left] = shapeBounds(shape);
  2420. bounds.top = Math.min(top, bounds.top);
  2421. bounds.left = Math.min(left, bounds.left);
  2422. bounds.bottom = Math.max(bottom, bounds.bottom);
  2423. bounds.right = Math.max(right, bounds.right);
  2424. return bounds;
  2425. }, {
  2426. top: 0,
  2427. right: 0,
  2428. bottom: 0,
  2429. left: 0,
  2430. });
  2431. if (bounds.right > 0)
  2432. bounds.right -= parentRect.width;
  2433. if (bounds.bottom > 0)
  2434. bounds.bottom -= parentRect.height;
  2435. return bounds;
  2436. };
  2437. const shapesFromCompositShape = (shape, parentRect, parser) => {
  2438. const shapeCopy = shapeDeepCopy(shape);
  2439. shapeComputeDisplay(shapeCopy, parentRect);
  2440. return parser(shapeCopy);
  2441. };
  2442. const shapeComputeRect = (shape, parentRect) => {
  2443. if (hasProp(shape, 'left'))
  2444. shape.x = shape.left;
  2445. if (hasProp(shape, 'right')) {
  2446. const r = parentRect.width - shape.right;
  2447. if (hasProp(shape, 'left')) {
  2448. shape.x = shape.left;
  2449. shape.width = Math.max(0, r - shape.left);
  2450. }
  2451. else if (hasProp(shape, 'width')) {
  2452. shape.x = r - shape.width;
  2453. }
  2454. }
  2455. if (hasProp(shape, 'top'))
  2456. shape.y = shape.top;
  2457. if (hasProp(shape, 'bottom')) {
  2458. const b = parentRect.height - shape.bottom;
  2459. if (hasProp(shape, 'top')) {
  2460. shape.y = shape.top;
  2461. shape.height = Math.max(0, b - shape.top);
  2462. }
  2463. else if (hasProp(shape, 'height')) {
  2464. shape.y = b - shape.height;
  2465. }
  2466. }
  2467. return shape;
  2468. };
  2469. const shapeComputeTransform = (shape, translate, scale) => {
  2470. if (shapeIsPath(shape)) {
  2471. shape.points
  2472. .filter((point) => isNumber(point.x))
  2473. .forEach((point) => {
  2474. point.x *= scale;
  2475. point.y *= scale;
  2476. point.x += translate.x;
  2477. point.y += translate.y;
  2478. });
  2479. }
  2480. if (shapeIsTriangle(shape) && isNumber(shape.x1)) {
  2481. shape.x1 *= scale;
  2482. shape.y1 *= scale;
  2483. shape.x2 *= scale;
  2484. shape.y2 *= scale;
  2485. shape.x3 *= scale;
  2486. shape.y3 *= scale;
  2487. shape.x1 += translate.x;
  2488. shape.y1 += translate.y;
  2489. shape.x2 += translate.x;
  2490. shape.y2 += translate.y;
  2491. shape.x3 += translate.x;
  2492. shape.y3 += translate.y;
  2493. }
  2494. if (shapeIsLine(shape) && isNumber(shape.x1)) {
  2495. shape.x1 *= scale;
  2496. shape.y1 *= scale;
  2497. shape.x2 *= scale;
  2498. shape.y2 *= scale;
  2499. shape.x1 += translate.x;
  2500. shape.y1 += translate.y;
  2501. shape.x2 += translate.x;
  2502. shape.y2 += translate.y;
  2503. }
  2504. if (isNumber(shape.x) && isNumber(shape.y)) {
  2505. shape.x *= scale;
  2506. shape.y *= scale;
  2507. shape.x += translate.x;
  2508. shape.y += translate.y;
  2509. }
  2510. if (isNumber(shape.width) && isNumber(shape.height)) {
  2511. shape.width *= scale;
  2512. shape.height *= scale;
  2513. }
  2514. if (isNumber(shape.rx) && isNumber(shape.ry)) {
  2515. shape.rx *= scale;
  2516. shape.ry *= scale;
  2517. }
  2518. if (shapeHasNumericStroke(shape)) {
  2519. shape.strokeWidth *= scale;
  2520. }
  2521. if (shapeIsText(shape) && isNumber(shape.fontSize)) {
  2522. shape.fontSize *= scale;
  2523. if (isNumber(shape.width) && !isNumber(shape.width))
  2524. shape.width *= scale;
  2525. }
  2526. if (hasProp(shape, 'cornerRadius') && isNumber(shape.cornerRadius)) {
  2527. shape.cornerRadius *= scale;
  2528. }
  2529. return shape;
  2530. };
  2531. const shapeGetCenter = (shape) => {
  2532. if (shapeIsRect(shape)) {
  2533. return vectorCreate(shape.x + shape.width * 0.5, shape.y + shape.height * 0.5);
  2534. }
  2535. if (shapeIsEllipse(shape)) {
  2536. return vectorCreate(shape.x, shape.y);
  2537. }
  2538. if (shapeIsTextBox(shape)) {
  2539. const height = shape.height || textSize(shape.text, shape).height;
  2540. return vectorCreate(shape.x + shape.width * 0.5, shape.y + height * 0.5);
  2541. }
  2542. if (shapeIsTextLine(shape)) {
  2543. const size = textSize(shape.text, shape);
  2544. return vectorCreate(shape.x + size.width * 0.5, shape.y + size.height * 0.5);
  2545. }
  2546. if (shapeIsPath(shape)) {
  2547. return vectorCenter(shape.points);
  2548. }
  2549. if (shapeIsLine(shape)) {
  2550. return vectorCenter([
  2551. shapeLineGetStartPoint(shape),
  2552. shapeLineGetEndPoint(shape),
  2553. ]);
  2554. }
  2555. return undefined;
  2556. };
  2557. //#endregion
  2558. var ctxRoundRect = (ctx, x, y, width, height, radius) => {
  2559. if (width < 2 * radius)
  2560. radius = width / 2;
  2561. if (height < 2 * radius)
  2562. radius = height / 2;
  2563. ctx.beginPath();
  2564. ctx.moveTo(x + radius, y);
  2565. ctx.arcTo(x + width, y, x + width, y + height, radius);
  2566. ctx.arcTo(x + width, y + height, x, y + height, radius);
  2567. ctx.arcTo(x, y + height, x, y, radius);
  2568. ctx.arcTo(x, y, x + width, y, radius);
  2569. ctx.closePath();
  2570. return ctx;
  2571. };
  2572. var isCanvas = (element) => /canvas/i.test(element.nodeName);
  2573. var isRemoteURL = (url) => new URL(url, location.href).origin !== location.origin;
  2574. var loadImage = (image, onSize = undefined) => new Promise((resolve, reject) => {
  2575. // the image element we'll use to load the image
  2576. let imageElement = image;
  2577. let sizeCalculated = false;
  2578. const reportSize = () => {
  2579. if (sizeCalculated)
  2580. return;
  2581. sizeCalculated = true;
  2582. isFunction(onSize) &&
  2583. /* Use Promise.resolve to make async but place before resolve of parent promise */
  2584. Promise.resolve().then(() => onSize(sizeCreate(imageElement.naturalWidth, imageElement.naturalHeight)));
  2585. };
  2586. // if is not an image element, it must be a valid image source
  2587. if (!imageElement.src) {
  2588. imageElement = new Image();
  2589. // if is remote image, set crossOrigin
  2590. // why not always set crossOrigin? -> because when set this fires two requests,
  2591. // one for asking permission and one for downloading the image
  2592. if (isString(image) && isRemoteURL(image))
  2593. imageElement.crossOrigin = 'anonymous';
  2594. imageElement.src = isString(image) ? image : URL.createObjectURL(image);
  2595. }
  2596. if (imageElement.complete) {
  2597. reportSize();
  2598. return resolve(imageElement);
  2599. }
  2600. // try to calculate size faster
  2601. if (isFunction(onSize))
  2602. getImageElementSize(imageElement).then(reportSize).catch(reject);
  2603. imageElement.onload = () => {
  2604. reportSize();
  2605. resolve(imageElement);
  2606. };
  2607. imageElement.onerror = reject;
  2608. });
  2609. var pubsub = () => {
  2610. let subs = [];
  2611. return {
  2612. sub: (event, callback) => {
  2613. subs.push({ event, callback });
  2614. return () => (subs = subs.filter((subscriber) => subscriber.event !== event || subscriber.callback !== callback));
  2615. },
  2616. pub: (event, value) => {
  2617. subs
  2618. .filter((sub) => sub.event === event)
  2619. .forEach((sub) => sub.callback(value));
  2620. }
  2621. };
  2622. };
  2623. const cache = new Map([]);
  2624. const getImage = (src, options = {}) => new Promise((resolve, reject) => {
  2625. const { onMetadata = noop$1, onLoad = resolve, onError = reject, onComplete = noop$1, } = options;
  2626. let imageLoadState = cache.get(src);
  2627. // start loading
  2628. if (!imageLoadState) {
  2629. imageLoadState = {
  2630. loading: false,
  2631. complete: false,
  2632. error: false,
  2633. image: undefined,
  2634. size: undefined,
  2635. bus: pubsub(),
  2636. };
  2637. // store
  2638. cache.set(src, imageLoadState);
  2639. }
  2640. // wait for load
  2641. imageLoadState.bus.sub('meta', onMetadata);
  2642. imageLoadState.bus.sub('load', onLoad);
  2643. imageLoadState.bus.sub('error', onError);
  2644. imageLoadState.bus.sub('complete', onComplete);
  2645. // if is canvas, it's already done
  2646. if (isCanvas(src)) {
  2647. const canvas = src;
  2648. // get image
  2649. const image = canvas.cloneNode();
  2650. // update state
  2651. imageLoadState.complete = true;
  2652. imageLoadState.image = image;
  2653. imageLoadState.size = sizeCreateFromElement(canvas);
  2654. }
  2655. // already loaded
  2656. if (imageLoadState.complete) {
  2657. imageLoadState.bus.pub('meta', { size: imageLoadState.size });
  2658. if (imageLoadState.error) {
  2659. imageLoadState.bus.pub('error', imageLoadState.error);
  2660. }
  2661. else {
  2662. imageLoadState.bus.pub('load', imageLoadState.image);
  2663. }
  2664. imageLoadState.bus.pub('complete');
  2665. // reset subscribers
  2666. imageLoadState.bus = pubsub();
  2667. return;
  2668. }
  2669. // already loading, exit here
  2670. if (imageLoadState.loading)
  2671. return;
  2672. // now loading
  2673. imageLoadState.loading = true;
  2674. // resource needs to be loaded
  2675. loadImage(src, (size) => {
  2676. imageLoadState.size = size;
  2677. imageLoadState.bus.pub('meta', { size });
  2678. })
  2679. .then((image) => {
  2680. imageLoadState.image = image;
  2681. imageLoadState.bus.pub('load', image);
  2682. })
  2683. .catch((err) => {
  2684. imageLoadState.error = err;
  2685. imageLoadState.bus.pub('error', err);
  2686. })
  2687. .finally(() => {
  2688. imageLoadState.complete = true;
  2689. imageLoadState.loading = false;
  2690. imageLoadState.bus.pub('complete');
  2691. // reset subscribers
  2692. imageLoadState.bus = pubsub();
  2693. });
  2694. });
  2695. const drawCanvas = (ctx, image, srcRect, destRect) => ctx.drawImage(image, srcRect.x, srcRect.x, srcRect.width, srcRect.height, destRect.x, destRect.y, destRect.width, destRect.height);
  2696. var ctxDrawImage = async (ctx, image, srcRect, destRect, draw = drawCanvas) => {
  2697. ctx.save();
  2698. ctx.clip();
  2699. await draw(ctx, image, srcRect, destRect);
  2700. ctx.restore();
  2701. };
  2702. const getDrawImageParams = (container, backgroundSize, imageSize) => {
  2703. let srcRect = rectCreate(0, 0, imageSize.width, imageSize.height);
  2704. const destRect = rectClone(container);
  2705. if (backgroundSize === 'contain') {
  2706. const rect = rectContainRect(container, rectAspectRatio(srcRect));
  2707. destRect.width = rect.width;
  2708. destRect.height = rect.height;
  2709. destRect.x += rect.x;
  2710. destRect.y += rect.y;
  2711. }
  2712. else if (backgroundSize === 'cover') {
  2713. srcRect = rectContainRect(rectCreate(0, 0, srcRect.width, srcRect.height), rectAspectRatio(destRect));
  2714. }
  2715. return {
  2716. srcRect,
  2717. destRect,
  2718. };
  2719. };
  2720. const defineRectShape = (ctx, shape) => {
  2721. shape.cornerRadius > 0
  2722. ? ctxRoundRect(ctx, shape.x, shape.y, shape.width, shape.height, shape.cornerRadius)
  2723. : ctx.rect(shape.x, shape.y, shape.width, shape.height);
  2724. return ctx;
  2725. };
  2726. const fillRectShape = (ctx, shape) => {
  2727. shape.backgroundColor && ctx.fill();
  2728. return ctx;
  2729. };
  2730. const strokeRectShape = (ctx, shape) => {
  2731. shape.strokeWidth && ctx.stroke();
  2732. return ctx;
  2733. };
  2734. var drawRect = async (ctx, shape, options = {}) => new Promise(async (resolve, reject) => {
  2735. const { drawImage } = options;
  2736. ctx.lineWidth = shape.strokeWidth ? shape.strokeWidth : 1; // 1 is default value for lineWidth prop
  2737. ctx.strokeStyle = shape.strokeColor ? colorArrayToRGBA(shape.strokeColor) : 'none';
  2738. ctx.fillStyle = shape.backgroundColor ? colorArrayToRGBA(shape.backgroundColor) : 'none';
  2739. ctx.globalAlpha = shape.opacity;
  2740. if (shape.backgroundImage) {
  2741. let image;
  2742. try {
  2743. if (isCanvas(shape.backgroundImage)) {
  2744. image = shape.backgroundImage;
  2745. }
  2746. else {
  2747. image = await getImage(shape.backgroundImage);
  2748. }
  2749. }
  2750. catch (err) {
  2751. reject(err);
  2752. }
  2753. defineRectShape(ctx, shape);
  2754. fillRectShape(ctx, shape);
  2755. const { srcRect, destRect } = getDrawImageParams(shape, shape.backgroundSize, sizeCreateFromElement(image));
  2756. await ctxDrawImage(ctx, image, srcRect, destRect, drawImage);
  2757. strokeRectShape(ctx, shape);
  2758. resolve([]);
  2759. }
  2760. else {
  2761. defineRectShape(ctx, shape);
  2762. fillRectShape(ctx, shape);
  2763. strokeRectShape(ctx, shape);
  2764. resolve([]);
  2765. }
  2766. });
  2767. var drawEllipse = async (ctx, shape, options = {}) => new Promise(async (resolve, reject) => {
  2768. const { drawImage } = options;
  2769. ctx.lineWidth = shape.strokeWidth || 1; // 1 is default value for lineWidth prop
  2770. ctx.strokeStyle = shape.strokeColor ? colorArrayToRGBA(shape.strokeColor) : 'none';
  2771. ctx.fillStyle = shape.backgroundColor ? colorArrayToRGBA(shape.backgroundColor) : 'none';
  2772. ctx.globalAlpha = shape.opacity;
  2773. ctx.ellipse(shape.x, shape.y, shape.rx, shape.ry, 0, 0, Math.PI * 2);
  2774. shape.backgroundColor && ctx.fill();
  2775. if (shape.backgroundImage) {
  2776. let image;
  2777. try {
  2778. image = await getImage(shape.backgroundImage);
  2779. }
  2780. catch (err) {
  2781. reject(err);
  2782. }
  2783. const bounds = rectCreate(shape.x - shape.rx, shape.y - shape.ry, shape.rx * 2, shape.ry * 2);
  2784. const { srcRect, destRect } = getDrawImageParams(bounds, shape.backgroundSize, sizeCreateFromElement(image));
  2785. // @ts-ignore
  2786. await ctxDrawImage(ctx, image, srcRect, destRect, drawImage);
  2787. shape.strokeWidth && ctx.stroke();
  2788. resolve([]);
  2789. }
  2790. else {
  2791. shape.strokeWidth && ctx.stroke();
  2792. resolve([]);
  2793. }
  2794. });
  2795. var drawText = async (ctx, shape, options) => {
  2796. const size = shape.width && shape.height
  2797. ? sizeCreateFromAny(shape)
  2798. : textSize(shape.text, shape);
  2799. const rect = {
  2800. x: shape.x,
  2801. y: shape.y,
  2802. width: shape.width || size.width,
  2803. height: size.height,
  2804. };
  2805. drawRect(ctx, {
  2806. ...shape,
  2807. ...rect,
  2808. options,
  2809. });
  2810. updateTextContext(ctx, shape);
  2811. let tx = 0;
  2812. if (shape.textAlign == 'center') {
  2813. tx = -textPadding * 0.5;
  2814. }
  2815. else if (shape.textAlign === 'right') {
  2816. tx = -textPadding;
  2817. }
  2818. ctx.rect(shape.x + tx, shape.y, shape.width + textPadding * 2, shape.height);
  2819. ctx.save();
  2820. ctx.clip();
  2821. drawText$1(ctx, shape.width ? wrapText(ctx, shape.text, shape.width) : shape.text, {
  2822. x: shape.x,
  2823. y: shape.y,
  2824. fontSize: shape.fontSize,
  2825. textAlign: shape.textAlign,
  2826. lineHeight: shape.lineHeight,
  2827. lineWidth: shape.width,
  2828. });
  2829. ctx.restore();
  2830. return [];
  2831. };
  2832. // TODO! START
  2833. // -----------
  2834. var drawLine = async (ctx, shape) => new Promise(async (resolve) => {
  2835. ctx.lineWidth = shape.strokeWidth || 1; // 1 is default value for lineWidth prop
  2836. ctx.strokeStyle = shape.strokeColor ? colorArrayToRGBA(shape.strokeColor) : 'none';
  2837. ctx.globalAlpha = shape.opacity;
  2838. let lineStartPosition = shapeLineGetStartPoint(shape);
  2839. let lineEndPosition = shapeLineGetEndPoint(shape);
  2840. // draw line
  2841. ctx.moveTo(lineStartPosition.x, lineStartPosition.y);
  2842. ctx.lineTo(lineEndPosition.x, lineEndPosition.y);
  2843. shape.strokeWidth && ctx.stroke();
  2844. // draw other shapes
  2845. resolve([]);
  2846. });
  2847. // TODO! END
  2848. // -----------
  2849. var drawPath = async (ctx, shape) => new Promise((resolve, reject) => {
  2850. ctx.lineWidth = shape.strokeWidth || 1; // 1 is default value for lineWidth prop
  2851. ctx.strokeStyle = shape.strokeColor ? colorArrayToRGBA(shape.strokeColor) : 'none';
  2852. ctx.fillStyle = shape.backgroundColor ? colorArrayToRGBA(shape.backgroundColor) : 'none';
  2853. ctx.globalAlpha = shape.opacity;
  2854. // draw line
  2855. const { points } = shape;
  2856. if (shape.pathClose)
  2857. ctx.beginPath();
  2858. ctx.moveTo(points[0].x, points[0].y);
  2859. const l = points.length;
  2860. for (let i = 1; i < l; i++) {
  2861. ctx.lineTo(points[i].x, points[i].y);
  2862. }
  2863. if (shape.pathClose)
  2864. ctx.closePath();
  2865. shape.strokeWidth && ctx.stroke();
  2866. shape.backgroundColor && ctx.fill();
  2867. resolve([]);
  2868. });
  2869. var ctxFlip = (ctx, flipX, flipY, pivot) => {
  2870. if (!flipX && !flipY)
  2871. return ctx;
  2872. ctx.translate(pivot.x, pivot.y);
  2873. ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
  2874. ctx.translate(-pivot.x, -pivot.y);
  2875. return ctx;
  2876. };
  2877. const drawShape = async (ctx, shape, options) => {
  2878. // center, needed for transforms
  2879. const center = shapeGetCenter(shape);
  2880. // rotate context
  2881. ctxRotate(ctx, shape.rotation, center);
  2882. // flip context
  2883. ctxFlip(ctx, shape.flipX, shape.flipY, center);
  2884. let fn;
  2885. if (shapeIsRect(shape)) {
  2886. fn = drawRect;
  2887. }
  2888. else if (shapeIsEllipse(shape)) {
  2889. fn = drawEllipse;
  2890. }
  2891. else if (shapeIsLine(shape)) {
  2892. fn = drawLine;
  2893. }
  2894. else if (shapeIsPath(shape)) {
  2895. fn = drawPath;
  2896. }
  2897. else if (shapeIsText(shape)) {
  2898. fn = drawText;
  2899. }
  2900. // get shapes
  2901. return fn ? [shape, ...(await drawShapes(ctx, await fn(ctx, shape, options), options))] : [];
  2902. };
  2903. var drawShapes = async (ctx, shapes, options) => {
  2904. let drawnShapes = [];
  2905. for (const shape of shapes) {
  2906. ctx.save();
  2907. // clears previous shape's path
  2908. ctx.beginPath();
  2909. // wait for shape to draw before drawing next shape
  2910. drawnShapes = [...drawnShapes, ...(await drawShape(ctx, shape, options))];
  2911. ctx.restore();
  2912. }
  2913. return drawnShapes;
  2914. };
  2915. var drawImageData = async (imageData, options = {}) => {
  2916. const { shapes = [], context = imageData, contextBounds = imageData, transform = noop$1, drawImage, preprocessShape = passthrough, } = options;
  2917. // no shapes to draw
  2918. if (!shapes.length)
  2919. return imageData;
  2920. // create drawing context
  2921. const canvas = h('canvas');
  2922. canvas.width = contextBounds.width;
  2923. canvas.height = contextBounds.height;
  2924. const ctx = canvas.getContext('2d');
  2925. ctx.putImageData(imageData, contextBounds.x || 0, contextBounds.y || 0);
  2926. // compute the position of all shapes
  2927. const computedShapes = shapes
  2928. .map(shapeDeepCopy)
  2929. .map((shape) => shapeComputeDisplay(shape, {
  2930. x: 0,
  2931. y: 0,
  2932. width: context.width,
  2933. height: context.height,
  2934. })) // need to take into account output size?
  2935. .map(preprocessShape)
  2936. .flat();
  2937. // compute transforms for all shapes
  2938. transform(ctx);
  2939. // draw shapes to canvas
  2940. await drawShapes(ctx, computedShapes, {
  2941. drawImage,
  2942. });
  2943. const imageDataOut = ctx.getImageData(0, 0, canvas.width, canvas.height);
  2944. releaseCanvas(canvas);
  2945. return imageDataOut;
  2946. };
  2947. var fillImageData = async (imageData, options = {}) => {
  2948. const { backgroundColor } = options;
  2949. // no background color set or is fully transparent background color
  2950. if (!backgroundColor || (backgroundColor && backgroundColor[3] === 0))
  2951. return imageData;
  2952. // fill
  2953. let imageDataOut;
  2954. let image = h('canvas');
  2955. image.width = imageData.width;
  2956. image.height = imageData.height;
  2957. const ctx = image.getContext('2d');
  2958. ctx.putImageData(imageData, 0, 0);
  2959. // fill behind image
  2960. ctx.globalCompositeOperation = 'destination-over';
  2961. ctx.fillStyle = colorArrayToRGBA(backgroundColor);
  2962. ctx.fillRect(0, 0, image.width, image.height);
  2963. imageDataOut = ctx.getImageData(0, 0, image.width, image.height);
  2964. releaseCanvas(image);
  2965. return imageDataOut;
  2966. };
  2967. var dotColorMatrix = (a, b) => {
  2968. const res = new Array(20);
  2969. // R
  2970. res[0] = a[0] * b[0] + a[1] * b[5] + a[2] * b[10] + a[3] * b[15];
  2971. res[1] = a[0] * b[1] + a[1] * b[6] + a[2] * b[11] + a[3] * b[16];
  2972. res[2] = a[0] * b[2] + a[1] * b[7] + a[2] * b[12] + a[3] * b[17];
  2973. res[3] = a[0] * b[3] + a[1] * b[8] + a[2] * b[13] + a[3] * b[18];
  2974. res[4] = a[0] * b[4] + a[1] * b[9] + a[2] * b[14] + a[3] * b[19] + a[4];
  2975. // G
  2976. res[5] = a[5] * b[0] + a[6] * b[5] + a[7] * b[10] + a[8] * b[15];
  2977. res[6] = a[5] * b[1] + a[6] * b[6] + a[7] * b[11] + a[8] * b[16];
  2978. res[7] = a[5] * b[2] + a[6] * b[7] + a[7] * b[12] + a[8] * b[17];
  2979. res[8] = a[5] * b[3] + a[6] * b[8] + a[7] * b[13] + a[8] * b[18];
  2980. res[9] = a[5] * b[4] + a[6] * b[9] + a[7] * b[14] + a[8] * b[19] + a[9];
  2981. // B
  2982. res[10] = a[10] * b[0] + a[11] * b[5] + a[12] * b[10] + a[13] * b[15];
  2983. res[11] = a[10] * b[1] + a[11] * b[6] + a[12] * b[11] + a[13] * b[16];
  2984. res[12] = a[10] * b[2] + a[11] * b[7] + a[12] * b[12] + a[13] * b[17];
  2985. res[13] = a[10] * b[3] + a[11] * b[8] + a[12] * b[13] + a[13] * b[18];
  2986. res[14] = a[10] * b[4] + a[11] * b[9] + a[12] * b[14] + a[13] * b[19] + a[14];
  2987. // A
  2988. res[15] = a[15] * b[0] + a[16] * b[5] + a[17] * b[10] + a[18] * b[15];
  2989. res[16] = a[15] * b[1] + a[16] * b[6] + a[17] * b[11] + a[18] * b[16];
  2990. res[17] = a[15] * b[2] + a[16] * b[7] + a[17] * b[12] + a[18] * b[17];
  2991. res[18] = a[15] * b[3] + a[16] * b[8] + a[17] * b[13] + a[18] * b[18];
  2992. res[19] = a[15] * b[4] + a[16] * b[9] + a[17] * b[14] + a[18] * b[19] + a[19];
  2993. return res;
  2994. };
  2995. var getColorMatrixFromColorMatrices = (colorMatrices) => colorMatrices.length
  2996. ? colorMatrices.reduce((previous, current) => dotColorMatrix([...previous], current), colorMatrices.shift())
  2997. : [];
  2998. var roundFraction = (value, fr = 2) => Math.round(value * fr) / fr;
  2999. var getImageRedactionScaleFactor = (imageSize, redactionShapes) => {
  3000. const imageRes = imageSize.width * imageSize.height;
  3001. const maxShapeSize = redactionShapes.reduce((max, shape) => {
  3002. if (shape.width > max.width && shape.height > max.height) {
  3003. max.width = shape.width;
  3004. max.height = shape.height;
  3005. }
  3006. return max;
  3007. }, { width: 0, height: 0 });
  3008. const maxShapeRes = maxShapeSize.width * maxShapeSize.height;
  3009. const fraction = Math.max(0.5, 0.5 + (1 - maxShapeRes / imageRes) / 2);
  3010. return roundFraction(fraction, 5);
  3011. };
  3012. function noop() { }
  3013. const identity = x => x;
  3014. function assign(tar, src) {
  3015. // @ts-ignore
  3016. for (const k in src)
  3017. tar[k] = src[k];
  3018. return tar;
  3019. }
  3020. function run(fn) {
  3021. return fn();
  3022. }
  3023. function blank_object() {
  3024. return Object.create(null);
  3025. }
  3026. function run_all(fns) {
  3027. fns.forEach(run);
  3028. }
  3029. function is_function(thing) {
  3030. return typeof thing === 'function';
  3031. }
  3032. function safe_not_equal(a, b) {
  3033. return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
  3034. }
  3035. function is_empty(obj) {
  3036. return Object.keys(obj).length === 0;
  3037. }
  3038. function subscribe(store, ...callbacks) {
  3039. if (store == null) {
  3040. return noop;
  3041. }
  3042. const unsub = store.subscribe(...callbacks);
  3043. return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
  3044. }
  3045. function get_store_value(store) {
  3046. let value;
  3047. subscribe(store, _ => value = _)();
  3048. return value;
  3049. }
  3050. function component_subscribe(component, store, callback) {
  3051. component.$$.on_destroy.push(subscribe(store, callback));
  3052. }
  3053. function create_slot(definition, ctx, $$scope, fn) {
  3054. if (definition) {
  3055. const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
  3056. return definition[0](slot_ctx);
  3057. }
  3058. }
  3059. function get_slot_context(definition, ctx, $$scope, fn) {
  3060. return definition[1] && fn
  3061. ? assign($$scope.ctx.slice(), definition[1](fn(ctx)))
  3062. : $$scope.ctx;
  3063. }
  3064. function get_slot_changes(definition, $$scope, dirty, fn) {
  3065. if (definition[2] && fn) {
  3066. const lets = definition[2](fn(dirty));
  3067. if ($$scope.dirty === undefined) {
  3068. return lets;
  3069. }
  3070. if (typeof lets === 'object') {
  3071. const merged = [];
  3072. const len = Math.max($$scope.dirty.length, lets.length);
  3073. for (let i = 0; i < len; i += 1) {
  3074. merged[i] = $$scope.dirty[i] | lets[i];
  3075. }
  3076. return merged;
  3077. }
  3078. return $$scope.dirty | lets;
  3079. }
  3080. return $$scope.dirty;
  3081. }
  3082. function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
  3083. const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
  3084. if (slot_changes) {
  3085. const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
  3086. slot.p(slot_context, slot_changes);
  3087. }
  3088. }
  3089. function exclude_internal_props(props) {
  3090. const result = {};
  3091. for (const k in props)
  3092. if (k[0] !== '$')
  3093. result[k] = props[k];
  3094. return result;
  3095. }
  3096. function compute_rest_props(props, keys) {
  3097. const rest = {};
  3098. keys = new Set(keys);
  3099. for (const k in props)
  3100. if (!keys.has(k) && k[0] !== '$')
  3101. rest[k] = props[k];
  3102. return rest;
  3103. }
  3104. function set_store_value(store, ret, value = ret) {
  3105. store.set(value);
  3106. return ret;
  3107. }
  3108. function action_destroyer(action_result) {
  3109. return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;
  3110. }
  3111. const is_client = typeof window !== 'undefined';
  3112. let now = is_client
  3113. ? () => window.performance.now()
  3114. : () => Date.now();
  3115. let raf = is_client ? cb => requestAnimationFrame(cb) : noop;
  3116. const tasks = new Set();
  3117. function run_tasks(now) {
  3118. tasks.forEach(task => {
  3119. if (!task.c(now)) {
  3120. tasks.delete(task);
  3121. task.f();
  3122. }
  3123. });
  3124. if (tasks.size !== 0)
  3125. raf(run_tasks);
  3126. }
  3127. /**
  3128. * Creates a new task that runs on each raf frame
  3129. * until it returns a falsy value or is aborted
  3130. */
  3131. function loop(callback) {
  3132. let task;
  3133. if (tasks.size === 0)
  3134. raf(run_tasks);
  3135. return {
  3136. promise: new Promise(fulfill => {
  3137. tasks.add(task = { c: callback, f: fulfill });
  3138. }),
  3139. abort() {
  3140. tasks.delete(task);
  3141. }
  3142. };
  3143. }
  3144. function append(target, node) {
  3145. target.appendChild(node);
  3146. }
  3147. function insert(target, node, anchor) {
  3148. target.insertBefore(node, anchor || null);
  3149. }
  3150. function detach(node) {
  3151. node.parentNode.removeChild(node);
  3152. }
  3153. function element(name) {
  3154. return document.createElement(name);
  3155. }
  3156. function svg_element(name) {
  3157. return document.createElementNS('http://www.w3.org/2000/svg', name);
  3158. }
  3159. function text(data) {
  3160. return document.createTextNode(data);
  3161. }
  3162. function space() {
  3163. return text(' ');
  3164. }
  3165. function empty() {
  3166. return text('');
  3167. }
  3168. function listen(node, event, handler, options) {
  3169. node.addEventListener(event, handler, options);
  3170. return () => node.removeEventListener(event, handler, options);
  3171. }
  3172. function prevent_default(fn) {
  3173. return function (event) {
  3174. event.preventDefault();
  3175. // @ts-ignore
  3176. return fn.call(this, event);
  3177. };
  3178. }
  3179. function stop_propagation(fn) {
  3180. return function (event) {
  3181. event.stopPropagation();
  3182. // @ts-ignore
  3183. return fn.call(this, event);
  3184. };
  3185. }
  3186. function attr(node, attribute, value) {
  3187. if (value == null)
  3188. node.removeAttribute(attribute);
  3189. else if (node.getAttribute(attribute) !== value)
  3190. node.setAttribute(attribute, value);
  3191. }
  3192. function set_attributes(node, attributes) {
  3193. // @ts-ignore
  3194. const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
  3195. for (const key in attributes) {
  3196. if (attributes[key] == null) {
  3197. node.removeAttribute(key);
  3198. }
  3199. else if (key === 'style') {
  3200. node.style.cssText = attributes[key];
  3201. }
  3202. else if (key === '__value') {
  3203. node.value = node[key] = attributes[key];
  3204. }
  3205. else if (descriptors[key] && descriptors[key].set) {
  3206. node[key] = attributes[key];
  3207. }
  3208. else {
  3209. attr(node, key, attributes[key]);
  3210. }
  3211. }
  3212. }
  3213. function children(element) {
  3214. return Array.from(element.childNodes);
  3215. }
  3216. function set_data(text, data) {
  3217. data = '' + data;
  3218. if (text.wholeText !== data)
  3219. text.data = data;
  3220. }
  3221. function set_input_value(input, value) {
  3222. input.value = value == null ? '' : value;
  3223. }
  3224. function set_style(node, key, value, important) {
  3225. node.style.setProperty(key, value, important ? 'important' : '');
  3226. }
  3227. function custom_event(type, detail) {
  3228. const e = document.createEvent('CustomEvent');
  3229. e.initCustomEvent(type, false, false, detail);
  3230. return e;
  3231. }
  3232. class HtmlTag {
  3233. constructor(anchor = null) {
  3234. this.a = anchor;
  3235. this.e = this.n = null;
  3236. }
  3237. m(html, target, anchor = null) {
  3238. if (!this.e) {
  3239. this.e = element(target.nodeName);
  3240. this.t = target;
  3241. this.h(html);
  3242. }
  3243. this.i(anchor);
  3244. }
  3245. h(html) {
  3246. this.e.innerHTML = html;
  3247. this.n = Array.from(this.e.childNodes);
  3248. }
  3249. i(anchor) {
  3250. for (let i = 0; i < this.n.length; i += 1) {
  3251. insert(this.t, this.n[i], anchor);
  3252. }
  3253. }
  3254. p(html) {
  3255. this.d();
  3256. this.h(html);
  3257. this.i(this.a);
  3258. }
  3259. d() {
  3260. this.n.forEach(detach);
  3261. }
  3262. }
  3263. const active_docs = new Set();
  3264. let active = 0;
  3265. // https://github.com/darkskyapp/string-hash/blob/master/index.js
  3266. function hash(str) {
  3267. let hash = 5381;
  3268. let i = str.length;
  3269. while (i--)
  3270. hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
  3271. return hash >>> 0;
  3272. }
  3273. function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
  3274. const step = 16.666 / duration;
  3275. let keyframes = '{\n';
  3276. for (let p = 0; p <= 1; p += step) {
  3277. const t = a + (b - a) * ease(p);
  3278. keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`;
  3279. }
  3280. const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
  3281. const name = `__svelte_${hash(rule)}_${uid}`;
  3282. const doc = node.ownerDocument;
  3283. active_docs.add(doc);
  3284. const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style')).sheet);
  3285. const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});
  3286. if (!current_rules[name]) {
  3287. current_rules[name] = true;
  3288. stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
  3289. }
  3290. const animation = node.style.animation || '';
  3291. node.style.animation = `${animation ? `${animation}, ` : ''}${name} ${duration}ms linear ${delay}ms 1 both`;
  3292. active += 1;
  3293. return name;
  3294. }
  3295. function delete_rule(node, name) {
  3296. const previous = (node.style.animation || '').split(', ');
  3297. const next = previous.filter(name
  3298. ? anim => anim.indexOf(name) < 0 // remove specific animation
  3299. : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations
  3300. );
  3301. const deleted = previous.length - next.length;
  3302. if (deleted) {
  3303. node.style.animation = next.join(', ');
  3304. active -= deleted;
  3305. if (!active)
  3306. clear_rules();
  3307. }
  3308. }
  3309. function clear_rules() {
  3310. raf(() => {
  3311. if (active)
  3312. return;
  3313. active_docs.forEach(doc => {
  3314. const stylesheet = doc.__svelte_stylesheet;
  3315. let i = stylesheet.cssRules.length;
  3316. while (i--)
  3317. stylesheet.deleteRule(i);
  3318. doc.__svelte_rules = {};
  3319. });
  3320. active_docs.clear();
  3321. });
  3322. }
  3323. let current_component;
  3324. function set_current_component(component) {
  3325. current_component = component;
  3326. }
  3327. function get_current_component() {
  3328. if (!current_component)
  3329. throw new Error('Function called outside component initialization');
  3330. return current_component;
  3331. }
  3332. function onMount(fn) {
  3333. get_current_component().$$.on_mount.push(fn);
  3334. }
  3335. function afterUpdate(fn) {
  3336. get_current_component().$$.after_update.push(fn);
  3337. }
  3338. function onDestroy(fn) {
  3339. get_current_component().$$.on_destroy.push(fn);
  3340. }
  3341. function createEventDispatcher() {
  3342. const component = get_current_component();
  3343. return (type, detail) => {
  3344. const callbacks = component.$$.callbacks[type];
  3345. if (callbacks) {
  3346. // TODO are there situations where events could be dispatched
  3347. // in a server (non-DOM) environment?
  3348. const event = custom_event(type, detail);
  3349. callbacks.slice().forEach(fn => {
  3350. fn.call(component, event);
  3351. });
  3352. }
  3353. };
  3354. }
  3355. function setContext(key, context) {
  3356. get_current_component().$$.context.set(key, context);
  3357. }
  3358. function getContext(key) {
  3359. return get_current_component().$$.context.get(key);
  3360. }
  3361. // TODO figure out if we still want to support
  3362. // shorthand events, or if we want to implement
  3363. // a real bubbling mechanism
  3364. function bubble(component, event) {
  3365. const callbacks = component.$$.callbacks[event.type];
  3366. if (callbacks) {
  3367. callbacks.slice().forEach(fn => fn(event));
  3368. }
  3369. }
  3370. const dirty_components = [];
  3371. const binding_callbacks = [];
  3372. const render_callbacks = [];
  3373. const flush_callbacks = [];
  3374. const resolved_promise = Promise.resolve();
  3375. let update_scheduled = false;
  3376. function schedule_update() {
  3377. if (!update_scheduled) {
  3378. update_scheduled = true;
  3379. resolved_promise.then(flush);
  3380. }
  3381. }
  3382. function add_render_callback(fn) {
  3383. render_callbacks.push(fn);
  3384. }
  3385. function add_flush_callback(fn) {
  3386. flush_callbacks.push(fn);
  3387. }
  3388. let flushing = false;
  3389. const seen_callbacks = new Set();
  3390. function flush() {
  3391. if (flushing)
  3392. return;
  3393. flushing = true;
  3394. do {
  3395. // first, call beforeUpdate functions
  3396. // and update components
  3397. for (let i = 0; i < dirty_components.length; i += 1) {
  3398. const component = dirty_components[i];
  3399. set_current_component(component);
  3400. update(component.$$);
  3401. }
  3402. set_current_component(null);
  3403. dirty_components.length = 0;
  3404. while (binding_callbacks.length)
  3405. binding_callbacks.pop()();
  3406. // then, once components are updated, call
  3407. // afterUpdate functions. This may cause
  3408. // subsequent updates...
  3409. for (let i = 0; i < render_callbacks.length; i += 1) {
  3410. const callback = render_callbacks[i];
  3411. if (!seen_callbacks.has(callback)) {
  3412. // ...so guard against infinite loops
  3413. seen_callbacks.add(callback);
  3414. callback();
  3415. }
  3416. }
  3417. render_callbacks.length = 0;
  3418. } while (dirty_components.length);
  3419. while (flush_callbacks.length) {
  3420. flush_callbacks.pop()();
  3421. }
  3422. update_scheduled = false;
  3423. flushing = false;
  3424. seen_callbacks.clear();
  3425. }
  3426. function update($$) {
  3427. if ($$.fragment !== null) {
  3428. $$.update();
  3429. run_all($$.before_update);
  3430. const dirty = $$.dirty;
  3431. $$.dirty = [-1];
  3432. $$.fragment && $$.fragment.p($$.ctx, dirty);
  3433. $$.after_update.forEach(add_render_callback);
  3434. }
  3435. }
  3436. let promise;
  3437. function wait() {
  3438. if (!promise) {
  3439. promise = Promise.resolve();
  3440. promise.then(() => {
  3441. promise = null;
  3442. });
  3443. }
  3444. return promise;
  3445. }
  3446. function dispatch(node, direction, kind) {
  3447. node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
  3448. }
  3449. const outroing = new Set();
  3450. let outros;
  3451. function group_outros() {
  3452. outros = {
  3453. r: 0,
  3454. c: [],
  3455. p: outros // parent group
  3456. };
  3457. }
  3458. function check_outros() {
  3459. if (!outros.r) {
  3460. run_all(outros.c);
  3461. }
  3462. outros = outros.p;
  3463. }
  3464. function transition_in(block, local) {
  3465. if (block && block.i) {
  3466. outroing.delete(block);
  3467. block.i(local);
  3468. }
  3469. }
  3470. function transition_out(block, local, detach, callback) {
  3471. if (block && block.o) {
  3472. if (outroing.has(block))
  3473. return;
  3474. outroing.add(block);
  3475. outros.c.push(() => {
  3476. outroing.delete(block);
  3477. if (callback) {
  3478. if (detach)
  3479. block.d(1);
  3480. callback();
  3481. }
  3482. });
  3483. block.o(local);
  3484. }
  3485. }
  3486. const null_transition = { duration: 0 };
  3487. function create_bidirectional_transition(node, fn, params, intro) {
  3488. let config = fn(node, params);
  3489. let t = intro ? 0 : 1;
  3490. let running_program = null;
  3491. let pending_program = null;
  3492. let animation_name = null;
  3493. function clear_animation() {
  3494. if (animation_name)
  3495. delete_rule(node, animation_name);
  3496. }
  3497. function init(program, duration) {
  3498. const d = program.b - t;
  3499. duration *= Math.abs(d);
  3500. return {
  3501. a: t,
  3502. b: program.b,
  3503. d,
  3504. duration,
  3505. start: program.start,
  3506. end: program.start + duration,
  3507. group: program.group
  3508. };
  3509. }
  3510. function go(b) {
  3511. const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;
  3512. const program = {
  3513. start: now() + delay,
  3514. b
  3515. };
  3516. if (!b) {
  3517. // @ts-ignore todo: improve typings
  3518. program.group = outros;
  3519. outros.r += 1;
  3520. }
  3521. if (running_program || pending_program) {
  3522. pending_program = program;
  3523. }
  3524. else {
  3525. // if this is an intro, and there's a delay, we need to do
  3526. // an initial tick and/or apply CSS animation immediately
  3527. if (css) {
  3528. clear_animation();
  3529. animation_name = create_rule(node, t, b, duration, delay, easing, css);
  3530. }
  3531. if (b)
  3532. tick(0, 1);
  3533. running_program = init(program, duration);
  3534. add_render_callback(() => dispatch(node, b, 'start'));
  3535. loop(now => {
  3536. if (pending_program && now > pending_program.start) {
  3537. running_program = init(pending_program, duration);
  3538. pending_program = null;
  3539. dispatch(node, running_program.b, 'start');
  3540. if (css) {
  3541. clear_animation();
  3542. animation_name = create_rule(node, t, running_program.b, running_program.duration, 0, easing, config.css);
  3543. }
  3544. }
  3545. if (running_program) {
  3546. if (now >= running_program.end) {
  3547. tick(t = running_program.b, 1 - t);
  3548. dispatch(node, running_program.b, 'end');
  3549. if (!pending_program) {
  3550. // we're done
  3551. if (running_program.b) {
  3552. // intro — we can tidy up immediately
  3553. clear_animation();
  3554. }
  3555. else {
  3556. // outro — needs to be coordinated
  3557. if (!--running_program.group.r)
  3558. run_all(running_program.group.c);
  3559. }
  3560. }
  3561. running_program = null;
  3562. }
  3563. else if (now >= running_program.start) {
  3564. const p = now - running_program.start;
  3565. t = running_program.a + running_program.d * easing(p / running_program.duration);
  3566. tick(t, 1 - t);
  3567. }
  3568. }
  3569. return !!(running_program || pending_program);
  3570. });
  3571. }
  3572. }
  3573. return {
  3574. run(b) {
  3575. if (is_function(config)) {
  3576. wait().then(() => {
  3577. // @ts-ignore
  3578. config = config();
  3579. go(b);
  3580. });
  3581. }
  3582. else {
  3583. go(b);
  3584. }
  3585. },
  3586. end() {
  3587. clear_animation();
  3588. running_program = pending_program = null;
  3589. }
  3590. };
  3591. }
  3592. const globals = (typeof window !== 'undefined'
  3593. ? window
  3594. : typeof globalThis !== 'undefined'
  3595. ? globalThis
  3596. : global);
  3597. function destroy_block(block, lookup) {
  3598. block.d(1);
  3599. lookup.delete(block.key);
  3600. }
  3601. function outro_and_destroy_block(block, lookup) {
  3602. transition_out(block, 1, 1, () => {
  3603. lookup.delete(block.key);
  3604. });
  3605. }
  3606. function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {
  3607. let o = old_blocks.length;
  3608. let n = list.length;
  3609. let i = o;
  3610. const old_indexes = {};
  3611. while (i--)
  3612. old_indexes[old_blocks[i].key] = i;
  3613. const new_blocks = [];
  3614. const new_lookup = new Map();
  3615. const deltas = new Map();
  3616. i = n;
  3617. while (i--) {
  3618. const child_ctx = get_context(ctx, list, i);
  3619. const key = get_key(child_ctx);
  3620. let block = lookup.get(key);
  3621. if (!block) {
  3622. block = create_each_block(key, child_ctx);
  3623. block.c();
  3624. }
  3625. else if (dynamic) {
  3626. block.p(child_ctx, dirty);
  3627. }
  3628. new_lookup.set(key, new_blocks[i] = block);
  3629. if (key in old_indexes)
  3630. deltas.set(key, Math.abs(i - old_indexes[key]));
  3631. }
  3632. const will_move = new Set();
  3633. const did_move = new Set();
  3634. function insert(block) {
  3635. transition_in(block, 1);
  3636. block.m(node, next);
  3637. lookup.set(block.key, block);
  3638. next = block.first;
  3639. n--;
  3640. }
  3641. while (o && n) {
  3642. const new_block = new_blocks[n - 1];
  3643. const old_block = old_blocks[o - 1];
  3644. const new_key = new_block.key;
  3645. const old_key = old_block.key;
  3646. if (new_block === old_block) {
  3647. // do nothing
  3648. next = new_block.first;
  3649. o--;
  3650. n--;
  3651. }
  3652. else if (!new_lookup.has(old_key)) {
  3653. // remove old block
  3654. destroy(old_block, lookup);
  3655. o--;
  3656. }
  3657. else if (!lookup.has(new_key) || will_move.has(new_key)) {
  3658. insert(new_block);
  3659. }
  3660. else if (did_move.has(old_key)) {
  3661. o--;
  3662. }
  3663. else if (deltas.get(new_key) > deltas.get(old_key)) {
  3664. did_move.add(new_key);
  3665. insert(new_block);
  3666. }
  3667. else {
  3668. will_move.add(old_key);
  3669. o--;
  3670. }
  3671. }
  3672. while (o--) {
  3673. const old_block = old_blocks[o];
  3674. if (!new_lookup.has(old_block.key))
  3675. destroy(old_block, lookup);
  3676. }
  3677. while (n)
  3678. insert(new_blocks[n - 1]);
  3679. return new_blocks;
  3680. }
  3681. function get_spread_update(levels, updates) {
  3682. const update = {};
  3683. const to_null_out = {};
  3684. const accounted_for = { $$scope: 1 };
  3685. let i = levels.length;
  3686. while (i--) {
  3687. const o = levels[i];
  3688. const n = updates[i];
  3689. if (n) {
  3690. for (const key in o) {
  3691. if (!(key in n))
  3692. to_null_out[key] = 1;
  3693. }
  3694. for (const key in n) {
  3695. if (!accounted_for[key]) {
  3696. update[key] = n[key];
  3697. accounted_for[key] = 1;
  3698. }
  3699. }
  3700. levels[i] = n;
  3701. }
  3702. else {
  3703. for (const key in o) {
  3704. accounted_for[key] = 1;
  3705. }
  3706. }
  3707. }
  3708. for (const key in to_null_out) {
  3709. if (!(key in update))
  3710. update[key] = undefined;
  3711. }
  3712. return update;
  3713. }
  3714. function get_spread_object(spread_props) {
  3715. return typeof spread_props === 'object' && spread_props !== null ? spread_props : {};
  3716. }
  3717. function bind(component, name, callback) {
  3718. const index = component.$$.props[name];
  3719. if (index !== undefined) {
  3720. component.$$.bound[index] = callback;
  3721. callback(component.$$.ctx[index]);
  3722. }
  3723. }
  3724. function create_component(block) {
  3725. block && block.c();
  3726. }
  3727. function mount_component(component, target, anchor, customElement) {
  3728. const { fragment, on_mount, on_destroy, after_update } = component.$$;
  3729. fragment && fragment.m(target, anchor);
  3730. if (!customElement) {
  3731. // onMount happens before the initial afterUpdate
  3732. add_render_callback(() => {
  3733. const new_on_destroy = on_mount.map(run).filter(is_function);
  3734. if (on_destroy) {
  3735. on_destroy.push(...new_on_destroy);
  3736. }
  3737. else {
  3738. // Edge case - component was destroyed immediately,
  3739. // most likely as a result of a binding initialising
  3740. run_all(new_on_destroy);
  3741. }
  3742. component.$$.on_mount = [];
  3743. });
  3744. }
  3745. after_update.forEach(add_render_callback);
  3746. }
  3747. function destroy_component(component, detaching) {
  3748. const $$ = component.$$;
  3749. if ($$.fragment !== null) {
  3750. run_all($$.on_destroy);
  3751. $$.fragment && $$.fragment.d(detaching);
  3752. // TODO null out other refs, including component.$$ (but need to
  3753. // preserve final state?)
  3754. $$.on_destroy = $$.fragment = null;
  3755. $$.ctx = [];
  3756. }
  3757. }
  3758. function make_dirty(component, i) {
  3759. if (component.$$.dirty[0] === -1) {
  3760. dirty_components.push(component);
  3761. schedule_update();
  3762. component.$$.dirty.fill(0);
  3763. }
  3764. component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
  3765. }
  3766. function init(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
  3767. const parent_component = current_component;
  3768. set_current_component(component);
  3769. const $$ = component.$$ = {
  3770. fragment: null,
  3771. ctx: null,
  3772. // state
  3773. props,
  3774. update: noop,
  3775. not_equal,
  3776. bound: blank_object(),
  3777. // lifecycle
  3778. on_mount: [],
  3779. on_destroy: [],
  3780. on_disconnect: [],
  3781. before_update: [],
  3782. after_update: [],
  3783. context: new Map(parent_component ? parent_component.$$.context : options.context || []),
  3784. // everything else
  3785. callbacks: blank_object(),
  3786. dirty,
  3787. skip_bound: false
  3788. };
  3789. let ready = false;
  3790. $$.ctx = instance
  3791. ? instance(component, options.props || {}, (i, ret, ...rest) => {
  3792. const value = rest.length ? rest[0] : ret;
  3793. if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
  3794. if (!$$.skip_bound && $$.bound[i])
  3795. $$.bound[i](value);
  3796. if (ready)
  3797. make_dirty(component, i);
  3798. }
  3799. return ret;
  3800. })
  3801. : [];
  3802. $$.update();
  3803. ready = true;
  3804. run_all($$.before_update);
  3805. // `false` as a special case of no DOM component
  3806. $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
  3807. if (options.target) {
  3808. if (options.hydrate) {
  3809. const nodes = children(options.target);
  3810. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  3811. $$.fragment && $$.fragment.l(nodes);
  3812. nodes.forEach(detach);
  3813. }
  3814. else {
  3815. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  3816. $$.fragment && $$.fragment.c();
  3817. }
  3818. if (options.intro)
  3819. transition_in(component.$$.fragment);
  3820. mount_component(component, options.target, options.anchor, options.customElement);
  3821. flush();
  3822. }
  3823. set_current_component(parent_component);
  3824. }
  3825. /**
  3826. * Base class for Svelte components. Used when dev=false.
  3827. */
  3828. class SvelteComponent {
  3829. $destroy() {
  3830. destroy_component(this, 1);
  3831. this.$destroy = noop;
  3832. }
  3833. $on(type, callback) {
  3834. const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
  3835. callbacks.push(callback);
  3836. return () => {
  3837. const index = callbacks.indexOf(callback);
  3838. if (index !== -1)
  3839. callbacks.splice(index, 1);
  3840. };
  3841. }
  3842. $set($$props) {
  3843. if (this.$$set && !is_empty($$props)) {
  3844. this.$$.skip_bound = true;
  3845. this.$$set($$props);
  3846. this.$$.skip_bound = false;
  3847. }
  3848. }
  3849. }
  3850. const subscriber_queue = [];
  3851. /**
  3852. * Creates a `Readable` store that allows reading by subscription.
  3853. * @param value initial value
  3854. * @param {StartStopNotifier}start start and stop notifications for subscriptions
  3855. */
  3856. function readable(value, start) {
  3857. return {
  3858. subscribe: writable(value, start).subscribe
  3859. };
  3860. }
  3861. /**
  3862. * Create a `Writable` store that allows both updating and reading by subscription.
  3863. * @param {*=}value initial value
  3864. * @param {StartStopNotifier=}start start and stop notifications for subscriptions
  3865. */
  3866. function writable(value, start = noop) {
  3867. let stop;
  3868. const subscribers = [];
  3869. function set(new_value) {
  3870. if (safe_not_equal(value, new_value)) {
  3871. value = new_value;
  3872. if (stop) { // store is ready
  3873. const run_queue = !subscriber_queue.length;
  3874. for (let i = 0; i < subscribers.length; i += 1) {
  3875. const s = subscribers[i];
  3876. s[1]();
  3877. subscriber_queue.push(s, value);
  3878. }
  3879. if (run_queue) {
  3880. for (let i = 0; i < subscriber_queue.length; i += 2) {
  3881. subscriber_queue[i][0](subscriber_queue[i + 1]);
  3882. }
  3883. subscriber_queue.length = 0;
  3884. }
  3885. }
  3886. }
  3887. }
  3888. function update(fn) {
  3889. set(fn(value));
  3890. }
  3891. function subscribe(run, invalidate = noop) {
  3892. const subscriber = [run, invalidate];
  3893. subscribers.push(subscriber);
  3894. if (subscribers.length === 1) {
  3895. stop = start(set) || noop;
  3896. }
  3897. run(value);
  3898. return () => {
  3899. const index = subscribers.indexOf(subscriber);
  3900. if (index !== -1) {
  3901. subscribers.splice(index, 1);
  3902. }
  3903. if (subscribers.length === 0) {
  3904. stop();
  3905. stop = null;
  3906. }
  3907. };
  3908. }
  3909. return { set, update, subscribe };
  3910. }
  3911. function derived(stores, fn, initial_value) {
  3912. const single = !Array.isArray(stores);
  3913. const stores_array = single
  3914. ? [stores]
  3915. : stores;
  3916. const auto = fn.length < 2;
  3917. return readable(initial_value, (set) => {
  3918. let inited = false;
  3919. const values = [];
  3920. let pending = 0;
  3921. let cleanup = noop;
  3922. const sync = () => {
  3923. if (pending) {
  3924. return;
  3925. }
  3926. cleanup();
  3927. const result = fn(single ? values[0] : values, set);
  3928. if (auto) {
  3929. set(result);
  3930. }
  3931. else {
  3932. cleanup = is_function(result) ? result : noop;
  3933. }
  3934. };
  3935. const unsubscribers = stores_array.map((store, i) => subscribe(store, (value) => {
  3936. values[i] = value;
  3937. pending &= ~(1 << i);
  3938. if (inited) {
  3939. sync();
  3940. }
  3941. }, () => {
  3942. pending |= (1 << i);
  3943. }));
  3944. inited = true;
  3945. sync();
  3946. return function stop() {
  3947. run_all(unsubscribers);
  3948. cleanup();
  3949. };
  3950. });
  3951. }
  3952. var mergeObjects = (objects) => objects.reduce((prev, curr) => Object.assign(prev, curr), {});
  3953. // @ts-ignore
  3954. const UPDATE_VALUE = (updateValue) => ({ updateValue });
  3955. const DEFAULT_VALUE = (defaultValue) => ({ defaultValue });
  3956. const CUSTOM_STORE = (fn) => ({ store: fn });
  3957. // @ts-ignore
  3958. const DERIVED_STORE = (fn) => ({ store: (defaultValue, stores) => derived(...fn(stores)) });
  3959. const UNIQUE_DERIVED_STORE = (fn) => ({
  3960. store: (defaultValue, stores) => {
  3961. const [selectedStores, update, isEqual = () => false] = fn(stores);
  3962. let isFirst = true;
  3963. let currentValue;
  3964. return derived(selectedStores, (storeValues, set) => {
  3965. update(storeValues, (value) => {
  3966. if (!isFirst && isEqual(currentValue, value))
  3967. return;
  3968. currentValue = value;
  3969. isFirst = false;
  3970. set(value);
  3971. });
  3972. });
  3973. },
  3974. });
  3975. const MAP_STORE = (fn) => ({
  3976. store: (defaultValue, stores) => {
  3977. const [valueMapper, observedStores = {}, sorter = undefined] = fn(stores);
  3978. let storedItems = [];
  3979. let $observedStores = {};
  3980. const mapValue = (item) => valueMapper(item, $observedStores);
  3981. // set default properties for each item
  3982. const setValue = (items) => {
  3983. // was empty, still empty
  3984. if (!storedItems.length && !items.length)
  3985. return;
  3986. // update value
  3987. storedItems = items;
  3988. updateValue();
  3989. };
  3990. const updateValue = () => {
  3991. const mappedItems = storedItems.map(mapValue);
  3992. if (sorter)
  3993. mappedItems.sort(sorter);
  3994. storedItems = [...mappedItems];
  3995. set(mappedItems);
  3996. };
  3997. // TODO: need to at some point unsub from these stores
  3998. Object.entries(observedStores).map(([name, store]) => {
  3999. return store.subscribe((value) => {
  4000. $observedStores[name] = value;
  4001. if (!value)
  4002. return;
  4003. updateValue();
  4004. });
  4005. });
  4006. const { subscribe, set } = writable(defaultValue || []);
  4007. return {
  4008. set: setValue,
  4009. update: (fn) => setValue(fn(storedItems)),
  4010. subscribe,
  4011. };
  4012. },
  4013. });
  4014. const createStore = (accessors, stores, options) => {
  4015. const { store = (defaultValue) => writable(defaultValue), defaultValue = noop$1, // should be a function returning the default value
  4016. updateValue = undefined, } = options;
  4017. // create our private store
  4018. const storeInstance = store(defaultValue(), stores, accessors);
  4019. const { subscribe, update = noop$1 } = storeInstance; // update = noop because not all stores can be updated
  4020. // on update private store
  4021. let unsub;
  4022. const onUpdate = (cb) => {
  4023. let ignoreFirstCallback = true;
  4024. if (unsub)
  4025. unsub();
  4026. unsub = subscribe((value) => {
  4027. // need to ignore first callback because that returns current value
  4028. if (ignoreFirstCallback)
  4029. return (ignoreFirstCallback = false);
  4030. // now we have the newly assigned value
  4031. cb(value);
  4032. unsub();
  4033. unsub = undefined;
  4034. });
  4035. };
  4036. // create the value updater function, needs access to stores so can read all store values
  4037. const updateStoreValue = updateValue ? updateValue(accessors) : passthrough;
  4038. // set and validate value
  4039. storeInstance.set = (nextValue) => update((previousValue) => updateStoreValue(nextValue, previousValue, onUpdate));
  4040. // set default value for external reference
  4041. storeInstance.defaultValue = defaultValue;
  4042. // expose store api
  4043. return storeInstance;
  4044. };
  4045. var createStores = (props) => {
  4046. const stores = {};
  4047. const accessors = {};
  4048. props.forEach(([name, ...options]) => {
  4049. const opts = mergeObjects(options);
  4050. const store = (stores[name] = createStore(accessors, stores, opts));
  4051. const property = {
  4052. get: () => get_store_value(store),
  4053. set: store.set,
  4054. };
  4055. Object.defineProperty(accessors, name, property);
  4056. });
  4057. return {
  4058. stores,
  4059. accessors,
  4060. };
  4061. };
  4062. var props = [
  4063. // io
  4064. ['src'],
  4065. ['imageReader'],
  4066. ['imageWriter'],
  4067. // will process markup items before rendering, used by arrows and frames
  4068. ['shapePreprocessor'],
  4069. // will scramble image data for use with image redaction logic
  4070. ['imageScrambler'],
  4071. // current images
  4072. ['images', DEFAULT_VALUE(() => [])],
  4073. ];
  4074. var capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
  4075. var defineMethods = (object, api) => {
  4076. Object.keys(api).forEach((name) => {
  4077. const descriptor = isFunction(api[name])
  4078. ? {
  4079. value: api[name],
  4080. writable: false,
  4081. }
  4082. : api[name];
  4083. Object.defineProperty(object, name, descriptor);
  4084. });
  4085. };
  4086. const scalar = 10000;
  4087. var offsetRectToFitPolygon = (rect, poly) => {
  4088. const polyLines = quadLines(poly);
  4089. const offset = vectorCreateEmpty();
  4090. const rectVertexes = rectGetCorners(rect);
  4091. // we can fit it
  4092. rectVertexes.forEach((vertex) => {
  4093. // we update each corner by adding the current offset
  4094. vectorAdd(vertex, offset);
  4095. // test if point lies in polygon, if so, all is fine and we can exit
  4096. if (pointInPoly(vertex, poly))
  4097. return;
  4098. polyLines.forEach((line) => {
  4099. // get angle of edge and draw a ray from the corner perpendicular to the edge
  4100. const a = Math.atan2(line.start.y - line.end.y, line.start.x - line.end.x);
  4101. const x = Math.sin(Math.PI - a) * scalar;
  4102. const y = Math.cos(Math.PI - a) * scalar;
  4103. const ray = vectorCreate(vertex.x + x, vertex.y + y);
  4104. // extend the poly line so even if we overshoot the polygon we hit it
  4105. const lineExtended = lineExtend(lineClone(line), scalar);
  4106. // get the resulting intersection (there's always an intersection)
  4107. const intersection = lineLineIntersection(lineCreate(vertex, ray), lineExtended);
  4108. // no intersection, no need to do anything
  4109. if (!intersection)
  4110. return;
  4111. // update offset to move towards image
  4112. vectorAdd(offset, vectorSubtract(vectorClone(intersection), vertex));
  4113. });
  4114. });
  4115. // test if any vertexes still fall outside of poly, if so, we can't fit the rect
  4116. const rectOffset = rectClone(rect);
  4117. vectorAdd(rectOffset, offset);
  4118. const rectOffsetVertices = rectGetCorners(rectOffset);
  4119. const fits = rectOffsetVertices.every((vertex) => pointInPoly(vertex, poly));
  4120. if (fits) {
  4121. rectUpdateWithRect(rect, rectOffset);
  4122. return true;
  4123. }
  4124. return false;
  4125. };
  4126. var limitCropRectToImage = (rect, poly) => {
  4127. // get crop rect polygon vertexes
  4128. const rectVertexes = rectGetCorners(rect);
  4129. // if we end up here it doesn't fit, we might need to adjust
  4130. const polyLines = quadLines(poly)
  4131. // extend the poly lines a tiny bit so we
  4132. // don't shoot rays between line gaps at corners
  4133. // this caused one intersection to be missing resulting
  4134. // in error while manipulating crop edges
  4135. // (rotate image 90degrees -> drag bottom edge) (2021-04-09)
  4136. .map((line) => lineExtend(line, 5));
  4137. const rectCenterPosition = rectCenter(rect);
  4138. const intersections = [];
  4139. rectVertexes.forEach((rectVertex) => {
  4140. const ray = lineMultiply(lineCreate(vectorClone(rectCenterPosition), vectorClone(rectVertex)), 1000000);
  4141. let intersectionFound = false;
  4142. polyLines.map(lineClone).forEach((line) => {
  4143. const intersection = lineLineIntersection(ray, line);
  4144. if (!intersection || intersectionFound)
  4145. return;
  4146. intersections.push(intersection);
  4147. intersectionFound = true;
  4148. });
  4149. });
  4150. // top left -> bottom right
  4151. const tlbr = vectorDistance(intersections[0], intersections[2]);
  4152. // top right -> bottom left
  4153. const trbl = vectorDistance(intersections[1], intersections[3]);
  4154. // calculate smallest rectangle we can make, use that
  4155. const rectLimitedVertices = tlbr < trbl ? [intersections[0], intersections[2]] : [intersections[1], intersections[3]];
  4156. const rectLimitedToImage = rectCreateFromPoints(rectLimitedVertices);
  4157. // only use our fitted crop rectangle if it's smaller than our current rectangle,
  4158. // this would mean that our current rectangle couldn't be moved to make it fit
  4159. if (rectLimitedToImage.width < rect.width) {
  4160. // need to center on previous rect
  4161. rectUpdateWithRect(rect, rectLimitedToImage);
  4162. return true;
  4163. }
  4164. return false;
  4165. };
  4166. var getImagePolygon = (image, imageRotation, imagePerspective = { x: 0, y: 0 }) => {
  4167. const imageRect = rectCreateFromSize(image);
  4168. const imageCenter = rectCenter(imageRect);
  4169. const imagePoly = rectApplyPerspective(imageRect, imagePerspective, imageCenter).map((imageVertex) => vectorRotate(imageVertex, imageRotation, imageCenter));
  4170. // get image poly bounds, we need this to offset the poly vertices from 0,0
  4171. const imagePolyBounds = rectCreateFromPoints(imagePoly);
  4172. // get image polygon vertexes
  4173. return imagePoly.map((imageVertex) => vectorSubtract(imageVertex, imagePolyBounds));
  4174. };
  4175. var getMaxSizeInRect = (size, rotation = 0, aspectRatio = rectAspectRatio(size)) => {
  4176. let width;
  4177. let height;
  4178. if (rotation !== 0) {
  4179. const innerAngle = Math.atan2(1, aspectRatio);
  4180. const rotationSigned = Math.sign(rotation) * rotation;
  4181. const rotationSignedMod = rotationSigned % Math.PI;
  4182. const rotationSignedModHalf = rotationSigned % HALF_PI;
  4183. // determine if is turned on side
  4184. let hyp;
  4185. let r;
  4186. if (rotationSignedMod > QUART_PI && rotationSignedMod < HALF_PI + QUART_PI) {
  4187. r = rotationSignedModHalf > QUART_PI ? rotationSigned : HALF_PI - rotationSignedModHalf;
  4188. }
  4189. else {
  4190. r = rotationSignedModHalf > QUART_PI ? HALF_PI - rotationSignedModHalf : rotationSigned;
  4191. }
  4192. hyp = Math.min(Math.abs(size.height / Math.sin(innerAngle + r)), Math.abs(size.width / Math.cos(innerAngle - r)));
  4193. width = Math.cos(innerAngle) * hyp;
  4194. height = width / aspectRatio;
  4195. }
  4196. else {
  4197. width = size.width;
  4198. height = width / aspectRatio;
  4199. if (height > size.height) {
  4200. height = size.height;
  4201. width = height * aspectRatio;
  4202. }
  4203. }
  4204. return sizeCreate(width, height);
  4205. };
  4206. var limitRectToImage = (rect, imageSize, imageRotation = 0, imagePerspective = vectorCreateEmpty(), minSize) => {
  4207. // rotation and/or perspective, let's use the "advanced" collision detection method
  4208. if ((isNumber(imageRotation) && imageRotation !== 0) ||
  4209. imagePerspective.x ||
  4210. imagePerspective.y) {
  4211. const inputAspectRatio = rectAspectRatio(rect);
  4212. // test if crop can fit image, if it can, offset the crop so it fits
  4213. const imagePolygon = getImagePolygon(imageSize, imageRotation, imagePerspective);
  4214. const maxSizeInRect = getMaxSizeInRect(imageSize, imageRotation, inputAspectRatio);
  4215. const canFit = rect.width < maxSizeInRect.width && rect.height < maxSizeInRect.height;
  4216. if (!canFit) {
  4217. const dx = rect.width * 0.5 - maxSizeInRect.width * 0.5;
  4218. const dy = rect.height * 0.5 - maxSizeInRect.height * 0.5;
  4219. // adjust crop rect to max size
  4220. if (rect.width > maxSizeInRect.width) {
  4221. rect.width = maxSizeInRect.width;
  4222. rect.x += dx;
  4223. }
  4224. if (rect.height > maxSizeInRect.height) {
  4225. rect.height = maxSizeInRect.height;
  4226. rect.y += dy;
  4227. }
  4228. // test if has exceeded min size, if so we need to limit the size and recalculate the other edge
  4229. /*
  4230. -\
  4231. / ---\
  4232. h2 ---\
  4233. / ---\
  4234. +--------w---------+\
  4235. /| | ---\
  4236. / | | ---\
  4237. / | | ---\
  4238. / | | --
  4239. h1 | | /
  4240. / | | /
  4241. / | | /
  4242. -\ | | /
  4243. ---\ | | /
  4244. --+------------------+ /
  4245. ---\ /
  4246. --\ /
  4247. ---\ /
  4248. ---\ /
  4249. ---\ /
  4250. --
  4251. */
  4252. }
  4253. offsetRectToFitPolygon(rect, imagePolygon);
  4254. const wasLimited = limitCropRectToImage(rect, imagePolygon);
  4255. // this makes sure that after limiting the size, the crop rect is moved to a position that is inside the image
  4256. if (wasLimited)
  4257. offsetRectToFitPolygon(rect, imagePolygon);
  4258. }
  4259. // no rotation, no perspective, use simple bounds method
  4260. else {
  4261. // remember intended aspect ratio so we can try and recreate it
  4262. let intendedAspectRatio = rectAspectRatio(rect);
  4263. // limit to image size first, can never exceed that
  4264. rect.width = Math.min(rect.width, imageSize.width);
  4265. rect.height = Math.min(rect.height, imageSize.height);
  4266. // reposition rect so it's always inside image bounds
  4267. rect.x = Math.max(rect.x, 0);
  4268. if (rect.x + rect.width > imageSize.width) {
  4269. rect.x -= rect.x + rect.width - imageSize.width;
  4270. }
  4271. rect.y = Math.max(rect.y, 0);
  4272. if (rect.y + rect.height > imageSize.height) {
  4273. rect.y -= rect.y + rect.height - imageSize.height;
  4274. }
  4275. // we get the center of the current rect so we can center the contained rect to it
  4276. const intendedCenter = rectCenter(rect);
  4277. // make sure still adheres to aspect ratio
  4278. const containedRect = rectContainRect(rect, intendedAspectRatio);
  4279. containedRect.width = Math.max(minSize.width, containedRect.width);
  4280. containedRect.height = Math.max(minSize.height, containedRect.height);
  4281. containedRect.x = intendedCenter.x - containedRect.width * 0.5;
  4282. containedRect.y = intendedCenter.y - containedRect.height * 0.5;
  4283. rectUpdateWithRect(rect, containedRect);
  4284. }
  4285. };
  4286. var applyCropRectAction = (cropRectPrevious, cropRectNext, imageSize, imageRotation, imagePerspective, cropLimitToImageBounds, cropMinSize, cropMaxSize) => {
  4287. // clone
  4288. const minSize = sizeClone(cropMinSize);
  4289. // set upper bounds to crop max size
  4290. const maxSize = sizeClone(cropMaxSize);
  4291. // limit max size (more important that min size is respected so first limit max size)
  4292. const maxScalar = fixPrecision(Math.max(cropRectNext.width / maxSize.width, cropRectNext.height / maxSize.height));
  4293. const minScalar = fixPrecision(Math.min(cropRectNext.width / minSize.width, cropRectNext.height / minSize.height));
  4294. // clone for resulting crop rect
  4295. const cropRectOut = rectClone(cropRectNext);
  4296. //
  4297. // if exceeds min or max scale correct next crop rectangle to conform to bounds
  4298. //
  4299. if (minScalar < 1 || maxScalar > 1) {
  4300. // center of both previous and next crop rects
  4301. const previousCropRectCenter = rectCenter(cropRectPrevious);
  4302. const nextCropRectCenter = rectCenter(cropRectNext);
  4303. // calculate scales
  4304. const scalar = minScalar < 1 ? minScalar : maxScalar;
  4305. const cx = (nextCropRectCenter.x + previousCropRectCenter.x) / 2;
  4306. const cy = (nextCropRectCenter.y + previousCropRectCenter.y) / 2;
  4307. const cw = cropRectOut.width / scalar;
  4308. const ch = cropRectOut.height / scalar;
  4309. rectUpdate(cropRectOut, cx - cw * 0.5, cy - ch * 0.5, cw, ch);
  4310. }
  4311. // no need to limit to bounds, let's go!
  4312. if (!cropLimitToImageBounds)
  4313. return {
  4314. crop: cropRectOut,
  4315. };
  4316. //
  4317. // make sure the crop is made inside the bounds of the image
  4318. //
  4319. limitRectToImage(cropRectOut, imageSize, imageRotation, imagePerspective, minSize);
  4320. return {
  4321. crop: cropRectOut,
  4322. };
  4323. };
  4324. var getBaseCropRect = (imageSize, transformedCropRect, imageRotation) => {
  4325. const imageRect = rectCreateFromSize(imageSize);
  4326. const imageCenter = rectCenter(imageRect);
  4327. const imageTransformedVertices = rectRotate(imageRect, imageRotation, imageCenter);
  4328. // get the rotated image bounds center (offset isn't relevant as crop is relative to top left image position)
  4329. const imageRotatedBoundsCenter = rectCenter(rectNormalizeOffset(rectCreateFromPoints(imageTransformedVertices)));
  4330. // get the center of the crop inside the rotated image
  4331. const cropCenterInTransformedImage = rectCenter(transformedCropRect);
  4332. // invert the rotation of the crop center around the rotated image center
  4333. const deRotatedCropCenter = vectorRotate(cropCenterInTransformedImage, -imageRotation, imageRotatedBoundsCenter);
  4334. // calculate crop distance from rotated image center
  4335. const cropFromCenterOfTransformedImage = vectorSubtract(deRotatedCropCenter, imageRotatedBoundsCenter);
  4336. // calculate original crop offset (from untransformed image)
  4337. const originalCropCenterOffset = vectorApply(vectorAdd(imageCenter, cropFromCenterOfTransformedImage), fixPrecision);
  4338. return rectCreate(originalCropCenterOffset.x - transformedCropRect.width * 0.5, originalCropCenterOffset.y - transformedCropRect.height * 0.5, transformedCropRect.width, transformedCropRect.height);
  4339. };
  4340. var clamp = (value, min, max) => Math.max(min, Math.min(value, max));
  4341. var applyRotationAction = (imageRotationPrevious, imageRotation, imageRotationRange, cropRect, imageSize, imagePerspective, cropLimitToImageBounds, cropRectOrigin, cropMinSize, cropMaxSize) => {
  4342. // clone
  4343. const minSize = sizeClone(cropMinSize);
  4344. // set upper bounds to crop max size if image is bigger than max size,
  4345. // else if should limit to image bounds use image size as limit
  4346. const maxSize = sizeClone(cropMaxSize);
  4347. if (cropLimitToImageBounds) {
  4348. maxSize.width = Math.min(cropMaxSize.width, imageSize.width);
  4349. maxSize.height = Math.min(cropMaxSize.height, imageSize.height);
  4350. }
  4351. let didAttemptDoubleTurn = false;
  4352. const rotate = (rotationPrevious, rotation) => {
  4353. // get the base crop rect (position of crop rect in untransformed image)
  4354. // if we have the base crop rect we can apply the new rotation to it
  4355. const cropRectBase = getBaseCropRect(imageSize, cropRect, rotationPrevious);
  4356. // calculate transforms based on new rotation and base crop rect
  4357. const imageRect = rectCreateFromSize(imageSize);
  4358. const imageCenter = rectCenter(imageRect);
  4359. const imageTransformedCorners = rectApplyPerspective(imageRect, imagePerspective, imageCenter);
  4360. // need this to correct for perspective centroid displacement
  4361. const perspectiveOffset = vectorSubtract(vectorClone(imageCenter), convexPolyCentroid(imageTransformedCorners));
  4362. // rotate around center of image
  4363. const cropCenter = vectorRotate(rectCenter(cropRectBase), rotation, imageCenter);
  4364. const rotateCropOffset = vectorSubtract(vectorClone(imageCenter), cropCenter);
  4365. // get center of image bounds and move to correct position
  4366. imageTransformedCorners.forEach((imageVertex) => vectorRotate(imageVertex, rotation, imageCenter));
  4367. const imageBoundsRect = rectCreateFromPoints(imageTransformedCorners);
  4368. const imageCentroid = convexPolyCentroid(imageTransformedCorners);
  4369. const cropOffset = vectorAdd(vectorSubtract(vectorSubtract(imageCentroid, rotateCropOffset), imageBoundsRect), perspectiveOffset);
  4370. // create output cropRect
  4371. const cropRectOut = rectCreate(cropOffset.x - cropRectBase.width * 0.5, cropOffset.y - cropRectBase.height * 0.5, cropRectBase.width, cropRectBase.height);
  4372. // if has size target, scale croprect to target size
  4373. if (cropRectOrigin) {
  4374. rectScale(cropRectOut, cropRectOrigin.width / cropRectOut.width);
  4375. }
  4376. // if should limit to image bounds
  4377. if (cropLimitToImageBounds) {
  4378. const imagePoly = getImagePolygon(imageSize, rotation, imagePerspective);
  4379. // offsetRectToFitPolygon(cropRectOut, imagePoly);
  4380. // commenting this fixes poly sliding problem when adjusting rotation
  4381. limitCropRectToImage(cropRectOut, imagePoly);
  4382. }
  4383. //#region if exceeds min or max adjust rotation to conform to bounds
  4384. const minScalar = fixPrecision(Math.min(cropRectOut.width / minSize.width, cropRectOut.height / minSize.height), 8);
  4385. const maxScalar = fixPrecision(Math.max(cropRectOut.width / maxSize.width, cropRectOut.height / maxSize.height), 8);
  4386. if (minScalar < 1 || maxScalar > 1) {
  4387. // determine if is full image turn
  4388. const isTurn = fixPrecision(Math.abs(rotation - rotationPrevious)) === fixPrecision(Math.PI / 2);
  4389. // try another turn if is turning image
  4390. if (isTurn && !didAttemptDoubleTurn) {
  4391. didAttemptDoubleTurn = true;
  4392. return rotate(imageRotationPrevious, imageRotationPrevious + Math.sign(rotation - rotationPrevious) * Math.PI);
  4393. }
  4394. }
  4395. //#endregion
  4396. return {
  4397. rotation,
  4398. crop: rectApply(cropRectOut, (v) => fixPrecision(v, 8)),
  4399. };
  4400. };
  4401. // amount of turns applied, we need this to correctly determine the allowed rotation range
  4402. const imageTurns = Math.sign(imageRotation) * Math.round(Math.abs(imageRotation) / HALF_PI) * HALF_PI;
  4403. const imageRotationClamped = clamp(imageRotation, imageTurns + imageRotationRange[0], imageTurns + imageRotationRange[1]);
  4404. // set new crop position
  4405. return rotate(imageRotationPrevious, imageRotationClamped);
  4406. };
  4407. // @ts-ignore
  4408. const ORDERED_STATE_PROPS = [
  4409. // requirements
  4410. 'cropLimitToImage',
  4411. 'cropMinSize',
  4412. 'cropMaxSize',
  4413. 'cropAspectRatio',
  4414. // selection -> flip -> rotate -> perspective -> crop
  4415. 'flipX',
  4416. 'flipY',
  4417. 'rotation',
  4418. 'crop',
  4419. // 'perspectiveX',
  4420. // 'perspectiveY',
  4421. // effects
  4422. 'colorMatrix',
  4423. 'convolutionMatrix',
  4424. 'gamma',
  4425. 'vignette',
  4426. // 'noise',
  4427. // shapes
  4428. 'redaction',
  4429. 'annotation',
  4430. 'decoration',
  4431. 'frame',
  4432. // other
  4433. 'backgroundColor',
  4434. 'targetSize',
  4435. 'metadata',
  4436. ];
  4437. const clone = (value) => {
  4438. if (isArray(value)) {
  4439. return value.map(clone);
  4440. }
  4441. else if (isObject(value)) {
  4442. return { ...value };
  4443. }
  4444. return value;
  4445. };
  4446. const filterShapeState = (shapes) => shapes.map((shape) => Object.entries(shape).reduce((copy, [key, value]) => {
  4447. if (key.startsWith('_'))
  4448. return copy;
  4449. copy[key] = value;
  4450. return copy;
  4451. }, {}));
  4452. var stateStore = (_, stores, accessors) => {
  4453. const observedStores = ORDERED_STATE_PROPS.map((key) => stores[key]);
  4454. // can only subscribe, setting is done directly through store accessors
  4455. // @ts-ignore
  4456. const { subscribe } = derived(observedStores, (values, set) => {
  4457. // create new state by looping over props in certain order
  4458. const state = ORDERED_STATE_PROPS.reduce((prev, curr, i) => {
  4459. prev[curr] = clone(values[i]);
  4460. return prev;
  4461. }, {});
  4462. // round crop if defined
  4463. state.crop && rectApply(state.crop, Math.round);
  4464. // remove internal state props from decoration and annotation
  4465. state.redaction = state.redaction && filterShapeState(state.redaction);
  4466. state.annotation = state.annotation && filterShapeState(state.annotation);
  4467. state.decoration = state.decoration && filterShapeState(state.decoration);
  4468. // set new state
  4469. set(state);
  4470. });
  4471. const setState = (state) => {
  4472. // requires at least some state to be supplied
  4473. if (!state)
  4474. return;
  4475. // make sure crop origin is reset
  4476. accessors.cropOrigin = undefined;
  4477. // apply new values
  4478. ORDERED_STATE_PROPS
  4479. // remove keys that weren't set
  4480. .filter((key) => hasProp(state, key))
  4481. // apply each key in order
  4482. .forEach((key) => {
  4483. accessors[key] = clone(state[key]);
  4484. });
  4485. };
  4486. return {
  4487. set: setState,
  4488. update: (fn) => setState(fn(null)),
  4489. subscribe,
  4490. };
  4491. };
  4492. var toNumericAspectRatio = (v) => {
  4493. if (!v)
  4494. return undefined;
  4495. if (/:/.test(v)) {
  4496. const [w, h] = v.split(':');
  4497. return w / h;
  4498. }
  4499. return parseFloat(v);
  4500. };
  4501. var arrayEqual = (a, b) => {
  4502. if (a.length !== b.length)
  4503. return false;
  4504. for (let i = 0; i < a.length; i++) {
  4505. if (a[i] !== b[i])
  4506. return false;
  4507. }
  4508. return true;
  4509. };
  4510. var padColorArray = (color = [0, 0, 0, 0], opacity = 1.0) => color.length === 4 ? color : [...color, opacity];
  4511. //
  4512. // constants
  4513. //
  4514. const MIN_ROTATION = -QUART_PI;
  4515. const MAX_ROTATION = QUART_PI;
  4516. //
  4517. // helper methods
  4518. //
  4519. const isCropCentered = (crop, imageSize, imageRotation) => {
  4520. const cropCenter = vectorApply(rectCenter(crop), (v) => fixPrecision(v, 8));
  4521. const imageRect = rectCreateFromSize(imageSize);
  4522. const imageCenter = rectCenter(imageRect);
  4523. const imageRotatedVertices = rectRotate(imageRect, imageRotation, imageCenter);
  4524. const imageBoundsCenter = vectorApply(sizeCenter(rectCreateFromPoints(imageRotatedVertices)), (v) => fixPrecision(v, 8));
  4525. const dx = Math.abs(imageBoundsCenter.x - cropCenter.x);
  4526. const dy = Math.abs(imageBoundsCenter.y - cropCenter.y);
  4527. return dx < 1 && dy < 1;
  4528. };
  4529. const isCropMaxSize = (cropRect, imageSize, rotation) => {
  4530. const maxSize = getMaxSizeInRect(imageSize, rotation, rectAspectRatio(cropRect));
  4531. return sizeEqual(sizeApply(maxSize, Math.round), sizeApply(sizeClone(cropRect), Math.round));
  4532. };
  4533. //
  4534. // updater methods
  4535. //
  4536. const updateCropRect = (props) => (cropNext, cropPrevious = cropNext) => {
  4537. // wait for image to load
  4538. const { loadState, size, cropMinSize, cropMaxSize, cropLimitToImage, cropAspectRatio, rotation, perspective, } = props;
  4539. // image hasn't loaded yet, use supplied crop rect
  4540. if ((!cropNext && !cropPrevious) || !loadState || !loadState.beforeComplete)
  4541. return cropNext;
  4542. // crop previous set, crop next set to undefined, set crop to fit image
  4543. if (!cropNext)
  4544. cropNext = rectCreateFromSize(getMaxSizeInRect(size, rotation, cropAspectRatio || rectAspectRatio(size)));
  4545. // apply the action
  4546. const res = applyCropRectAction(cropPrevious, cropNext, size, rotation, perspective, cropLimitToImage, cropMinSize, cropMaxSize);
  4547. const cropOut = rectApply(res.crop, (v) => fixPrecision(v, 8));
  4548. return cropOut;
  4549. };
  4550. const updateCropAspectRatio = (props) => (aspectRatioNext, aspectRatioPrevious) => {
  4551. const { loadState, crop, size, rotation, cropLimitToImage } = props;
  4552. const aspectRatio = toNumericAspectRatio(aspectRatioNext);
  4553. // no aspect ratio means custom aspect ratio so set to undefined
  4554. if (!aspectRatio)
  4555. return undefined;
  4556. // can't update crop if not defined yet
  4557. if (!crop || !loadState || !loadState.beforeComplete)
  4558. return aspectRatio;
  4559. // calculate difference between aspect ratios, if big difference, re-align in image
  4560. const aspectRatioDist = aspectRatioPrevious
  4561. ? Math.abs(aspectRatioNext - aspectRatioPrevious)
  4562. : 1;
  4563. // if crop centered scale up
  4564. if (isCropCentered(crop, size, rotation) && cropLimitToImage && aspectRatioDist >= 0.1) {
  4565. const imageSize = sizeTurn(sizeClone(size), rotation);
  4566. props.crop = rectApply(rectContainRect(rectCreateFromSize(imageSize), aspectRatioNext), fixPrecision);
  4567. }
  4568. else {
  4569. const cropSize = {
  4570. width: crop.height * aspectRatio,
  4571. height: crop.height,
  4572. };
  4573. const tx = (crop.width - cropSize.width) * 0.5;
  4574. const ty = (crop.height - cropSize.height) * 0.5;
  4575. props.crop = rectApply(rectCreate(crop.x + tx, crop.y + ty, cropSize.width, cropSize.height), fixPrecision);
  4576. }
  4577. return aspectRatio;
  4578. };
  4579. const updateCropLimitToImage = (props) => (limitToImageNext, limitToImagePrevious, onUpdate) => {
  4580. // skip if no crop defined
  4581. const { crop } = props;
  4582. if (!crop)
  4583. return limitToImageNext;
  4584. // if was not limiting previously and now set limiting make sure crop fits bounds
  4585. if (!limitToImagePrevious && limitToImageNext) {
  4586. onUpdate(() => (props.crop = rectClone(props.crop)));
  4587. }
  4588. return limitToImageNext;
  4589. };
  4590. const updateRotation = (props) => (rotationNext, rotationPrevious, onUpdate) => {
  4591. // when image rotation is updated we need to adjust the
  4592. // cropRect offset so rotation happens from cropRect center
  4593. // no change
  4594. if (rotationNext === rotationPrevious)
  4595. return rotationNext;
  4596. // get relevant data from store state
  4597. const { loadState, size, rotationRange, cropMinSize, cropMaxSize, crop, perspective, cropLimitToImage, cropOrigin, } = props;
  4598. // image not ready, exit!
  4599. if (!crop || !loadState || !loadState.beforeComplete)
  4600. return rotationNext;
  4601. // remember if current crop was at max size and centered, if so, resulting crop should also be at max size
  4602. const cropWasAtMaxSize = isCropMaxSize(crop, size, rotationPrevious);
  4603. const cropWasCentered = isCropCentered(crop, size, rotationPrevious);
  4604. // get new state
  4605. const res = applyRotationAction(rotationPrevious, rotationNext, rotationRange, crop, size, perspective, cropLimitToImage, cropOrigin, cropMinSize, cropMaxSize);
  4606. // if is centered, and initial crop was at max size expand crop to max size
  4607. if (cropWasAtMaxSize && cropWasCentered) {
  4608. const rect = getMaxSizeInRect(size, rotationNext, rectAspectRatio(res.crop));
  4609. // move top left corner
  4610. res.crop.x += res.crop.width * 0.5;
  4611. res.crop.y += res.crop.height * 0.5;
  4612. res.crop.x -= rect.width * 0.5;
  4613. res.crop.y -= rect.height * 0.5;
  4614. // update size to max size
  4615. res.crop.width = rect.width;
  4616. res.crop.height = rect.height;
  4617. }
  4618. // return validated rotation value, then, after we assign that value, we update the crop rect
  4619. // we may only call onUpdate if a change was made
  4620. onUpdate(() => {
  4621. props.crop = rectApply(res.crop, (v) => fixPrecision(v, 8));
  4622. });
  4623. // return result rotation (might have been rotated twice to fit crop rectangle)
  4624. return res.rotation;
  4625. };
  4626. // updates the range of valid rotation input
  4627. const updateRotationRange = (imageSize, imageIsRotatedSideways, cropMinSize, cropSize, cropLimitToImage) => {
  4628. if (!cropLimitToImage)
  4629. return [MIN_ROTATION, MAX_ROTATION];
  4630. /*
  4631. - 'a' is angle between diagonal and image height
  4632. - 'b' is angle between diagonal and crop height
  4633. - 'c' is angle between diagonal and image width
  4634. - resulting range is then a - b
  4635. +----------/\------------------------+
  4636. | / \ \ |
  4637. | / \ \ |
  4638. | / \ \ |
  4639. | \ \ \ |
  4640. | \ \ \ |
  4641. | \ \ \ |
  4642. | \ \ / |
  4643. | \ \ / |
  4644. | \ \ / |
  4645. | \\a/b |
  4646. +---------------------\--------------+
  4647. */
  4648. const scalar = Math.max(cropMinSize.width / cropSize.width, cropMinSize.height / cropSize.height);
  4649. const minSize = sizeCreate(cropSize.width * scalar, cropSize.height * scalar);
  4650. // the hypotenus is the length of the diagonal of the min crop size
  4651. const requiredSpace = sizeHypotenuse(minSize);
  4652. // minimum space available in horizontal / vertical direction
  4653. const availableSpace = Math.min(imageSize.width, imageSize.height);
  4654. // if there's enough space available, we can return the max range
  4655. if (requiredSpace < availableSpace)
  4656. return [MIN_ROTATION, MAX_ROTATION];
  4657. // if the image is turned we need to swap the width and height
  4658. const imageWidth = imageIsRotatedSideways ? imageSize.height : imageSize.width;
  4659. const imageHeight = imageIsRotatedSideways ? imageSize.width : imageSize.height;
  4660. // subtracting the angle between the hypotenuse and the crop itself
  4661. const a = Math.acos(minSize.height / requiredSpace);
  4662. const b = Math.acos(imageHeight / requiredSpace);
  4663. const c = Math.asin(imageWidth / requiredSpace);
  4664. const rangeHorizontal = a - b;
  4665. const rangeVertical = c - a;
  4666. // range is not a number, it means we can rotate as much as we want
  4667. if (Number.isNaN(rangeHorizontal) && Number.isNaN(rangeVertical))
  4668. return [MIN_ROTATION, MAX_ROTATION];
  4669. // get minimum range
  4670. const range = Number.isNaN(rangeHorizontal)
  4671. ? rangeVertical
  4672. : Number.isNaN(rangeVertical)
  4673. ? rangeHorizontal
  4674. : Math.min(rangeHorizontal, rangeVertical);
  4675. // if not, limit range to min and max rotation
  4676. const rangeMin = Math.max(-range, MIN_ROTATION);
  4677. const rangeMax = Math.min(range, MAX_ROTATION);
  4678. return [rangeMin, rangeMax];
  4679. };
  4680. // updates the range of valid crop rectangle input
  4681. const updateCropRange = (imageSize, rotation, cropAspectRatio, cropMinSize, cropMaxSize, cropLimitToImage) => {
  4682. // ! rotation doesn't affect min size, only max size
  4683. // set lower bounds to crop min size
  4684. const minSize = sizeClone(cropMinSize);
  4685. // set upper bounds to crop max size
  4686. const maxSize = sizeClone(cropMaxSize);
  4687. // now we got basic bounds, let's see if we should limit to the image bounds, else we done
  4688. if (!cropLimitToImage)
  4689. return [minSize, maxSize];
  4690. return [minSize, sizeApply(getMaxSizeInRect(imageSize, rotation, cropAspectRatio), Math.round)];
  4691. };
  4692. const formatShape = (shape, options) => {
  4693. const { context, props } = options;
  4694. // only auto-format once
  4695. if (!shape._isFormatted) {
  4696. shape = shapeFormat(shape);
  4697. shape._isFormatted = true;
  4698. Object.assign(shape, props);
  4699. }
  4700. // we need to make sure shape is still correctly positioned relative to parent context
  4701. // draft cannot be relative
  4702. // if context changed
  4703. // if has left top right or bottom
  4704. if (!shape._isDraft &&
  4705. shapeHasRelativeSize(shape) &&
  4706. (!shape._context || !rectEqual(context, shape._context))) {
  4707. shape = shapeComputeRect(shape, context);
  4708. shape._context = { ...context };
  4709. }
  4710. return shape;
  4711. };
  4712. const updateFrame = () => (frameShapeNext) => {
  4713. if (!frameShapeNext)
  4714. return;
  4715. const shape = {
  4716. frameStyle: undefined,
  4717. x: 0,
  4718. y: 0,
  4719. width: '100%',
  4720. height: '100%',
  4721. disableStyle: ['backgroundColor', 'strokeColor', 'strokeWidth'],
  4722. };
  4723. if (isString(frameShapeNext)) {
  4724. shape.frameStyle = frameShapeNext;
  4725. }
  4726. else {
  4727. Object.assign(shape, frameShapeNext);
  4728. }
  4729. return shape;
  4730. };
  4731. var imageProps = [
  4732. // image info received from read
  4733. ['file'],
  4734. ['size'],
  4735. // loading and processing state
  4736. ['loadState'],
  4737. ['processState'],
  4738. // derived info
  4739. [
  4740. 'aspectRatio',
  4741. DERIVED_STORE(({ size }) => [
  4742. size,
  4743. ($size) => ($size ? rectAspectRatio($size) : undefined),
  4744. ]),
  4745. ],
  4746. // image modifications
  4747. ['perspectiveX', DEFAULT_VALUE(() => 0)],
  4748. ['perspectiveY', DEFAULT_VALUE(() => 0)],
  4749. [
  4750. 'perspective',
  4751. DERIVED_STORE(({ perspectiveX, perspectiveY }) => [
  4752. [perspectiveX, perspectiveY],
  4753. ([x, y]) => ({ x, y }),
  4754. ]),
  4755. ],
  4756. ['rotation', DEFAULT_VALUE(() => 0), UPDATE_VALUE(updateRotation)],
  4757. ['flipX', DEFAULT_VALUE(() => false)],
  4758. ['flipY', DEFAULT_VALUE(() => false)],
  4759. ['flip', DERIVED_STORE(({ flipX, flipY }) => [[flipX, flipY], ([x, y]) => ({ x, y })])],
  4760. [
  4761. 'isRotatedSideways',
  4762. UNIQUE_DERIVED_STORE(({ rotation }) => [
  4763. [rotation],
  4764. ([$rotation], set) => set(isRotatedSideways($rotation)),
  4765. (prevValue, nextValue) => prevValue !== nextValue,
  4766. ]),
  4767. ],
  4768. ['crop', UPDATE_VALUE(updateCropRect)],
  4769. ['cropAspectRatio', UPDATE_VALUE(updateCropAspectRatio)],
  4770. ['cropOrigin'],
  4771. ['cropMinSize', DEFAULT_VALUE(() => ({ width: 1, height: 1 }))],
  4772. ['cropMaxSize', DEFAULT_VALUE(() => ({ width: 32768, height: 32768 }))],
  4773. ['cropLimitToImage', DEFAULT_VALUE(() => true), UPDATE_VALUE(updateCropLimitToImage)],
  4774. [
  4775. 'cropSize',
  4776. UNIQUE_DERIVED_STORE(({ crop }) => [
  4777. [crop],
  4778. ([$crop], set) => {
  4779. if (!$crop)
  4780. return;
  4781. set(sizeCreate($crop.width, $crop.height));
  4782. },
  4783. // if is same as previous size, don't trigger update (happens when updating only the crop offset)
  4784. (prevValue, nextValue) => sizeEqual(prevValue, nextValue),
  4785. ]),
  4786. ],
  4787. [
  4788. 'cropRectAspectRatio',
  4789. DERIVED_STORE(({ cropSize }) => [
  4790. [cropSize],
  4791. ([$cropSize], set) => {
  4792. if (!$cropSize)
  4793. return;
  4794. set(fixPrecision(rectAspectRatio($cropSize), 5));
  4795. },
  4796. ]),
  4797. ],
  4798. [
  4799. 'cropRange',
  4800. UNIQUE_DERIVED_STORE(({ size, rotation, cropRectAspectRatio, cropMinSize, cropMaxSize, cropLimitToImage, }) => [
  4801. [size, rotation, cropRectAspectRatio, cropMinSize, cropMaxSize, cropLimitToImage],
  4802. ([$size, $rotation, $cropRectAspectRatio, $cropMinSize, $cropMaxSize, $cropLimitToImage,], set) => {
  4803. // wait for image size
  4804. if (!$size)
  4805. return;
  4806. const range = updateCropRange($size, $rotation, $cropRectAspectRatio, $cropMinSize, $cropMaxSize, $cropLimitToImage);
  4807. set(range);
  4808. },
  4809. // if is same range as previous range, don't trigger update
  4810. (prevRange, nextRange) => arrayEqual(prevRange, nextRange),
  4811. ]),
  4812. ],
  4813. [
  4814. 'rotationRange',
  4815. UNIQUE_DERIVED_STORE(({ size, isRotatedSideways, cropMinSize, cropSize, cropLimitToImage }) => [
  4816. [size, isRotatedSideways, cropMinSize, cropSize, cropLimitToImage],
  4817. ([$size, $isRotatedSideways, $cropMinSize, $cropSize, $cropLimitToImage], set) => {
  4818. // wait for image size
  4819. if (!$size || !$cropSize)
  4820. return;
  4821. const range = updateRotationRange($size, $isRotatedSideways, $cropMinSize, $cropSize, $cropLimitToImage);
  4822. set(range);
  4823. },
  4824. // if is same range as previous range, don't trigger update
  4825. (prevRange, nextRange) => arrayEqual(prevRange, nextRange),
  4826. ]),
  4827. ],
  4828. // canvas
  4829. ['backgroundColor', UPDATE_VALUE(() => (color) => padColorArray(color))],
  4830. // size
  4831. ['targetSize'],
  4832. // effects
  4833. ['colorMatrix'],
  4834. ['convolutionMatrix'],
  4835. ['gamma'],
  4836. ['noise'],
  4837. ['vignette'],
  4838. // redaction lives in image space
  4839. ['redaction', MAP_STORE(({ size }) => [formatShape, { context: size }])],
  4840. // annotation lives in image space
  4841. ['annotation', MAP_STORE(({ size }) => [formatShape, { context: size }])],
  4842. // decoration lives in crop space
  4843. ['decoration', MAP_STORE(({ crop }) => [formatShape, { context: crop }])],
  4844. // frame to render on top of the image (or outside)
  4845. ['frame', UPDATE_VALUE(updateFrame)],
  4846. // custom metadata
  4847. ['metadata'],
  4848. // state of image, used to restore a previous state or request the current state
  4849. ['state', CUSTOM_STORE(stateStore)],
  4850. ];
  4851. var process = async (value, chainTasks, chainOptions = {}, processOptions) => {
  4852. // options relevant to the process method itself
  4853. const { ontaskstart, ontaskprogress, ontaskend, token } = processOptions;
  4854. // has been cancelled
  4855. let cancelled = false;
  4856. // set cancel handler method
  4857. token.cancel = () => {
  4858. // cancel called from outside of the process method
  4859. cancelled = true;
  4860. };
  4861. // step through chain
  4862. for (const [index, task] of chainTasks.entries()) {
  4863. // exit when cancelled
  4864. if (cancelled)
  4865. return;
  4866. // get the task function and the id so we can notify the callee of the task that is being started
  4867. const [fn, id] = task;
  4868. // start task
  4869. ontaskstart(index, id);
  4870. try {
  4871. value = await fn(value, { ...chainOptions }, (event) => ontaskprogress(index, id, event));
  4872. }
  4873. catch (err) {
  4874. // stop processing more items in the chain
  4875. cancelled = true;
  4876. // pass error back to parent
  4877. throw err;
  4878. }
  4879. ontaskend(index, id);
  4880. }
  4881. return value;
  4882. };
  4883. // TODO: find better location for minSize / file load validation
  4884. var createImageCore = ({ minSize = { width: 1, height: 1 } } = {}) => {
  4885. // create default store
  4886. const { stores, accessors } = createStores(imageProps);
  4887. // pub/sub
  4888. const { pub, sub } = pubsub();
  4889. // processing handler
  4890. const createProcessingHandler = (stateProp, eventKey) => {
  4891. const getStore = () => accessors[stateProp] || {};
  4892. const setStore = (obj) => (accessors[stateProp] = {
  4893. ...getStore(),
  4894. ...obj,
  4895. timeStamp: Date.now(),
  4896. });
  4897. const hasError = () => getStore().error;
  4898. const handleError = (error) => {
  4899. if (hasError())
  4900. return;
  4901. setStore({
  4902. error: error,
  4903. });
  4904. pub(`${eventKey}error`, { ...getStore() });
  4905. };
  4906. return {
  4907. start() {
  4908. pub(`${eventKey}start`);
  4909. },
  4910. onabort() {
  4911. setStore({
  4912. abort: true,
  4913. });
  4914. pub(`${eventKey}abort`, { ...getStore() });
  4915. },
  4916. ontaskstart(index, id) {
  4917. if (hasError())
  4918. return;
  4919. setStore({
  4920. index,
  4921. task: id,
  4922. taskProgress: undefined,
  4923. taskLengthComputable: undefined,
  4924. });
  4925. pub(`${eventKey}taskstart`, { ...getStore() });
  4926. },
  4927. ontaskprogress(index, id, event) {
  4928. if (hasError())
  4929. return;
  4930. setStore({
  4931. index,
  4932. task: id,
  4933. taskProgress: event.loaded / event.total,
  4934. taskLengthComputable: event.lengthComputable,
  4935. });
  4936. pub(`${eventKey}taskprogress`, { ...getStore() });
  4937. pub(`${eventKey}progress`, { ...getStore() });
  4938. },
  4939. ontaskend(index, id) {
  4940. if (hasError())
  4941. return;
  4942. setStore({
  4943. index,
  4944. task: id,
  4945. });
  4946. pub(`${eventKey}taskend`, { ...getStore() });
  4947. },
  4948. ontaskerror(error) {
  4949. handleError(error);
  4950. },
  4951. error(error) {
  4952. handleError(error);
  4953. },
  4954. beforeComplete(data) {
  4955. if (hasError())
  4956. return;
  4957. setStore({ beforeComplete: true });
  4958. pub(`before${eventKey}`, data);
  4959. },
  4960. complete(data) {
  4961. if (hasError())
  4962. return;
  4963. setStore({ complete: true });
  4964. pub(eventKey, data);
  4965. },
  4966. };
  4967. };
  4968. //#region read image
  4969. const read = (src, { reader }) => {
  4970. // exit if no reader supplied
  4971. if (!reader)
  4972. return;
  4973. // reset file data to undefined as we're loading a new image
  4974. Object.assign(accessors, {
  4975. file: undefined,
  4976. size: undefined,
  4977. loadState: undefined,
  4978. });
  4979. // our cancel token so we can abort load if needed, cancel will be set by process
  4980. let imageReadToken = { cancel: noop$1 };
  4981. let imageReadCancelled = false;
  4982. const imageReadHandler = createProcessingHandler('loadState', 'load');
  4983. const processOptions = {
  4984. token: imageReadToken,
  4985. ...imageReadHandler,
  4986. };
  4987. const readerState = {
  4988. src,
  4989. size: undefined,
  4990. dest: undefined,
  4991. };
  4992. const readerOptions = {};
  4993. // wait a tick before starting image read so the read can be cancelled in loadstart
  4994. Promise.resolve().then(async () => {
  4995. try {
  4996. imageReadHandler.start();
  4997. if (imageReadCancelled)
  4998. return imageReadHandler.onabort();
  4999. const output = (await process(readerState, reader, readerOptions, processOptions));
  5000. // was cancelled
  5001. if (imageReadCancelled)
  5002. return imageReadHandler.onabort();
  5003. // get shortcuts for validation
  5004. const { size, dest } = output || {};
  5005. // if we don't have a size
  5006. if (!size || !size.width || !size.height)
  5007. throw new EditorError('Image size missing', 'IMAGE_SIZE_MISSING', output);
  5008. // size of image is too small
  5009. if (size.width < minSize.width || size.height < minSize.height)
  5010. throw new EditorError('Image too small', 'IMAGE_TOO_SMALL', {
  5011. ...output,
  5012. minWidth: minSize.width,
  5013. minHeight: minSize.height,
  5014. });
  5015. // update internal data
  5016. Object.assign(accessors, {
  5017. size: size,
  5018. file: dest,
  5019. });
  5020. // before load complete
  5021. imageReadHandler.beforeComplete(output);
  5022. // done loading image
  5023. imageReadHandler.complete(output);
  5024. }
  5025. catch (err) {
  5026. imageReadHandler.error(err);
  5027. }
  5028. finally {
  5029. imageReadToken = undefined;
  5030. }
  5031. });
  5032. // call to abort load
  5033. return () => {
  5034. imageReadCancelled = true;
  5035. imageReadToken && imageReadToken.cancel();
  5036. imageReadHandler.onabort();
  5037. };
  5038. };
  5039. //#endregion
  5040. //#region write image
  5041. const write = (writer, options) => {
  5042. // not ready to start processing
  5043. if (!accessors.loadState.complete)
  5044. return;
  5045. // reset process state to undefined
  5046. accessors.processState = undefined;
  5047. const imageWriteHandler = createProcessingHandler('processState', 'process');
  5048. const writerState = {
  5049. src: accessors.file,
  5050. imageState: accessors.state,
  5051. dest: undefined,
  5052. };
  5053. // willProcessImageState
  5054. if (!writer) {
  5055. imageWriteHandler.start();
  5056. imageWriteHandler.complete(writerState);
  5057. return;
  5058. }
  5059. // we need this token to be a blet to cancel the processing operation
  5060. let imageWriteToken = { cancel: noop$1 };
  5061. let imageWriteCancelled = false;
  5062. const writerOptions = options;
  5063. const processOptions = {
  5064. token: imageWriteToken,
  5065. ...imageWriteHandler,
  5066. };
  5067. // wait a tick before starting image write so the write can be cancelled in processtart
  5068. Promise.resolve().then(async () => {
  5069. try {
  5070. imageWriteHandler.start();
  5071. if (imageWriteCancelled)
  5072. return imageWriteHandler.onabort();
  5073. const output = (await process(writerState, writer, writerOptions, processOptions));
  5074. imageWriteHandler.complete(output);
  5075. }
  5076. catch (err) {
  5077. imageWriteHandler.error(err);
  5078. }
  5079. finally {
  5080. imageWriteToken = undefined;
  5081. }
  5082. });
  5083. // call to abort processing
  5084. return () => {
  5085. imageWriteCancelled = true;
  5086. imageWriteToken && imageWriteToken.cancel();
  5087. };
  5088. };
  5089. //#endregion
  5090. //#region api
  5091. defineMethods(accessors, {
  5092. read,
  5093. write,
  5094. on: sub,
  5095. });
  5096. //#endregion
  5097. // expose store API
  5098. return {
  5099. accessors,
  5100. stores,
  5101. };
  5102. };
  5103. // @ts-ignore
  5104. const editorEventsToBubble = [
  5105. 'loadstart',
  5106. 'loadabort',
  5107. 'loaderror',
  5108. 'loadprogress',
  5109. 'load',
  5110. 'processstart',
  5111. 'processabort',
  5112. 'processerror',
  5113. 'processprogress',
  5114. 'process',
  5115. ];
  5116. const imagePrivateProps = [
  5117. 'flip',
  5118. 'cropOrigin',
  5119. 'isRotatedSideways',
  5120. 'perspective',
  5121. 'perspectiveX',
  5122. 'perspectiveY',
  5123. 'cropRange',
  5124. ];
  5125. const editorPrivateProps = ['images'];
  5126. const imagePublicProps = imageProps
  5127. .map(([prop]) => prop)
  5128. .filter((prop) => !imagePrivateProps.includes(prop));
  5129. const getImagePropGroupedName = (prop) => `image${capitalizeFirstLetter(prop)}`;
  5130. const getEditorProps$1 = () => {
  5131. const imageProperties = imagePublicProps.map(getImagePropGroupedName);
  5132. const editorProperties = props
  5133. .map(([prop]) => prop)
  5134. .filter((prop) => !editorPrivateProps.includes(prop));
  5135. return imageProperties.concat(editorProperties);
  5136. };
  5137. const isImageSource = (src) => isString(src) || isBinary(src) || isElement(src);
  5138. const isImageState = (obj) => hasProp(obj, 'crop');
  5139. var createImageEditor = () => {
  5140. // create default stores
  5141. const { stores, accessors } = createStores(props);
  5142. // set up pub/sub for the app layer
  5143. const { sub, pub } = pubsub();
  5144. const bubble = (name) => (value) => pub(name, value);
  5145. // helper method
  5146. const getImageObjSafe = () => (accessors.images ? accessors.images[0] : {});
  5147. // initialImageProps is the list of transforms to apply when the image loads
  5148. let initialImageProps = {};
  5149. // create shortcuts to image props : `crop` -> `imageCrop`
  5150. imagePublicProps.forEach((prop) => {
  5151. Object.defineProperty(accessors, getImagePropGroupedName(prop), {
  5152. get: () => {
  5153. // no image, can't get
  5154. const image = getImageObjSafe();
  5155. if (!image)
  5156. return;
  5157. // return from image state
  5158. return image.accessors[prop];
  5159. },
  5160. set: (value) => {
  5161. // always use as initial prop when loading a new image without reset
  5162. initialImageProps[getImagePropGroupedName(prop)] = value;
  5163. // no image, we can't update
  5164. const image = getImageObjSafe();
  5165. if (!image)
  5166. return;
  5167. // update the image immidiately
  5168. image.accessors[prop] = value;
  5169. },
  5170. });
  5171. });
  5172. // internal helper method to get active image
  5173. const getImage = () => accessors.images && accessors.images[0];
  5174. // handling loading an image if a src is set
  5175. const unsubSrc = stores.src.subscribe((src) => {
  5176. // no image set, means clear active image
  5177. if (!src)
  5178. return (accessors.images = []);
  5179. // exit here if we don't have an imageReader we'll wait for an imageReader to be defined
  5180. if (!accessors.imageReader)
  5181. return;
  5182. // reset initial image props if an image is already loaded, so props applied to previous image aren't applied to the new one
  5183. if (accessors.images.length)
  5184. initialImageProps = {};
  5185. // load image in src prop
  5186. loadSrc(src);
  5187. });
  5188. const unsubReader = stores.imageReader.subscribe((reader) => {
  5189. // can't do anything without an image reader
  5190. if (!reader)
  5191. return;
  5192. // an image has already been loaded no need to load images that were set earlier
  5193. if (accessors.images.length)
  5194. return;
  5195. // no image to load, we'll wait for images to be set to the `src` prop
  5196. if (!accessors.src)
  5197. return;
  5198. // src is waiting to be loaded so let's pick it up,
  5199. loadSrc(accessors.src);
  5200. });
  5201. const loadSrc = (src) => {
  5202. // push it back a tick so we know initialImageProps are set
  5203. Promise.resolve()
  5204. .then(() => {
  5205. // load with initial props
  5206. return loadImage(src, initialImageProps);
  5207. })
  5208. .catch(() => {
  5209. // fail silently, any errors are handled with 'loaderror' event
  5210. });
  5211. };
  5212. //#endregion
  5213. //#region public method (note that these are also called from UI, name of method is name of dispatched event in UI)
  5214. const applyImageOptionsOrState = (image, options) => {
  5215. // test if options is image state, if so, apply and exit
  5216. if (isImageState(options)) {
  5217. accessors.imageState = options;
  5218. return;
  5219. }
  5220. // create an initial crop rect if no crop supplied
  5221. if (!options.imageCrop) {
  5222. const imageSize = image.accessors.size;
  5223. const imageRotation = options.imageRotation || 0;
  5224. const cropRect = rectCreateFromSize(sizeRotate(sizeClone(imageSize), imageRotation));
  5225. const aspectRatio = options.imageCropAspectRatio ||
  5226. (options.imageCropLimitToImage
  5227. ? rectAspectRatio(imageSize) // use image size if should limit to image
  5228. : rectAspectRatio(cropRect)); // use rotated crop rect bounds if no limit
  5229. const crop = rectContainRect(cropRect, aspectRatio);
  5230. // center the image in the crop rectangle
  5231. if (!options.imageCropLimitToImage) {
  5232. crop.x = (imageSize.width - crop.width) / 2;
  5233. crop.y = (imageSize.height - crop.height) / 2;
  5234. }
  5235. options.imageCrop = crop;
  5236. }
  5237. // we need to apply these props in the correct order
  5238. ['imageCropLimitToImage', 'imageCrop', 'imageCropAspectRatio', 'imageRotation']
  5239. .filter((prop) => hasProp(options, prop))
  5240. .forEach((prop) => {
  5241. // assign to `image`
  5242. accessors[prop] = options[prop];
  5243. // remove from normalizedOptions so it's not set twice
  5244. delete options[prop];
  5245. });
  5246. // don't set the above options for a second time
  5247. const { imageCropLimitToImage, imageCrop, imageCropAspectRatio, imageRotation, ...remainingOptions } = options;
  5248. // trigger setState
  5249. Object.assign(accessors, remainingOptions);
  5250. };
  5251. // load image, resolve when image is loaded
  5252. let imageLoadAbort;
  5253. const loadImage = (src, options = {}) => new Promise((resolve, reject) => {
  5254. // get current image
  5255. let image = getImage();
  5256. // determine min defined image size (is crop min size)
  5257. const cropLimitedToImage = !(options.cropLimitToImage === false || options.imageCropLimitToImage === false);
  5258. const cropMinSize = options.cropMinSize || options.imageCropMinSize;
  5259. const minImageSize = cropLimitedToImage
  5260. ? cropMinSize
  5261. : image && image.accessors.cropMinSize;
  5262. // if already has image, remove existing image
  5263. if (image)
  5264. removeImage();
  5265. // access image props and stores
  5266. image = createImageCore({ minSize: minImageSize });
  5267. editorEventsToBubble.map((event) => image.accessors.on(event, bubble(event)));
  5268. // done, clean up listeners
  5269. const fin = () => {
  5270. // reset initial props (as now applied)
  5271. initialImageProps = {};
  5272. unsubs.forEach((unsub) => unsub());
  5273. };
  5274. const unsubs = [];
  5275. unsubs.push(image.accessors.on('loaderror', (error) => {
  5276. fin();
  5277. reject(error);
  5278. }));
  5279. unsubs.push(image.accessors.on('loadabort', () => {
  5280. fin();
  5281. reject({ name: 'AbortError' });
  5282. }));
  5283. unsubs.push(image.accessors.on('load', (output) => {
  5284. imageLoadAbort = undefined;
  5285. fin();
  5286. resolve(output);
  5287. }));
  5288. unsubs.push(image.accessors.on('beforeload', () => applyImageOptionsOrState(image, options)));
  5289. // set new image
  5290. accessors.images = [image];
  5291. // assign passed options to editor accessors, we ignore 'src'
  5292. if (options.imageReader)
  5293. accessors.imageReader = options.imageReader;
  5294. if (options.imageWriter)
  5295. accessors.imageWriter = options.imageWriter;
  5296. // start reading image
  5297. imageLoadAbort = image.accessors.read(src, { reader: accessors.imageReader });
  5298. });
  5299. // start processing a loaded image, resolve when image is processed
  5300. let imageProcessAbort;
  5301. const processImage = (src, options) => new Promise(async (resolve, reject) => {
  5302. // if src supplied, first load src, then process
  5303. if (isImageSource(src)) {
  5304. await loadImage(src, options);
  5305. }
  5306. // if first argument is not `src` but is set it's an options object, so we'll update the options before generating the image
  5307. else if (src) {
  5308. if (isImageState(src)) {
  5309. accessors.imageState = src;
  5310. }
  5311. else {
  5312. Object.assign(accessors, src);
  5313. }
  5314. }
  5315. // get current active image
  5316. const image = getImage();
  5317. // needs image for processing
  5318. if (!image)
  5319. return reject('no image');
  5320. // done, clean up listeners
  5321. const fin = () => {
  5322. imageProcessAbort = undefined;
  5323. unsubs.forEach((unsub) => unsub());
  5324. };
  5325. const unsubs = [];
  5326. unsubs.push(image.accessors.on('processerror', (error) => {
  5327. fin();
  5328. reject(error);
  5329. }));
  5330. unsubs.push(image.accessors.on('processabort', () => {
  5331. fin();
  5332. reject({ name: 'AbortError' });
  5333. }));
  5334. unsubs.push(image.accessors.on('process', (output) => {
  5335. fin();
  5336. resolve(output);
  5337. }));
  5338. imageProcessAbort = image.accessors.write(accessors.imageWriter, {
  5339. shapePreprocessor: accessors.shapePreprocessor || passthrough,
  5340. imageScrambler: accessors.imageScrambler,
  5341. });
  5342. });
  5343. const abortProcessImage = () => {
  5344. const image = getImage();
  5345. if (!image)
  5346. return;
  5347. if (imageProcessAbort)
  5348. imageProcessAbort();
  5349. image.accessors.processState = undefined;
  5350. };
  5351. // used internally (triggered by 'x' button when error loading image in UI)
  5352. const abortLoadImage = () => {
  5353. if (imageLoadAbort)
  5354. imageLoadAbort();
  5355. accessors.images = [];
  5356. };
  5357. // edit image, loads an image and resolve when image is processed
  5358. const editImage = (src, options) => new Promise((resolve, reject) => {
  5359. loadImage(src, options)
  5360. .then(() => {
  5361. // access image props and stores
  5362. const { images } = accessors;
  5363. const image = images[0];
  5364. // done, clean up listeners
  5365. const done = () => {
  5366. unsubReject();
  5367. unsubResolve();
  5368. };
  5369. const unsubReject = image.accessors.on('processerror', (error) => {
  5370. done();
  5371. reject(error);
  5372. });
  5373. const unsubResolve = image.accessors.on('process', (output) => {
  5374. done();
  5375. resolve(output);
  5376. });
  5377. })
  5378. .catch(reject);
  5379. });
  5380. const removeImage = () => {
  5381. // no images, nothing to remove
  5382. const image = getImage();
  5383. if (!image)
  5384. return;
  5385. // try to abort image load
  5386. if (imageLoadAbort)
  5387. imageLoadAbort();
  5388. image.accessors.loadState = undefined;
  5389. // clear images
  5390. accessors.images = [];
  5391. };
  5392. //#endregion
  5393. Object.defineProperty(accessors, 'stores', {
  5394. get: () => stores,
  5395. });
  5396. //#region API
  5397. defineMethods(accessors, {
  5398. on: sub,
  5399. loadImage,
  5400. abortLoadImage,
  5401. editImage,
  5402. removeImage,
  5403. processImage,
  5404. abortProcessImage,
  5405. destroy: () => {
  5406. unsubSrc();
  5407. unsubReader();
  5408. },
  5409. });
  5410. return accessors;
  5411. //#endregion
  5412. };
  5413. const processImage = (src, options) => {
  5414. const { processImage } = createImageEditor();
  5415. return processImage(src, options);
  5416. };
  5417. var getCanvasMemoryLimit = () => {
  5418. if (!isSafari$1())
  5419. return Infinity;
  5420. const isSafari15 = /15_/.test(navigator.userAgent);
  5421. if (isIOS()) {
  5422. // limit resolution a little bit further to prevent drawing issues
  5423. if (isSafari15)
  5424. return 3840 * 3840;
  5425. // old iOS can deal with 4096 * 4096 without issues
  5426. return 4096 * 4096;
  5427. }
  5428. return isSafari15 ? 4096 * 4096 : Infinity;
  5429. };
  5430. // custom method to draw images
  5431. const canvasDrawImage = async (ctx, image, srcRect, destRect) => {
  5432. // get resized image
  5433. const { dest } = await processImage(image, {
  5434. imageReader: createDefaultImageReader$1(),
  5435. imageWriter: createDefaultImageWriter$1({
  5436. format: 'canvas',
  5437. targetSize: {
  5438. ...destRect,
  5439. upscale: true,
  5440. },
  5441. }),
  5442. imageCrop: srcRect,
  5443. });
  5444. // draw processed image
  5445. ctx.drawImage(dest, destRect.x, destRect.y, destRect.width, destRect.height);
  5446. // release image canvas to free up memory
  5447. releaseCanvas(dest);
  5448. };
  5449. // connect function in process chain
  5450. const connect = (fn, getter = (...args) => args, setter) => async (state, options, onprogress) => {
  5451. // will hold function result
  5452. // at this point we don't know if the length of this task can be computed
  5453. onprogress(createProgressEvent(0, false));
  5454. // try to run the function
  5455. let progressUpdated = false;
  5456. const res = await fn(...getter(state, options, (event) => {
  5457. progressUpdated = true;
  5458. onprogress(event);
  5459. }));
  5460. // a setter isn't required
  5461. setter && setter(state, res);
  5462. // if progress was updated, we expect the connected function to fire the 1/1 event, else we fire it here
  5463. if (!progressUpdated)
  5464. onprogress(createProgressEvent(1, false));
  5465. return state;
  5466. };
  5467. //
  5468. // Reader/Writer Presets
  5469. //
  5470. const AnyToFile = ({ srcProp = 'src', destProp = 'dest' } = {}) => [
  5471. connect(srcToFile, (state, options, onprogress) => [state[srcProp], onprogress], (state, file) => (state[destProp] = file)),
  5472. 'any-to-file',
  5473. ];
  5474. const BlobReadImageSize = ({ srcProp = 'src', destProp = 'size' } = {}) => [
  5475. connect(getImageSize, (state, options) => [state[srcProp]], (state, size) => (state[destProp] = size)),
  5476. 'read-image-size',
  5477. ];
  5478. const ImageSizeMatchOrientation = ({ srcSize = 'size', srcOrientation = 'orientation', destSize = 'size', } = {}) => [
  5479. connect(orientImageSize, (state) => [state[srcSize], state[srcOrientation]], (state, size) => (state[destSize] = size)),
  5480. 'image-size-match-orientation',
  5481. ];
  5482. const BlobReadImageHead = ({ srcProp = 'src', destProp = 'head' } = {}) => [
  5483. connect((blob, slice) => (isJPEG(blob) ? blobReadSection(blob, slice) : undefined),
  5484. // 64 * 1024 should be plenty to find extract header
  5485. // Exif metadata are restricted in size to 64 kB in JPEG images because
  5486. // according to the specification this information must be contained within a single JPEG APP1 segment.
  5487. (state) => [state[srcProp], [0, 64 * 2048], onprogress], (state, head) => (state[destProp] = head)),
  5488. 'read-image-head',
  5489. ];
  5490. const ImageHeadReadExifOrientationTag = ({ srcProp = 'head', destProp = 'orientation', } = {}) => [
  5491. connect(arrayBufferImageExif, (state) => [state[srcProp], ORIENTATION_TAG], (state, orientation = 1) => (state[destProp] = orientation)),
  5492. 'read-exif-orientation-tag',
  5493. ];
  5494. const ImageHeadClearExifOrientationTag = ({ srcProp = 'head' } = {}) => [
  5495. connect(arrayBufferImageExif, (state) => [state[srcProp], ORIENTATION_TAG, 1]),
  5496. 'clear-exif-orientation-tag',
  5497. ];
  5498. const ApplyCanvasScalar = ({ srcImageSize = 'size', srcCanvasSize = 'imageData', srcImageState = 'imageState', destImageSize = 'size', destScalar = 'scalar', } = {}) => [
  5499. connect((naturalSize, canvasSize, imageState) => {
  5500. // calculate canvas scalar
  5501. const scalar = Math.min(canvasSize.width / naturalSize.width, canvasSize.height / naturalSize.height);
  5502. // done because not scaling
  5503. if (scalar !== 1) {
  5504. const { crop, annotation, decoration } = imageState;
  5505. // origin to scale to
  5506. const origin = vectorCreateEmpty();
  5507. // scale select.crop
  5508. if (crop)
  5509. imageState.crop = rectScale(crop, scalar, origin);
  5510. // scale annotation
  5511. const translate = vectorCreateEmpty();
  5512. imageState.annotation = annotation.map((shape) => shapeComputeTransform(shape, translate, scalar));
  5513. // scale decoration
  5514. imageState.decoration = decoration.map((shape) => shapeComputeTransform(shape, translate, scalar));
  5515. }
  5516. return [scalar, sizeCreateFromAny(canvasSize)];
  5517. }, (state) => [state[srcImageSize], state[srcCanvasSize], state[srcImageState]], (state, [scalar, imageSize]) => {
  5518. state[destScalar] = scalar;
  5519. state[destImageSize] = imageSize;
  5520. }),
  5521. 'calculate-canvas-scalar',
  5522. ];
  5523. const BlobToImageData = ({ srcProp = 'src', destProp = 'imageData', canvasMemoryLimit = undefined, }) => [
  5524. connect(blobToImageData, (state) => [state[srcProp], canvasMemoryLimit], (state, imageData) => (state[destProp] = imageData)),
  5525. 'blob-to-image-data',
  5526. ];
  5527. const ImageDataMatchOrientation = ({ srcImageData = 'imageData', srcOrientation = 'orientation', } = {}) => [
  5528. connect(orientImageData, (state) => [state[srcImageData], state[srcOrientation]], (state, imageData) => (state.imageData = imageData)),
  5529. 'image-data-match-orientation',
  5530. ];
  5531. const ImageDataFill = ({ srcImageData = 'imageData', srcImageState = 'imageState' } = {}) => [
  5532. connect(fillImageData, (state) => [
  5533. state[srcImageData],
  5534. { backgroundColor: state[srcImageState].backgroundColor },
  5535. ], (state, imageData) => (state.imageData = imageData)),
  5536. 'image-data-fill',
  5537. ];
  5538. const ImageDataCrop = ({ srcImageData = 'imageData', srcImageState = 'imageState' } = {}) => [
  5539. connect(cropImageData, (state) => [
  5540. state[srcImageData],
  5541. {
  5542. crop: state[srcImageState].crop,
  5543. rotation: state[srcImageState].rotation,
  5544. flipX: state[srcImageState].flipX,
  5545. flipY: state[srcImageState].flipY,
  5546. },
  5547. ], (state, imageData) => (state.imageData = imageData)),
  5548. 'image-data-crop',
  5549. ];
  5550. const hasTargetSize = (imageState) => !!((imageState.targetSize && imageState.targetSize.width) ||
  5551. (imageState.targetSize && imageState.targetSize.height));
  5552. const ImageDataResize = ({ resize = {
  5553. width: undefined,
  5554. height: undefined,
  5555. fit: undefined,
  5556. upscale: undefined,
  5557. }, srcProp = 'imageData', srcImageState = 'imageState', destImageScaledSize = 'imageScaledSize', }) => [
  5558. connect(resizeImageData, (state) => [
  5559. state[srcProp],
  5560. {
  5561. width: Math.min(resize.width || Number.MAX_SAFE_INTEGER, (state[srcImageState].targetSize && state[srcImageState].targetSize.width) ||
  5562. Number.MAX_SAFE_INTEGER),
  5563. height: Math.min(resize.height || Number.MAX_SAFE_INTEGER, (state[srcImageState].targetSize && state[srcImageState].targetSize.height) ||
  5564. Number.MAX_SAFE_INTEGER),
  5565. fit: resize.fit || 'contain',
  5566. upscale: hasTargetSize(state[srcImageState]) ? true : resize.upscale || false,
  5567. },
  5568. ], (state, imageData) => {
  5569. if (!sizeEqual(state.imageData, imageData))
  5570. state[destImageScaledSize] = sizeCreateFromAny(imageData);
  5571. state.imageData = imageData;
  5572. }),
  5573. 'image-data-resize',
  5574. ];
  5575. const ImageDataFilter = ({ srcImageData = 'imageData', srcImageState = 'imageState', destImageData = 'imageData', } = {}) => [
  5576. connect(filterImageData, (state) => {
  5577. const { colorMatrix } = state[srcImageState];
  5578. const colorMatrices = colorMatrix &&
  5579. Object.keys(colorMatrix)
  5580. .map((name) => colorMatrix[name])
  5581. .filter(Boolean);
  5582. return [
  5583. state[srcImageData],
  5584. {
  5585. colorMatrix: colorMatrices && getColorMatrixFromColorMatrices(colorMatrices),
  5586. convolutionMatrix: state[srcImageState].convolutionMatrix,
  5587. gamma: state[srcImageState].gamma,
  5588. noise: state[srcImageState].noise,
  5589. vignette: state[srcImageState].vignette,
  5590. },
  5591. ];
  5592. }, (state, imageData) => (state[destImageData] = imageData)),
  5593. 'image-data-filter',
  5594. ];
  5595. const createImageContextDrawingTransform = (state, { srcSize, srcImageState, destImageScaledSize }) => (ctx) => {
  5596. const imageSize = state[srcSize];
  5597. const { crop = rectCreateFromSize(imageSize), rotation = 0, flipX, flipY } = state[srcImageState];
  5598. const rotatedRect = getImageTransformedRect(imageSize, rotation);
  5599. const rotatedSize = {
  5600. width: rotatedRect.width,
  5601. height: rotatedRect.height,
  5602. };
  5603. // calculate image scalar so we can scale annotations accordingly
  5604. const scaledSize = state[destImageScaledSize];
  5605. const scalar = scaledSize
  5606. ? Math.min(scaledSize.width / crop.width, scaledSize.height / crop.height)
  5607. : 1;
  5608. // calculate center
  5609. const dx = imageSize.width * 0.5 - rotatedSize.width * 0.5;
  5610. const dy = imageSize.height * 0.5 - rotatedSize.height * 0.5;
  5611. const center = sizeCenter(imageSize);
  5612. // image scalar
  5613. ctx.scale(scalar, scalar);
  5614. // offset
  5615. ctx.translate(-dx, -dy);
  5616. ctx.translate(-crop.x, -crop.y);
  5617. // rotation
  5618. ctx.translate(center.x, center.y);
  5619. ctx.rotate(rotation);
  5620. ctx.translate(-center.x, -center.y);
  5621. // flipping
  5622. ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
  5623. ctx.translate(flipX ? -imageSize.width : 0, flipY ? -imageSize.height : 0);
  5624. // annotations are clipped clip to image
  5625. ctx.rect(0, 0, imageSize.width, imageSize.height);
  5626. ctx.clip();
  5627. };
  5628. const ImageDataRedact = ({ srcImageData = 'imageData', srcImageState = 'imageState', destImageData = 'imageData', destScalar = 'scalar', } = {}) => [
  5629. connect(async (imageData, imageScrambler, imageBackgroundColor, shapes, scalar) => {
  5630. // skip!
  5631. if (!imageScrambler)
  5632. return imageData;
  5633. // create scrambled texture version
  5634. let scrambledCanvas;
  5635. try {
  5636. const options = {
  5637. dataSizeScalar: getImageRedactionScaleFactor(imageData, shapes),
  5638. };
  5639. if (imageBackgroundColor && imageBackgroundColor[3] > 0) {
  5640. options.backgroundColor = [...imageBackgroundColor];
  5641. }
  5642. scrambledCanvas = await imageScrambler(imageData, options);
  5643. }
  5644. catch (err) {
  5645. }
  5646. // create drawing context
  5647. const canvas = h('canvas');
  5648. canvas.width = imageData.width;
  5649. canvas.height = imageData.height;
  5650. const ctx = canvas.getContext('2d');
  5651. ctx.putImageData(imageData, 0, 0);
  5652. // set up a clip path so we only draw scrambled image within path
  5653. const path = new Path2D();
  5654. shapes.forEach((shape) => {
  5655. const rect = rectCreate(shape.x, shape.y, shape.width, shape.height);
  5656. rectMultiply(rect, scalar);
  5657. const corners = rectRotate(rectClone(rect), shape.rotation);
  5658. const poly = new Path2D();
  5659. corners.forEach((corner, i) => {
  5660. if (i === 0)
  5661. return poly.moveTo(corner.x, corner.y);
  5662. poly.lineTo(corner.x, corner.y);
  5663. });
  5664. path.addPath(poly);
  5665. });
  5666. ctx.clip(path, 'nonzero');
  5667. ctx.imageSmoothingEnabled = false;
  5668. ctx.drawImage(scrambledCanvas, 0, 0, canvas.width, canvas.height);
  5669. releaseCanvas(scrambledCanvas);
  5670. // done
  5671. const imageDataOut = ctx.getImageData(0, 0, canvas.width, canvas.height);
  5672. // clean up memory usage
  5673. releaseCanvas(canvas);
  5674. return imageDataOut;
  5675. }, (state, { imageScrambler }) => [
  5676. state[srcImageData],
  5677. imageScrambler,
  5678. state[srcImageState].backgroundColor,
  5679. state[srcImageState].redaction,
  5680. state[destScalar],
  5681. ], (state, imageData) => (state[destImageData] = imageData)),
  5682. 'image-data-annotate',
  5683. ];
  5684. const ImageDataAnnotate = ({ srcImageData = 'imageData', srcSize = 'size', srcImageState = 'imageState', destImageData = 'imageData', destImageScaledSize = 'imageScaledSize', } = {}) => [
  5685. connect(drawImageData, (state, { shapePreprocessor }) => [
  5686. state[srcImageData],
  5687. {
  5688. shapes: state[srcImageState].annotation,
  5689. context: state[srcSize],
  5690. transform: createImageContextDrawingTransform(state, {
  5691. srcSize,
  5692. srcImageState,
  5693. destImageScaledSize,
  5694. }),
  5695. drawImage: canvasDrawImage,
  5696. preprocessShape: (shape) => shapePreprocessor(shape, { isPreview: false }),
  5697. },
  5698. ], (state, imageData) => (state[destImageData] = imageData)),
  5699. 'image-data-annotate',
  5700. ];
  5701. const ImageDataDecorate = ({ srcImageData = 'imageData', srcImageState = 'imageState', destImageData = 'imageData', destImageScaledSize = 'imageScaledSize', } = {}) => [
  5702. connect(drawImageData, (state, { shapePreprocessor }) => [
  5703. state[srcImageData],
  5704. {
  5705. shapes: state[srcImageState].decoration,
  5706. context: state[srcImageState].crop,
  5707. transform: (ctx) => {
  5708. // calculate image scalar so we can scale decoration accordingly
  5709. const { crop } = state.imageState;
  5710. const scaledSize = state[destImageScaledSize];
  5711. const scalar = scaledSize
  5712. ? Math.min(scaledSize.width / crop.width, scaledSize.height / crop.height)
  5713. : 1;
  5714. ctx.scale(scalar, scalar);
  5715. },
  5716. drawImage: canvasDrawImage,
  5717. preprocessShape: (shape) => shapePreprocessor(shape, { isPreview: false }),
  5718. },
  5719. ], (state, imageData) => (state[destImageData] = imageData)),
  5720. 'image-data-decorate',
  5721. ];
  5722. const ImageDataFrame = ({ srcImageData = 'imageData', srcImageState = 'imageState', destImageData = 'imageData', destImageScaledSize = 'imageScaledSize', } = {}) => [
  5723. connect(drawImageData, (state, { shapePreprocessor }) => {
  5724. const frame = state[srcImageState].frame;
  5725. if (!frame)
  5726. return [state[srcImageData]];
  5727. const context = { ...state[srcImageState].crop };
  5728. const bounds = shapesBounds(shapesFromCompositShape(frame, context, shapePreprocessor), context);
  5729. context.x = Math.abs(bounds.left);
  5730. context.y = Math.abs(bounds.top);
  5731. context.width += Math.abs(bounds.left) + Math.abs(bounds.right);
  5732. context.height += Math.abs(bounds.top) + Math.abs(bounds.bottom);
  5733. const { crop } = state.imageState;
  5734. const scaledSize = state[destImageScaledSize];
  5735. const scalar = scaledSize
  5736. ? Math.min(scaledSize.width / crop.width, scaledSize.height / crop.height)
  5737. : 1;
  5738. rectMultiply(context, scalar);
  5739. // use floor because we can't fill up half pixels
  5740. context.x = Math.floor(context.x);
  5741. context.y = Math.floor(context.y);
  5742. context.width = Math.floor(context.width);
  5743. context.height = Math.floor(context.height);
  5744. return [
  5745. state[srcImageData],
  5746. {
  5747. shapes: [frame],
  5748. contextBounds: context,
  5749. transform: (ctx) => {
  5750. ctx.translate(context.x, context.y);
  5751. },
  5752. drawImage: canvasDrawImage,
  5753. preprocessShape: (shape) => shapePreprocessor(shape, { isPreview: false }),
  5754. },
  5755. ];
  5756. }, (state, imageData) => (state[destImageData] = imageData)),
  5757. 'image-data-frame',
  5758. ];
  5759. const ImageDataToBlob = ({ mimeType = undefined, quality = undefined, srcImageData = 'imageData', srcFile = 'src', destBlob = 'blob', } = {}) => [
  5760. connect(imageDataToBlob, (state) => [
  5761. state[srcImageData],
  5762. mimeType || getMimeTypeFromFilename(state[srcFile].name) || state[srcFile].type,
  5763. quality,
  5764. ], (state, blob) => (state[destBlob] = blob)),
  5765. 'image-data-to-blob',
  5766. ];
  5767. const ImageDataToCanvas = ({ srcImageData = 'imageData', srcOrientation = 'orientation', destCanvas = 'dest', } = {}) => [
  5768. connect(imageDataToCanvas, (state) => [state[srcImageData], state[srcOrientation]], (state, canvas) => (state[destCanvas] = canvas)),
  5769. 'image-data-to-canvas',
  5770. ];
  5771. const writeImageHead = async (blob, head) => {
  5772. if (!isJPEG(blob) || !head)
  5773. return blob;
  5774. // get exif section
  5775. const view = new DataView(head);
  5776. const markers = dataViewGetApplicationMarkers(view);
  5777. if (!markers || !markers.exif)
  5778. return blob;
  5779. const { exif } = markers;
  5780. // from byte 0 to end of exif header
  5781. const exifBuffer = head.slice(0, exif.offset + exif.size + 2);
  5782. return blobWriteSection(blob,
  5783. // insert head buffer into blob
  5784. exifBuffer,
  5785. // current blob doesn't have exif header (as outputted by canvas), so we insert ours in
  5786. // (jpeg header 2) + (jfif size 16) + (app1 header 2)
  5787. [20]);
  5788. };
  5789. const BlobWriteImageHead = (srcBlob = 'blob', srcHead = 'head', destBlob = 'blob') => [
  5790. connect(writeImageHead, (state) => [state[srcBlob], state[srcHead]], (state, blob) => (state[destBlob] = blob)),
  5791. 'blob-write-image-head',
  5792. ];
  5793. const BlobToFile = ({ renameFile = undefined, srcBlob = 'blob', srcFile = 'src', destFile = 'dest', defaultFilename = undefined, } = {}) => [
  5794. connect(blobToFile, (state) => [
  5795. state[srcBlob],
  5796. renameFile
  5797. ? renameFile(state[srcFile])
  5798. : state[srcFile].name ||
  5799. `${defaultFilename}.${getExtensionFromMimeType(state[srcBlob].type)}`,
  5800. ], (state, file) => (state[destFile] = file)),
  5801. 'blob-to-file',
  5802. ];
  5803. const Store = ({ url = './', dataset = (state) => [
  5804. ['dest', state.dest, state.dest.name],
  5805. ['imageState', state.imageState],
  5806. ], destStore = 'store', }) => [
  5807. connect(
  5808. // upload function
  5809. async (dataset, onprogress) => await post(url, dataset, { onprogress }),
  5810. // get state values
  5811. (state, options, onprogress) => [dataset(state), onprogress],
  5812. // set state values
  5813. (state, xhr) => (state[destStore] = xhr) // logs XHR request returned by `post`
  5814. ),
  5815. 'store',
  5816. ];
  5817. const PropFilter = (allowlist) => [
  5818. connect((state) => {
  5819. // if no allowlist suppleid or is empty array we don't filter
  5820. if (!allowlist || !allowlist.length)
  5821. return state;
  5822. // else we only allow the props defined in the list and delete non matching props
  5823. Object.keys(state).forEach((key) => {
  5824. if (allowlist.includes(key))
  5825. return;
  5826. delete state[key];
  5827. });
  5828. return state;
  5829. }),
  5830. 'prop-filter',
  5831. ];
  5832. // Generic image reader, suitable for most use cases
  5833. const createDefaultImageReader$1 = (options = {}) => {
  5834. const { orientImage = true, outputProps = ['src', 'dest', 'size'], preprocessImageFile, } = options;
  5835. return [
  5836. // can read most source files and turn them into blobs
  5837. AnyToFile(),
  5838. // TODO: test if supported mime/type
  5839. // called when file created, can be used to read unrecognized files
  5840. preprocessImageFile && [
  5841. connect(preprocessImageFile, (state, options, onprogress) => [
  5842. state.dest,
  5843. options,
  5844. onprogress,
  5845. ], (state, file) => (state.dest = file)),
  5846. 'preprocess-image-file',
  5847. ],
  5848. // quickly read size (only reads first part of image)
  5849. BlobReadImageSize({ srcProp: 'dest' }),
  5850. // fix image orientation
  5851. orientImage && BlobReadImageHead({ srcProp: 'dest' }),
  5852. orientImage && ImageHeadReadExifOrientationTag(),
  5853. orientImage && ImageSizeMatchOrientation(),
  5854. // remove unwanted props
  5855. PropFilter(outputProps),
  5856. ].filter(Boolean);
  5857. };
  5858. const createDefaultImageWriter$1 = (options = {}) => {
  5859. const { canvasMemoryLimit = getCanvasMemoryLimit(), orientImage = true, copyImageHead = true, mimeType = undefined, quality = undefined, renameFile = undefined, targetSize = undefined, store = undefined, format = 'file', outputProps = ['src', 'dest', 'imageState', 'store'], preprocessImageSource, preprocessImageState, postprocessImageData, postprocessImageBlob, } = options;
  5860. return [
  5861. // allow preprocessing of image blob, should return a new blob, for example to automatically make image background transparent
  5862. preprocessImageSource && [
  5863. connect(preprocessImageSource, (state, options, onprogress) => [
  5864. state.src,
  5865. options,
  5866. onprogress,
  5867. ], (state, src) => (state.src = src)),
  5868. 'preprocess-image-source',
  5869. ],
  5870. // get orientation info (if is jpeg)
  5871. (orientImage || copyImageHead) && BlobReadImageHead(),
  5872. orientImage && ImageHeadReadExifOrientationTag(),
  5873. // get image size
  5874. BlobReadImageSize(),
  5875. // allow preproccesing of image state for example to replace placeholders
  5876. preprocessImageState && [
  5877. connect(preprocessImageState, (state, options, onprogress) => [
  5878. state.imageState,
  5879. options,
  5880. onprogress,
  5881. ], (state, imageState) => (state.imageState = imageState)),
  5882. 'preprocess-image-state',
  5883. ],
  5884. // get image data
  5885. BlobToImageData({ canvasMemoryLimit }),
  5886. // fix image orientation
  5887. orientImage && ImageSizeMatchOrientation(),
  5888. orientImage && ImageDataMatchOrientation(),
  5889. // apply canvas scalar to data
  5890. ApplyCanvasScalar(),
  5891. // apply image state
  5892. ImageDataRedact(),
  5893. ImageDataCrop(),
  5894. ImageDataResize({ resize: targetSize }),
  5895. ImageDataFilter(),
  5896. ImageDataFill(),
  5897. ImageDataAnnotate(),
  5898. ImageDataDecorate(),
  5899. ImageDataFrame(),
  5900. // run post processing on image data, for example to apply circular crop
  5901. postprocessImageData && [
  5902. connect(postprocessImageData, (state, options, onprogress) => [
  5903. state.imageData,
  5904. options,
  5905. onprogress,
  5906. ], (state, imageData) => (state.imageData = imageData)),
  5907. 'postprocess-image-data',
  5908. ],
  5909. // convert to correct output format
  5910. format === 'file'
  5911. ? ImageDataToBlob({ mimeType, quality })
  5912. : format === 'canvas'
  5913. ? ImageDataToCanvas()
  5914. : [
  5915. (state) => {
  5916. state.dest = state.imageData;
  5917. return state;
  5918. },
  5919. ],
  5920. // we overwite the exif orientation tag so the image is oriented correctly
  5921. format === 'file' && orientImage && ImageHeadClearExifOrientationTag(),
  5922. // we write the new image head to the target blob
  5923. format === 'file' && copyImageHead && BlobWriteImageHead(),
  5924. // allow converting the blob to a different format
  5925. postprocessImageBlob && [
  5926. connect(postprocessImageBlob, ({ blob, imageData, src }, options, onprogress) => [
  5927. { blob, imageData, src },
  5928. options,
  5929. onprogress,
  5930. ], (state, blob) => (state.blob = blob)),
  5931. 'postprocess-image-file',
  5932. ],
  5933. // turn the image blob into a file, will also rename the file
  5934. format === 'file' && BlobToFile({ defaultFilename: 'image', renameFile }),
  5935. // upload or process data if is a file
  5936. format === 'file'
  5937. ? // used for file output formats
  5938. store &&
  5939. (isString(store)
  5940. ? // a basic store to post to
  5941. Store({ url: store })
  5942. : // see if is fully custom or store config
  5943. isFunction(store)
  5944. ? // fully custom store function
  5945. [store, 'store']
  5946. : // a store configuration object
  5947. Store(store))
  5948. : // used for imageData and canvas output formats
  5949. isFunction(store) && [store, 'store'],
  5950. // remove unwanted props
  5951. PropFilter(outputProps),
  5952. ].filter(Boolean);
  5953. };
  5954. var scrambleEffect = (options, done) => {
  5955. const { imageData, amount = 1 } = options;
  5956. const intensity = Math.round(Math.max(1, amount) * 2);
  5957. const range = Math.round(intensity * 0.5);
  5958. const inputWidth = imageData.width;
  5959. const inputHeight = imageData.height;
  5960. const outputData = new Uint8ClampedArray(inputWidth * inputHeight * 4);
  5961. const inputData = imageData.data;
  5962. let randomData;
  5963. let i = 0, x, y, r;
  5964. let xoffset = 0;
  5965. let yoffset = 0;
  5966. let index;
  5967. const l = inputWidth * inputHeight * 4 - 4;
  5968. for (y = 0; y < inputHeight; y++) {
  5969. randomData = crypto.getRandomValues(new Uint8ClampedArray(inputHeight));
  5970. for (x = 0; x < inputWidth; x++) {
  5971. r = randomData[y] / 255;
  5972. xoffset = 0;
  5973. yoffset = 0;
  5974. if (r < 0.5) {
  5975. xoffset = (-range + Math.round(Math.random() * intensity)) * 4;
  5976. }
  5977. if (r > 0.5) {
  5978. yoffset = (-range + Math.round(Math.random() * intensity)) * (inputWidth * 4);
  5979. }
  5980. // limit to image data
  5981. index = Math.min(Math.max(0, i + xoffset + yoffset), l);
  5982. outputData[i] = inputData[index];
  5983. outputData[i + 1] = inputData[index + 1];
  5984. outputData[i + 2] = inputData[index + 2];
  5985. outputData[i + 3] = inputData[index + 3];
  5986. i += 4;
  5987. }
  5988. }
  5989. done(null, {
  5990. data: outputData,
  5991. width: imageData.width,
  5992. height: imageData.height,
  5993. });
  5994. };
  5995. // basic blur covolution matrix
  5996. const BLUR_MATRIX = [0.0625, 0.125, 0.0625, 0.125, 0.25, 0.125, 0.0625, 0.125, 0.0625];
  5997. var imageDataScramble = async (inputData, options = {}) => {
  5998. if (!inputData)
  5999. return;
  6000. const { width, height } = inputData;
  6001. const { dataSize = 96, dataSizeScalar = 1, scrambleAmount = 4, blurAmount = 6, outputFormat = 'canvas', backgroundColor = [0, 0, 0], } = options;
  6002. const size = Math.round(dataSize * dataSizeScalar);
  6003. const scalar = Math.min(size / width, size / height);
  6004. const outputWidth = Math.floor(width * scalar);
  6005. const outputHeight = Math.floor(height * scalar);
  6006. // draw low res preview, add margin so blur isn't transparent
  6007. const scaledOutputCanvas = (h('canvas', { width: outputWidth, height: outputHeight }));
  6008. const ctx = scaledOutputCanvas.getContext('2d');
  6009. // fill background on transparent images
  6010. backgroundColor.length = 3; // prevent transparent colors
  6011. ctx.fillStyle = colorArrayToRGBA(backgroundColor);
  6012. ctx.fillRect(0, 0, outputWidth, outputHeight);
  6013. if (isImageData(inputData)) {
  6014. // temporarily draw to canvas so we can draw image data to scaled context
  6015. const transferCanvas = h('canvas', { width, height });
  6016. transferCanvas.getContext('2d').putImageData(inputData, 0, 0);
  6017. // draw to scaled context
  6018. ctx.drawImage(transferCanvas, 0, 0, outputWidth, outputHeight);
  6019. // release memory
  6020. releaseCanvas(transferCanvas);
  6021. }
  6022. else {
  6023. // bitmap data
  6024. ctx.drawImage(inputData, 0, 0, outputWidth, outputHeight);
  6025. }
  6026. // get scaled image data for scrambling
  6027. const imageData = ctx.getImageData(0, 0, outputWidth, outputHeight);
  6028. // filters to apply
  6029. const filters = [];
  6030. // add scramble filter
  6031. if (scrambleAmount > 0)
  6032. filters.push([scrambleEffect, { amount: scrambleAmount }]);
  6033. // add blur filters
  6034. if (blurAmount > 0)
  6035. for (let i = 0; i < blurAmount; i++) {
  6036. filters.push([convolutionEffect, { matrix: BLUR_MATRIX }]);
  6037. }
  6038. let imageDataScrambled;
  6039. if (filters.length) {
  6040. // builds effect chain
  6041. const chain = (transforms, i) => `(err, imageData) => {
  6042. (${transforms[i][0].toString()})(Object.assign({ imageData: imageData }, filterInstructions[${i}]),
  6043. ${transforms[i + 1] ? chain(transforms, i + 1) : 'done'})
  6044. }`;
  6045. const filterChain = `function (options, done) {
  6046. const filterInstructions = options.filterInstructions;
  6047. const imageData = options.imageData;
  6048. (${chain(filters, 0)})(null, imageData)
  6049. }`;
  6050. // scramble image data in separate thread
  6051. const imageDataObjectScrambled = await thread(filterChain, [
  6052. {
  6053. imageData: imageData,
  6054. filterInstructions: filters.map((t) => t[1]),
  6055. },
  6056. ], [imageData.data.buffer]);
  6057. imageDataScrambled = imageDataObjectToImageData(imageDataObjectScrambled);
  6058. }
  6059. else {
  6060. imageDataScrambled = imageData;
  6061. }
  6062. if (outputFormat === 'canvas') {
  6063. // put back scrambled data
  6064. ctx.putImageData(imageDataScrambled, 0, 0);
  6065. // return canvas
  6066. return scaledOutputCanvas;
  6067. }
  6068. return imageDataScrambled;
  6069. };
  6070. var getComponentExportedProps = (Component) => {
  6071. const descriptors = Object.getOwnPropertyDescriptors(Component.prototype);
  6072. return Object.keys(descriptors).filter((key) => !!descriptors[key]['get']);
  6073. };
  6074. function circOut(t) {
  6075. return Math.sqrt(1 - --t * t);
  6076. }
  6077. function is_date(obj) {
  6078. return Object.prototype.toString.call(obj) === '[object Date]';
  6079. }
  6080. function get_interpolator(a, b) {
  6081. if (a === b || a !== a)
  6082. return () => a;
  6083. const type = typeof a;
  6084. if (type !== typeof b || Array.isArray(a) !== Array.isArray(b)) {
  6085. throw new Error('Cannot interpolate values of different type');
  6086. }
  6087. if (Array.isArray(a)) {
  6088. const arr = b.map((bi, i) => {
  6089. return get_interpolator(a[i], bi);
  6090. });
  6091. return t => arr.map(fn => fn(t));
  6092. }
  6093. if (type === 'object') {
  6094. if (!a || !b)
  6095. throw new Error('Object cannot be null');
  6096. if (is_date(a) && is_date(b)) {
  6097. a = a.getTime();
  6098. b = b.getTime();
  6099. const delta = b - a;
  6100. return t => new Date(a + t * delta);
  6101. }
  6102. const keys = Object.keys(b);
  6103. const interpolators = {};
  6104. keys.forEach(key => {
  6105. interpolators[key] = get_interpolator(a[key], b[key]);
  6106. });
  6107. return t => {
  6108. const result = {};
  6109. keys.forEach(key => {
  6110. result[key] = interpolators[key](t);
  6111. });
  6112. return result;
  6113. };
  6114. }
  6115. if (type === 'number') {
  6116. const delta = b - a;
  6117. return t => a + t * delta;
  6118. }
  6119. throw new Error(`Cannot interpolate ${type} values`);
  6120. }
  6121. function tweened(value, defaults = {}) {
  6122. const store = writable(value);
  6123. let task;
  6124. let target_value = value;
  6125. function set(new_value, opts) {
  6126. if (value == null) {
  6127. store.set(value = new_value);
  6128. return Promise.resolve();
  6129. }
  6130. target_value = new_value;
  6131. let previous_task = task;
  6132. let started = false;
  6133. let { delay = 0, duration = 400, easing = identity, interpolate = get_interpolator } = assign(assign({}, defaults), opts);
  6134. if (duration === 0) {
  6135. if (previous_task) {
  6136. previous_task.abort();
  6137. previous_task = null;
  6138. }
  6139. store.set(value = target_value);
  6140. return Promise.resolve();
  6141. }
  6142. const start = now() + delay;
  6143. let fn;
  6144. task = loop(now => {
  6145. if (now < start)
  6146. return true;
  6147. if (!started) {
  6148. fn = interpolate(value, new_value);
  6149. if (typeof duration === 'function')
  6150. duration = duration(value, new_value);
  6151. started = true;
  6152. }
  6153. if (previous_task) {
  6154. previous_task.abort();
  6155. previous_task = null;
  6156. }
  6157. const elapsed = now - start;
  6158. if (elapsed > duration) {
  6159. store.set(value = new_value);
  6160. return false;
  6161. }
  6162. // @ts-ignore
  6163. store.set(value = fn(easing(elapsed / duration)));
  6164. return true;
  6165. });
  6166. return task.promise;
  6167. }
  6168. return {
  6169. set,
  6170. update: (fn, opts) => set(fn(target_value, value), opts),
  6171. subscribe: store.subscribe
  6172. };
  6173. }
  6174. // @ts-ignore
  6175. function tick_spring(ctx, last_value, current_value, target_value) {
  6176. if (typeof current_value === 'number') {
  6177. // @ts-ignore
  6178. const delta = target_value - current_value;
  6179. // @ts-ignore
  6180. const velocity = (current_value - last_value) / (ctx.dt || 1 / 60); // guard div by 0
  6181. const spring = ctx.opts.stiffness * delta;
  6182. const damper = ctx.opts.damping * velocity;
  6183. const acceleration = (spring - damper) * ctx.inv_mass;
  6184. const d = (velocity + acceleration) * ctx.dt;
  6185. if (Math.abs(d) < ctx.opts.precision && Math.abs(delta) < ctx.opts.precision) {
  6186. return target_value; // settled
  6187. }
  6188. else {
  6189. ctx.settled = false; // signal loop to keep ticking
  6190. // @ts-ignore
  6191. return current_value + d;
  6192. }
  6193. }
  6194. else if (isArray(current_value)) {
  6195. // @ts-ignore
  6196. return current_value.map((_, i) => tick_spring(ctx, last_value[i], current_value[i], target_value[i]));
  6197. }
  6198. else if (typeof current_value === 'object') {
  6199. const next_value = {};
  6200. // @ts-ignore
  6201. for (const k in current_value) {
  6202. // @ts-ignore
  6203. next_value[k] = tick_spring(ctx, last_value[k], current_value[k], target_value[k]);
  6204. }
  6205. // @ts-ignore
  6206. return next_value;
  6207. }
  6208. else {
  6209. throw new Error(`Cannot spring ${typeof current_value} values`);
  6210. }
  6211. }
  6212. // export interface Spring {
  6213. // set: (new_value: any, opts?: SpringUpdateOpts) => Promise<void>;
  6214. // update: (fn: Function, opts?: SpringUpdateOpts) => Promise<void>;
  6215. // subscribe: Function;
  6216. // precision: number;
  6217. // damping: number;
  6218. // stiffness: number;
  6219. // }
  6220. function spring(value, opts = {}) {
  6221. const store = writable(value);
  6222. const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts;
  6223. let last_time;
  6224. let task;
  6225. let current_token;
  6226. let last_value = value;
  6227. let target_value = value;
  6228. let inv_mass = 1;
  6229. let inv_mass_recovery_rate = 0;
  6230. let cancel_task = false;
  6231. function set(new_value, opts = {}) {
  6232. target_value = new_value;
  6233. const token = (current_token = {});
  6234. if (value == null || opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) {
  6235. cancel_task = true; // cancel any running animation
  6236. last_time = null;
  6237. last_value = new_value;
  6238. store.set((value = target_value));
  6239. return Promise.resolve();
  6240. }
  6241. else if (opts.soft) {
  6242. const rate = opts.soft === true ? 0.5 : +opts.soft;
  6243. inv_mass_recovery_rate = 1 / (rate * 60);
  6244. inv_mass = 0; // infinite mass, unaffected by spring forces
  6245. }
  6246. if (!task) {
  6247. last_time = null;
  6248. cancel_task = false;
  6249. const ctx = {
  6250. inv_mass: undefined,
  6251. opts: spring,
  6252. settled: true,
  6253. dt: undefined,
  6254. };
  6255. task = loop((now) => {
  6256. if (last_time === null)
  6257. last_time = now;
  6258. if (cancel_task) {
  6259. cancel_task = false;
  6260. task = null;
  6261. return false;
  6262. }
  6263. inv_mass = Math.min(inv_mass + inv_mass_recovery_rate, 1);
  6264. // altered so doesn't create a new object
  6265. ctx.inv_mass = inv_mass;
  6266. ctx.opts = spring;
  6267. ctx.settled = true; // tick_spring may signal false
  6268. ctx.dt = ((now - last_time) * 60) / 1000;
  6269. const next_value = tick_spring(ctx, last_value, value, target_value);
  6270. last_time = now;
  6271. last_value = value;
  6272. store.set((value = next_value));
  6273. if (ctx.settled)
  6274. task = null;
  6275. return !ctx.settled;
  6276. });
  6277. }
  6278. return new Promise((fulfil) => {
  6279. task.promise.then(() => {
  6280. if (token === current_token)
  6281. fulfil();
  6282. });
  6283. });
  6284. }
  6285. const spring = {
  6286. set,
  6287. update: (fn, opts) => set(fn(target_value, value), opts),
  6288. subscribe: store.subscribe,
  6289. stiffness,
  6290. damping,
  6291. precision,
  6292. };
  6293. return spring;
  6294. }
  6295. var prefersReducedMotion = readable(false, set => {
  6296. const mql = window.matchMedia('(prefers-reduced-motion:reduce)');
  6297. set(mql.matches);
  6298. mql.onchange = () => set(mql.matches);
  6299. });
  6300. var hasResizeObserver = () => 'ResizeObserver' in window;
  6301. //
  6302. const rectNext = rectCreateEmpty();
  6303. const updateNodeRect = (node, x, y, width, height) => {
  6304. if (!node.rect)
  6305. node.rect = rectCreateEmpty();
  6306. const rect = node.rect;
  6307. rectUpdate(rectNext, x, y, width, height);
  6308. if (rectEqual(rect, rectNext))
  6309. return;
  6310. rectUpdateWithRect(rect, rectNext);
  6311. node.dispatchEvent(new CustomEvent('measure', { detail: rect }));
  6312. };
  6313. // measures the element
  6314. const r = Math.round;
  6315. const measureViewRect = (node) => {
  6316. const clientRect = node.getBoundingClientRect();
  6317. updateNodeRect(node, r(clientRect.x), r(clientRect.y), r(clientRect.width), r(clientRect.height));
  6318. };
  6319. const measureOffset = (node) => updateNodeRect(node, node.offsetLeft, node.offsetTop, node.offsetWidth, node.offsetHeight);
  6320. // holds all the elements to measure using requestAnimationFrame
  6321. const elements = [];
  6322. // draw loop
  6323. let frame = null;
  6324. function tick() {
  6325. if (!elements.length) {
  6326. frame = null;
  6327. return;
  6328. }
  6329. elements.forEach((node) => node.measure(node));
  6330. frame = requestAnimationFrame(tick);
  6331. }
  6332. let observer; // ResizeObserver API not known by TypeScript
  6333. var measurable = (node, options = {}) => {
  6334. const { observePosition = false, observeViewRect = false, once = false, disabled = false, } = options;
  6335. // exit
  6336. if (disabled)
  6337. return;
  6338. // use resize observe if available
  6339. if (hasResizeObserver() && !observePosition && !observeViewRect) {
  6340. // we only create one observer, it will observe all registered elements
  6341. if (!observer) {
  6342. // @ts-ignore: [2020-02-20] ResizeObserver API not known by TypeScript
  6343. observer = new ResizeObserver((entries) => {
  6344. // @ts-ignore
  6345. entries.forEach((entry) => measureOffset(entry.target));
  6346. });
  6347. }
  6348. // start observing this node
  6349. observer.observe(node);
  6350. // measure our node for the first time
  6351. measureOffset(node);
  6352. // if should only measure once, remove now
  6353. if (once)
  6354. observer.unobserve(node);
  6355. // and we done, need to return a clean up method for when our node is destroyed
  6356. return {
  6357. destroy() {
  6358. // already unobserved this node
  6359. if (once)
  6360. return;
  6361. observer.unobserve(node);
  6362. // TODO: test if all nodes have been removed, if so, remove observer
  6363. },
  6364. };
  6365. }
  6366. // set measure function
  6367. node.measure = observeViewRect ? measureViewRect : measureOffset;
  6368. // add so the element is measured
  6369. elements.push(node);
  6370. // start measuring on next frame, we set up a single measure loop,
  6371. // the loop will check if there's still elements that need to be measured,
  6372. // else it will stop running
  6373. if (!frame)
  6374. frame = requestAnimationFrame(tick);
  6375. // measure this element now
  6376. node.measure(node);
  6377. // remove method
  6378. return {
  6379. destroy() {
  6380. const index = elements.indexOf(node);
  6381. elements.splice(index, 1);
  6382. },
  6383. };
  6384. };
  6385. var focusvisible = (element) => {
  6386. let isKeyboardInteraction = false;
  6387. const handlePointerdown = () => {
  6388. isKeyboardInteraction = false;
  6389. };
  6390. const handleKeydown = () => {
  6391. isKeyboardInteraction = true;
  6392. };
  6393. const handleKeyup = () => {
  6394. isKeyboardInteraction = false;
  6395. };
  6396. const handleFocus = (e) => {
  6397. if (!isKeyboardInteraction)
  6398. return;
  6399. e.target.dataset.focusVisible = '';
  6400. };
  6401. const handleBlur = (e) => {
  6402. delete e.target.dataset.focusVisible;
  6403. };
  6404. const map = {
  6405. pointerdown: handlePointerdown,
  6406. keydown: handleKeydown,
  6407. keyup: handleKeyup,
  6408. focus: handleFocus,
  6409. blur: handleBlur,
  6410. };
  6411. Object.keys(map).forEach((event) => element.addEventListener(event, map[event], true));
  6412. return {
  6413. destroy() {
  6414. Object.keys(map).forEach((event) => element.removeEventListener(event, map[event], true));
  6415. },
  6416. };
  6417. };
  6418. const getResourceFromItem = async (item) => new Promise((resolve) => {
  6419. if (item.kind === 'file')
  6420. return resolve(item.getAsFile());
  6421. item.getAsString(resolve);
  6422. });
  6423. const getResourcesFromEvent = (e) => new Promise((resolve, reject) => {
  6424. const { items } = e.dataTransfer;
  6425. if (!items)
  6426. return resolve([]);
  6427. Promise.all(Array.from(items).map(getResourceFromItem))
  6428. .then((res) => {
  6429. resolve(res.filter((item) => (isBinary(item) && isImage(item)) || /^http/.test(item)));
  6430. })
  6431. .catch(reject);
  6432. });
  6433. var dropable = (node, options = {}) => {
  6434. const handleDragOver = (e) => {
  6435. // need to be prevent default to allow drop
  6436. e.preventDefault();
  6437. };
  6438. const handleDrop = async (e) => {
  6439. e.preventDefault();
  6440. e.stopPropagation(); // prevents parents from catching this drop
  6441. try {
  6442. const resources = await getResourcesFromEvent(e);
  6443. node.dispatchEvent(new CustomEvent('dropfiles', {
  6444. detail: {
  6445. event: e,
  6446. resources,
  6447. },
  6448. ...options,
  6449. }));
  6450. }
  6451. catch (err) {
  6452. // silent, wasn't able to catch
  6453. }
  6454. };
  6455. node.addEventListener('drop', handleDrop);
  6456. node.addEventListener('dragover', handleDragOver);
  6457. // remove method
  6458. return {
  6459. destroy() {
  6460. node.removeEventListener('drop', handleDrop);
  6461. node.removeEventListener('dragover', handleDragOver);
  6462. },
  6463. };
  6464. };
  6465. let result$6 = null;
  6466. var supportsWebGL2 = () => {
  6467. if (result$6 === null) {
  6468. if ('WebGL2RenderingContext' in window) {
  6469. let canvas;
  6470. try {
  6471. canvas = h('canvas');
  6472. result$6 = !!canvas.getContext('webgl2');
  6473. }
  6474. catch (err) {
  6475. result$6 = false;
  6476. }
  6477. canvas && releaseCanvas(canvas);
  6478. }
  6479. else {
  6480. result$6 = false;
  6481. }
  6482. }
  6483. return result$6;
  6484. };
  6485. var getWebGLContext = (canvas, attrs) => {
  6486. if (supportsWebGL2())
  6487. return canvas.getContext('webgl2', attrs);
  6488. return (canvas.getContext('webgl', attrs) ||
  6489. canvas.getContext('experimental-webgl', attrs));
  6490. };
  6491. let result$5 = null;
  6492. var isSoftwareRendering = () => {
  6493. if (result$5 === null) {
  6494. if (isBrowser()) {
  6495. const canvas = h('canvas');
  6496. result$5 = !getWebGLContext(canvas, {
  6497. failIfMajorPerformanceCaveat: true,
  6498. });
  6499. releaseCanvas(canvas);
  6500. }
  6501. else {
  6502. result$5 = false;
  6503. }
  6504. }
  6505. return result$5;
  6506. };
  6507. var isPowerOf2 = (value) => (value & (value - 1)) === 0;
  6508. var stringReplace = (str, entries = {}, prefix = '', postfix = '') => {
  6509. return Object.keys(entries)
  6510. .filter((key) => !isObject(entries[key]))
  6511. .reduce((prev, curr) => {
  6512. return prev.replace(new RegExp(prefix + curr + postfix), entries[curr]);
  6513. }, str);
  6514. };
  6515. var SHADER_FRAG_HEAD = "#version 300 es\nprecision highp float;\n\nout vec4 fragColor;"; // eslint-disable-line
  6516. var SHADER_FRAG_INIT = "\nfloat a=1.0;vec4 fillColor=uColor;vec4 textureColor=texture(uTexture,vTexCoord);textureColor*=(1.0-step(1.0,vTexCoord.y))*step(0.0,vTexCoord.y)*(1.0-step(1.0,vTexCoord.x))*step(0.0,vTexCoord.x);"; // eslint-disable-line
  6517. var SHADER_FRAG_MASK = "\nuniform float uMaskFeather[8];uniform float uMaskBounds[4];uniform float uMaskOpacity;float mask(float x,float y,float bounds[4],float opacity){return 1.0-(1.0-(smoothstep(bounds[3],bounds[3]+1.0,x)*(1.0-smoothstep(bounds[1]-1.0,bounds[1],x))*(1.0-step(bounds[0],y))*step(bounds[2],y)))*(1.0-opacity);}"; // eslint-disable-line
  6518. var SHADER_FRAG_MASK_APPLY = "\nfloat m=mask(gl_FragCoord.x,gl_FragCoord.y,uMaskBounds,uMaskOpacity);"; // eslint-disable-line
  6519. var SHADER_FRAG_MASK_FEATHER_APPLY = "\nfloat leftFeatherOpacity=step(uMaskFeather[1],gl_FragCoord.x)*uMaskFeather[0]+((1.0-uMaskFeather[0])*smoothstep(uMaskFeather[1],uMaskFeather[3],gl_FragCoord.x));float rightFeatherOpacity=(1.0-step(uMaskFeather[7],gl_FragCoord.x))*uMaskFeather[4]+((1.0-uMaskFeather[4])*smoothstep(uMaskFeather[7],uMaskFeather[5],gl_FragCoord.x));a*=leftFeatherOpacity*rightFeatherOpacity;"; // eslint-disable-line
  6520. var SHADER_FRAG_RECT_AA = "\nvec2 scaledPoint=vec2(vRectCoord.x*uSize.x,vRectCoord.y*uSize.y);a*=smoothstep(0.0,1.0,uSize.x-scaledPoint.x);a*=smoothstep(0.0,1.0,uSize.y-scaledPoint.y);a*=smoothstep(0.0,1.0,scaledPoint.x);a*=smoothstep(0.0,1.0,scaledPoint.y);"; // eslint-disable-line
  6521. var SHADER_FRAG_CORNER_RADIUS = "\nvec2 s=(uSize-2.0)*.5;vec2 r=(vRectCoord*uSize);vec2 p=r-(uSize*.5);float cornerRadius=uCornerRadius[0];bool left=r.x<s.x;bool top=r.y<s.x;if(!left&&top){cornerRadius=uCornerRadius[1];}if(!left&&!top){cornerRadius=uCornerRadius[3];}if(left&&!top){cornerRadius=uCornerRadius[2];}a*=1.0-clamp(length(max(abs(p)-(s-cornerRadius),0.0))-cornerRadius,0.0,1.0);"; // eslint-disable-line
  6522. var SHADER_FRAG_SHAPE_BLEND_COLOR = "\nif(m<=0.0)discard;fillColor.a*=a;fillColor.rgb*=fillColor.a;fillColor.rgb*=m;fillColor.rgb+=(1.0-m)*(uCanvasColor.rgb*fillColor.a);textureColor*=uTextureOpacity;textureColor.a*=a;textureColor.rgb*=m*a;textureColor.rgb+=(1.0-m)*(uCanvasColor.rgb*textureColor.a);fragColor=textureColor+(fillColor*(1.0-textureColor.a));"; // eslint-disable-line
  6523. var SHADER_FRAG_TEXTURE_COLORIZE = "\nif(uTextureColor.a!=0.0&&textureColor.a>0.0){vec3 colorFlattened=textureColor.rgb/textureColor.a;if(colorFlattened.r>.999999&&colorFlattened.g==0.0&&colorFlattened.b>.999999){textureColor.rgb=uTextureColor.rgb*textureColor.a;}textureColor*=uTextureColor.a;}"; // eslint-disable-line
  6524. var SHADER_VERT_HEAD = "#version 300 es\n\nin vec4 aPosition;uniform mat4 uMatrix;"; // eslint-disable-line
  6525. var SHADER_VERT_MULTIPLY_MATRUX = "\ngl_Position=uMatrix*vec4(aPosition.x,aPosition.y,0,1);"; // eslint-disable-line
  6526. var SHADER_VERT_TEXTURE = "\nin vec2 aTexCoord;out vec2 vTexCoord;"; // eslint-disable-line
  6527. const SHADER_VERT_SNIPPETS = {
  6528. head: SHADER_VERT_HEAD,
  6529. text: SHADER_VERT_TEXTURE,
  6530. matrix: SHADER_VERT_MULTIPLY_MATRUX,
  6531. };
  6532. const SHADER_FRAG_SNIPPETS = {
  6533. head: SHADER_FRAG_HEAD,
  6534. mask: SHADER_FRAG_MASK,
  6535. init: SHADER_FRAG_INIT,
  6536. colorize: SHADER_FRAG_TEXTURE_COLORIZE,
  6537. maskapply: SHADER_FRAG_MASK_APPLY,
  6538. maskfeatherapply: SHADER_FRAG_MASK_FEATHER_APPLY,
  6539. edgeaa: SHADER_FRAG_RECT_AA,
  6540. cornerradius: SHADER_FRAG_CORNER_RADIUS,
  6541. fragcolor: SHADER_FRAG_SHAPE_BLEND_COLOR,
  6542. };
  6543. const transpileShader = (gl, src, type) => {
  6544. src = stringReplace(src, type === gl.VERTEX_SHADER ? SHADER_VERT_SNIPPETS : SHADER_FRAG_SNIPPETS, '##').trim();
  6545. // ready if supports webgl
  6546. if (supportsWebGL2())
  6547. return src;
  6548. src = src.replace(/#version.+/gm, '').trim();
  6549. src = src.replace(/^\/\/\#/gm, '#');
  6550. if (type === gl.VERTEX_SHADER) {
  6551. src = src.replace(/in /gm, 'attribute ').replace(/out /g, 'varying ');
  6552. }
  6553. if (type === gl.FRAGMENT_SHADER) {
  6554. src = src
  6555. .replace(/in /gm, 'varying ')
  6556. .replace(/out.*?;/gm, '')
  6557. .replace(/texture\(/g, 'texture2D(')
  6558. .replace(/fragColor/g, 'gl_FragColor');
  6559. }
  6560. return `${src}`;
  6561. };
  6562. const compileShader = (gl, src, type) => {
  6563. const shader = gl.createShader(type);
  6564. const transpiledSrc = transpileShader(gl, src, type);
  6565. gl.shaderSource(shader, transpiledSrc);
  6566. gl.compileShader(shader);
  6567. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  6568. console.error(gl.getShaderInfoLog(shader));
  6569. }
  6570. return shader;
  6571. };
  6572. const createShader = (gl, vertexShader, fragmentShader, attribs, uniforms) => {
  6573. const program = gl.createProgram();
  6574. gl.attachShader(program, compileShader(gl, vertexShader, gl.VERTEX_SHADER));
  6575. gl.attachShader(program, compileShader(gl, fragmentShader, gl.FRAGMENT_SHADER));
  6576. gl.linkProgram(program);
  6577. const locations = {};
  6578. attribs.forEach((name) => {
  6579. locations[name] = gl.getAttribLocation(program, name);
  6580. });
  6581. uniforms.forEach((name) => {
  6582. locations[name] = gl.getUniformLocation(program, name);
  6583. });
  6584. return {
  6585. program,
  6586. locations,
  6587. };
  6588. };
  6589. const canMipMap = (source) => {
  6590. if (supportsWebGL2())
  6591. return true;
  6592. return isPowerOf2(source.width) && isPowerOf2(source.height);
  6593. };
  6594. const applyTextureProperties = (gl, source, options) => {
  6595. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, canMipMap(source) ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
  6596. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, options.filter // === 'nearest' ? gl.NEAREST : gl.LINEAR
  6597. );
  6598. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  6599. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  6600. if (canMipMap(source))
  6601. gl.generateMipmap(gl.TEXTURE_2D);
  6602. };
  6603. const updateTexture = (gl, texture, source, options) => {
  6604. gl.bindTexture(gl.TEXTURE_2D, texture);
  6605. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
  6606. applyTextureProperties(gl, source, options);
  6607. gl.bindTexture(gl.TEXTURE_2D, null);
  6608. return texture;
  6609. };
  6610. const applyOpacity = (color, opacity = 1) => color
  6611. ? [color[0], color[1], color[2], isNumber(color[3]) ? opacity * color[3] : opacity]
  6612. : [0, 0, 0, 0];
  6613. const mat4Create = () => {
  6614. const mat = new Float32Array(16);
  6615. mat[0] = 1;
  6616. mat[5] = 1;
  6617. mat[10] = 1;
  6618. mat[15] = 1;
  6619. return mat;
  6620. };
  6621. const mat4Perspective = (mat, fovy, aspect, near, far) => {
  6622. const f = 1.0 / Math.tan(fovy / 2);
  6623. const nf = 1 / (near - far);
  6624. mat[0] = f / aspect;
  6625. mat[1] = 0;
  6626. mat[2] = 0;
  6627. mat[3] = 0;
  6628. mat[4] = 0;
  6629. mat[5] = f;
  6630. mat[6] = 0;
  6631. mat[7] = 0;
  6632. mat[8] = 0;
  6633. mat[9] = 0;
  6634. mat[10] = (far + near) * nf;
  6635. mat[11] = -1;
  6636. mat[12] = 0;
  6637. mat[13] = 0;
  6638. mat[14] = 2 * far * near * nf;
  6639. mat[15] = 0;
  6640. };
  6641. const mat4Ortho = (mat, left, right, bottom, top, near, far) => {
  6642. const lr = 1 / (left - right);
  6643. const bt = 1 / (bottom - top);
  6644. const nf = 1 / (near - far);
  6645. mat[0] = -2 * lr;
  6646. mat[1] = 0;
  6647. mat[2] = 0;
  6648. mat[3] = 0;
  6649. mat[4] = 0;
  6650. mat[5] = -2 * bt;
  6651. mat[6] = 0;
  6652. mat[7] = 0;
  6653. mat[8] = 0;
  6654. mat[9] = 0;
  6655. mat[10] = 2 * nf;
  6656. mat[11] = 0;
  6657. mat[12] = (left + right) * lr;
  6658. mat[13] = (top + bottom) * bt;
  6659. mat[14] = (far + near) * nf;
  6660. mat[15] = 1;
  6661. };
  6662. const mat4Translate = (mat, x, y, z) => {
  6663. mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
  6664. mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
  6665. mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
  6666. mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
  6667. };
  6668. const mat4Scale = (mat, s) => {
  6669. mat[0] = mat[0] * s;
  6670. mat[1] = mat[1] * s;
  6671. mat[2] = mat[2] * s;
  6672. mat[3] = mat[3] * s;
  6673. mat[4] = mat[4] * s;
  6674. mat[5] = mat[5] * s;
  6675. mat[6] = mat[6] * s;
  6676. mat[7] = mat[7] * s;
  6677. mat[8] = mat[8] * s;
  6678. mat[9] = mat[9] * s;
  6679. mat[10] = mat[10] * s;
  6680. mat[11] = mat[11] * s;
  6681. };
  6682. const mat4ScaleX = (mat, s) => {
  6683. mat[0] = mat[0] * s;
  6684. mat[1] = mat[1] * s;
  6685. mat[2] = mat[2] * s;
  6686. mat[3] = mat[3] * s;
  6687. };
  6688. const mat4ScaleY = (mat, s) => {
  6689. mat[4] = mat[4] * s;
  6690. mat[5] = mat[5] * s;
  6691. mat[6] = mat[6] * s;
  6692. mat[7] = mat[7] * s;
  6693. };
  6694. const mat4RotateX = (mat, rad) => {
  6695. const s = Math.sin(rad);
  6696. const c = Math.cos(rad);
  6697. const a10 = mat[4];
  6698. const a11 = mat[5];
  6699. const a12 = mat[6];
  6700. const a13 = mat[7];
  6701. const a20 = mat[8];
  6702. const a21 = mat[9];
  6703. const a22 = mat[10];
  6704. const a23 = mat[11];
  6705. mat[4] = a10 * c + a20 * s;
  6706. mat[5] = a11 * c + a21 * s;
  6707. mat[6] = a12 * c + a22 * s;
  6708. mat[7] = a13 * c + a23 * s;
  6709. mat[8] = a20 * c - a10 * s;
  6710. mat[9] = a21 * c - a11 * s;
  6711. mat[10] = a22 * c - a12 * s;
  6712. mat[11] = a23 * c - a13 * s;
  6713. };
  6714. const mat4RotateY = (mat, rad) => {
  6715. const s = Math.sin(rad);
  6716. const c = Math.cos(rad);
  6717. const a00 = mat[0];
  6718. const a01 = mat[1];
  6719. const a02 = mat[2];
  6720. const a03 = mat[3];
  6721. const a20 = mat[8];
  6722. const a21 = mat[9];
  6723. const a22 = mat[10];
  6724. const a23 = mat[11];
  6725. mat[0] = a00 * c - a20 * s;
  6726. mat[1] = a01 * c - a21 * s;
  6727. mat[2] = a02 * c - a22 * s;
  6728. mat[3] = a03 * c - a23 * s;
  6729. mat[8] = a00 * s + a20 * c;
  6730. mat[9] = a01 * s + a21 * c;
  6731. mat[10] = a02 * s + a22 * c;
  6732. mat[11] = a03 * s + a23 * c;
  6733. };
  6734. const mat4RotateZ = (mat, rad) => {
  6735. const s = Math.sin(rad);
  6736. const c = Math.cos(rad);
  6737. const a00 = mat[0];
  6738. const a01 = mat[1];
  6739. const a02 = mat[2];
  6740. const a03 = mat[3];
  6741. const a10 = mat[4];
  6742. const a11 = mat[5];
  6743. const a12 = mat[6];
  6744. const a13 = mat[7];
  6745. mat[0] = a00 * c + a10 * s;
  6746. mat[1] = a01 * c + a11 * s;
  6747. mat[2] = a02 * c + a12 * s;
  6748. mat[3] = a03 * c + a13 * s;
  6749. mat[4] = a10 * c - a00 * s;
  6750. mat[5] = a11 * c - a01 * s;
  6751. mat[6] = a12 * c - a02 * s;
  6752. mat[7] = a13 * c - a03 * s;
  6753. };
  6754. var degToRad = (degrees) => degrees * Math.PI / 180;
  6755. var imageFragmentShader = "\n##head\nin vec2 vTexCoord;uniform sampler2D uTexture;uniform sampler2D uTextureMarkup;uniform sampler2D uTextureBlend;uniform vec2 uTextureSize;uniform float uOpacity;uniform vec4 uFillColor;uniform vec4 uOverlayColor;uniform mat4 uColorMatrix;uniform vec4 uColorOffset;uniform float uClarityKernel[9];uniform float uClarityKernelWeight;uniform float uColorGamma;uniform float uColorVignette;uniform float uMaskClip;uniform float uMaskOpacity;uniform float uMaskBounds[4];uniform float uMaskCornerRadius[4];uniform float uMaskFeather[8];vec4 applyGamma(vec4 c,float g){c.r=pow(c.r,g);c.g=pow(c.g,g);c.b=pow(c.b,g);return c;}vec4 applyColorMatrix(vec4 c,mat4 m,vec4 o){vec4 cM=(c*m)+o;cM*=cM.a;return cM;}vec4 applyConvolutionMatrix(vec4 c,float k0,float k1,float k2,float k3,float k4,float k5,float k6,float k7,float k8,float w){vec2 pixel=vec2(1)/uTextureSize;vec4 colorSum=texture(uTexture,vTexCoord-pixel)*k0+texture(uTexture,vTexCoord+pixel*vec2(0.0,-1.0))*k1+texture(uTexture,vTexCoord+pixel*vec2(1.0,-1.0))*k2+texture(uTexture,vTexCoord+pixel*vec2(-1.0,0.0))*k3+texture(uTexture,vTexCoord)*k4+texture(uTexture,vTexCoord+pixel*vec2(1.0,0.0))*k5+texture(uTexture,vTexCoord+pixel*vec2(-1.0,1.0))*k6+texture(uTexture,vTexCoord+pixel*vec2(0.0,1.0))*k7+texture(uTexture,vTexCoord+pixel)*k8;vec4 color=vec4((colorSum/w).rgb,c.a);color.rgb=clamp(color.rgb,0.0,1.0);return color;}vec4 applyVignette(vec4 c,vec2 pos,vec2 center,float v){float d=distance(pos,center)/length(center);float f=1.0-(d*abs(v));if(v>0.0){c.rgb*=f;}else if(v<0.0){c.rgb+=(1.0-f)*(1.0-c.rgb);}return c;}vec4 blendPremultipliedAlpha(vec4 back,vec4 front){return front+(back*(1.0-front.a));}void main(){float x=gl_FragCoord.x;float y=gl_FragCoord.y;float a=1.0;float maskTop=uMaskBounds[0];float maskRight=uMaskBounds[1];float maskBottom=uMaskBounds[2];float maskLeft=uMaskBounds[3];float leftFeatherOpacity=step(uMaskFeather[1],x)*uMaskFeather[0]+((1.0-uMaskFeather[0])*smoothstep(uMaskFeather[1],uMaskFeather[3],x));float rightFeatherOpacity=(1.0-step(uMaskFeather[7],x))*uMaskFeather[4]+((1.0-uMaskFeather[4])*smoothstep(uMaskFeather[7],uMaskFeather[5],x));a*=leftFeatherOpacity*rightFeatherOpacity;float overlayColorAlpha=(smoothstep(maskLeft,maskLeft+1.0,x)*(1.0-smoothstep(maskRight-1.0,maskRight,x))*(1.0-step(maskTop,y))*step(maskBottom,y));if(uOverlayColor.a==0.0){a*=overlayColorAlpha;}vec2 offset=vec2(maskLeft,maskBottom);vec2 size=vec2(maskRight-maskLeft,maskTop-maskBottom)*.5;vec2 center=offset.xy+size.xy;int pixelX=int(step(center.x,x));int pixelY=int(step(y,center.y));float cornerRadius=0.0;if(pixelX==0&&pixelY==0)cornerRadius=uMaskCornerRadius[0];if(pixelX==1&&pixelY==0)cornerRadius=uMaskCornerRadius[1];if(pixelX==0&&pixelY==1)cornerRadius=uMaskCornerRadius[2];if(pixelX==1&&pixelY==1)cornerRadius=uMaskCornerRadius[3];float cornerOffset=sign(cornerRadius)*length(max(abs(gl_FragCoord.xy-size-offset)-size+cornerRadius,0.0))-cornerRadius;float cornerOpacity=1.0-smoothstep(0.0,1.0,cornerOffset);a*=cornerOpacity;vec2 scaledPoint=vec2(vTexCoord.x*uTextureSize.x,vTexCoord.y*uTextureSize.y);a*=smoothstep(0.0,1.0,uTextureSize.x-scaledPoint.x);a*=smoothstep(0.0,1.0,uTextureSize.y-scaledPoint.y);a*=smoothstep(0.0,1.0,scaledPoint.x);a*=smoothstep(0.0,1.0,scaledPoint.y);vec4 color=texture(uTexture,vTexCoord);color=blendPremultipliedAlpha(color,texture(uTextureBlend,vTexCoord));if(uClarityKernelWeight!=-1.0){color=applyConvolutionMatrix(color,uClarityKernel[0],uClarityKernel[1],uClarityKernel[2],uClarityKernel[3],uClarityKernel[4],uClarityKernel[5],uClarityKernel[6],uClarityKernel[7],uClarityKernel[8],uClarityKernelWeight);}color=applyGamma(color,uColorGamma);color=applyColorMatrix(color,uColorMatrix,uColorOffset);color=blendPremultipliedAlpha(uFillColor,color);color*=a;if(uColorVignette!=0.0){vec2 pos=gl_FragCoord.xy-offset;color=applyVignette(color,pos,center-offset,uColorVignette);}color=blendPremultipliedAlpha(color,texture(uTextureMarkup,vTexCoord));vec4 overlayColor=uOverlayColor*(1.0-overlayColorAlpha);overlayColor.rgb*=overlayColor.a;color=blendPremultipliedAlpha(color,overlayColor);if(uOverlayColor.a>0.0&&color.a<1.0&&uFillColor.a>0.0){color=blendPremultipliedAlpha(uFillColor,overlayColor);}color*=uOpacity;fragColor=color;}"; // eslint-disable-line
  6756. var imageVertexShader = "\n##head\n##text\nvoid main(){vTexCoord=aTexCoord;gl_Position=uMatrix*aPosition;}"; // eslint-disable-line
  6757. var pathVertexShader = "#version 300 es\n\nin vec4 aPosition;in vec2 aNormal;in float aMiter;out vec2 vNormal;out float vMiter;out float vWidth;uniform float uWidth;uniform mat4 uMatrix;void main(){vMiter=aMiter;vNormal=aNormal;vWidth=(uWidth*.5)+1.0;gl_Position=uMatrix*vec4(aPosition.x+(aNormal.x*vWidth*aMiter),aPosition.y+(aNormal.y*vWidth*aMiter),0,1);}"; // eslint-disable-line
  6758. var pathFragmentShader = "\n##head\n##mask\nin vec2 vNormal;in float vMiter;in float vWidth;uniform float uWidth;uniform vec4 uColor;uniform vec4 uCanvasColor;void main(){vec4 fillColor=uColor;float m=mask(gl_FragCoord.x,gl_FragCoord.y,uMaskBounds,uMaskOpacity);if(m<=0.0)discard;fillColor.a*=clamp(smoothstep(vWidth-.5,vWidth-1.0,abs(vMiter)*vWidth),0.0,1.0);fillColor.rgb*=fillColor.a;fillColor.rgb*=m;fillColor.rgb+=(1.0-m)*(uCanvasColor.rgb*fillColor.a);fragColor=fillColor;}"; // eslint-disable-line
  6759. var rectVertexShader = "\n##head\n##text\nin vec2 aRectCoord;out vec2 vRectCoord;void main(){vTexCoord=aTexCoord;vRectCoord=aRectCoord;\n##matrix\n}"; // eslint-disable-line
  6760. var rectFragmentShader = "\n##head\n##mask\nin vec2 vTexCoord;in vec2 vRectCoord;uniform sampler2D uTexture;uniform vec4 uTextureColor;uniform float uTextureOpacity;uniform vec4 uColor;uniform float uCornerRadius[4];uniform vec2 uSize;uniform vec2 uPosition;uniform vec4 uCanvasColor;uniform int uInverted;void main(){\n##init\n##colorize\n##edgeaa\n##cornerradius\n##maskfeatherapply\nif(uInverted==1)a=1.0-a;\n##maskapply\n##fragcolor\n}"; // eslint-disable-line
  6761. var ellipseVertexShader = "\n##head\n##text\nout vec2 vTexCoordDouble;void main(){vTexCoordDouble=vec2(aTexCoord.x*2.0-1.0,aTexCoord.y*2.0-1.0);vTexCoord=aTexCoord;\n##matrix\n}"; // eslint-disable-line
  6762. var ellipseFragmentShader = "\n##head\n##mask\nin vec2 vTexCoord;in vec2 vTexCoordDouble;uniform sampler2D uTexture;uniform float uTextureOpacity;uniform vec2 uRadius;uniform vec4 uColor;uniform int uInverted;uniform vec4 uCanvasColor;void main(){\n##init\nfloat ar=uRadius.x/uRadius.y;vec2 rAA=vec2(uRadius.x-1.0,uRadius.y-(1.0/ar));vec2 scaledPointSq=vec2((vTexCoordDouble.x*uRadius.x)*(vTexCoordDouble.x*uRadius.x),(vTexCoordDouble.y*uRadius.y)*(vTexCoordDouble.y*uRadius.y));float p=(scaledPointSq.x/(uRadius.x*uRadius.x))+(scaledPointSq.y/(uRadius.y*uRadius.y));float pAA=(scaledPointSq.x/(rAA.x*rAA.x))+(scaledPointSq.y/(rAA.y*rAA.y));a=smoothstep(1.0,p/pAA,p);if(uInverted==1)a=1.0-a;\n##maskapply\n##fragcolor\n}"; // eslint-disable-line
  6763. var triangleVertexShader = "\n##head\nvoid main(){\n##matrix\n}"; // eslint-disable-line
  6764. var triangleFragmentShader = "\n##head\n##mask\nuniform vec4 uColor;uniform vec4 uCanvasColor;void main(){vec4 fillColor=uColor;\n##maskapply\nfillColor.rgb*=fillColor.a;fillColor.rgb*=m;fillColor.rgb+=(1.0-m)*(uCanvasColor.rgb*fillColor.a);fragColor=fillColor;}"; // eslint-disable-line
  6765. const createPathSegment = (vertices, index, a, b, c) => {
  6766. const ab = vectorNormalize(vectorCreate(b.x - a.x, b.y - a.y));
  6767. const bc = vectorNormalize(vectorCreate(c.x - b.x, c.y - b.y));
  6768. const tangent = vectorNormalize(vectorCreate(ab.x + bc.x, ab.y + bc.y));
  6769. const miter = vectorCreate(-tangent.y, tangent.x);
  6770. const normal = vectorCreate(-ab.y, ab.x);
  6771. // limit miter length (TEMP fix to prevent spikes, should eventually add caps)
  6772. const miterLength = Math.min(1 / vectorDot(miter, normal), 5);
  6773. vertices[index] = b.x;
  6774. vertices[index + 1] = b.y;
  6775. vertices[index + 2] = miter.x * miterLength;
  6776. vertices[index + 3] = miter.y * miterLength;
  6777. vertices[index + 4] = -1;
  6778. vertices[index + 5] = b.x;
  6779. vertices[index + 6] = b.y;
  6780. vertices[index + 7] = miter.x * miterLength;
  6781. vertices[index + 8] = miter.y * miterLength;
  6782. vertices[index + 9] = 1;
  6783. };
  6784. const createPathVertices = (points, close) => {
  6785. let a, b, c, i = 0;
  6786. const l = points.length;
  6787. const stride = 10;
  6788. const vertices = new Float32Array((close ? l + 1 : l) * stride);
  6789. const first = points[0];
  6790. const last = points[l - 1];
  6791. for (i = 0; i < l; i++) {
  6792. a = points[i - 1];
  6793. b = points[i];
  6794. c = points[i + 1];
  6795. // if previous point not available use inverse vector to next point
  6796. if (!a)
  6797. a = close ? last : vectorCreate(b.x + (b.x - c.x), b.y + (b.y - c.y));
  6798. // if next point not available use inverse vector from previous point
  6799. if (!c)
  6800. c = close ? first : vectorCreate(b.x + (b.x - a.x), b.y + (b.y - a.y));
  6801. createPathSegment(vertices, i * stride, a, b, c);
  6802. }
  6803. if (close)
  6804. createPathSegment(vertices, l * stride, last, first, points[1]);
  6805. return vertices;
  6806. };
  6807. const rectPointsToVertices = (points) => {
  6808. // [tl, tr, br, bl]
  6809. // B D
  6810. // | \ |
  6811. // A C
  6812. const vertices = new Float32Array(8);
  6813. vertices[0] = points[3].x;
  6814. vertices[1] = points[3].y;
  6815. vertices[2] = points[0].x;
  6816. vertices[3] = points[0].y;
  6817. vertices[4] = points[2].x;
  6818. vertices[5] = points[2].y;
  6819. vertices[6] = points[1].x;
  6820. vertices[7] = points[1].y;
  6821. return vertices;
  6822. };
  6823. const trianglePointToVertices = (points) => {
  6824. const vertices = new Float32Array(6);
  6825. vertices[0] = points[0].x;
  6826. vertices[1] = points[0].y;
  6827. vertices[2] = points[1].x;
  6828. vertices[3] = points[1].y;
  6829. vertices[4] = points[2].x;
  6830. vertices[5] = points[2].y;
  6831. return vertices;
  6832. };
  6833. const createRectPoints = (rect, rotation = 0, flipX, flipY) => {
  6834. const corners = rectGetCorners(rect);
  6835. const cx = rect.x + rect.width * 0.5;
  6836. const cy = rect.y + rect.height * 0.5;
  6837. if (flipX || flipY)
  6838. vectorsFlip(corners, flipX, flipY, cx, cy);
  6839. if (rotation !== 0)
  6840. vectorsRotate(corners, rotation, cx, cy);
  6841. return corners;
  6842. };
  6843. const createEllipseOutline = (x, y, width, height, rotation, flipX, flipY) => {
  6844. const rx = Math.abs(width) * 0.5;
  6845. const ry = Math.abs(height) * 0.5;
  6846. const size = Math.abs(width) + Math.abs(height);
  6847. const precision = Math.max(20, Math.round(size / 6));
  6848. return ellipseToPolygon(vectorCreate(x + rx, y + ry), rx, ry, rotation, flipX, flipY, precision);
  6849. };
  6850. const createRectOutline = (x, y, width, height, rotation, cornerRadius, flipX, flipY) => {
  6851. const points = [];
  6852. if (cornerRadius.every((v) => v === 0)) {
  6853. points.push(vectorCreate(x, y), // top left corner
  6854. vectorCreate(x + width, y), // top right corner
  6855. vectorCreate(x + width, y + height), // bottom right corner
  6856. vectorCreate(x, y + height) // bottom left corner
  6857. );
  6858. }
  6859. else {
  6860. const [tl, tr, bl, br] = cornerRadius;
  6861. const l = x;
  6862. const r = x + width;
  6863. const t = y;
  6864. const b = y + height;
  6865. // start at end of top left corner
  6866. points.push(vectorCreate(l + tl, t));
  6867. pushRectCornerPoints(points, r - tr, t + tr, tr, -1);
  6868. // move to bottom right corner
  6869. points.push(vectorCreate(r, t + tr));
  6870. pushRectCornerPoints(points, r - br, b - br, br, 0);
  6871. // move to bottom left corner
  6872. points.push(vectorCreate(r - br, b));
  6873. pushRectCornerPoints(points, l + bl, b - bl, bl, 1);
  6874. // move to top left corner
  6875. points.push(vectorCreate(l, b - bl));
  6876. pushRectCornerPoints(points, l + tl, t + tl, tl, 2);
  6877. }
  6878. if (flipX || flipY)
  6879. vectorsFlip(points, flipX, flipY, x + width * 0.5, y + height * 0.5);
  6880. if (rotation)
  6881. vectorsRotate(points, rotation, x + width * 0.5, y + height * 0.5);
  6882. return points;
  6883. };
  6884. const pushRectCornerPoints = (points, x, y, radius, offset) => {
  6885. const precision = Math.min(20, Math.max(4, Math.round(radius / 2)));
  6886. let p = 0;
  6887. let s = 0;
  6888. let rx = 0;
  6889. let ry = 0;
  6890. let i = 0;
  6891. for (; i < precision; i++) {
  6892. p = i / precision;
  6893. s = offset * HALF_PI + p * HALF_PI;
  6894. rx = radius * Math.cos(s);
  6895. ry = radius * Math.sin(s);
  6896. points.push(vectorCreate(x + rx, y + ry));
  6897. }
  6898. };
  6899. let limit = null;
  6900. var getWebGLTextureSizeLimit = () => {
  6901. if (limit !== null)
  6902. return limit;
  6903. const canvas = h('canvas');
  6904. const gl = getWebGLContext(canvas);
  6905. limit = gl ? gl.getParameter(gl.MAX_TEXTURE_SIZE) : undefined;
  6906. releaseCanvas(canvas);
  6907. return limit;
  6908. };
  6909. // prettier-ignore
  6910. // B D
  6911. // | \ |
  6912. // A C
  6913. const RECT_UV = new Float32Array([
  6914. 0.0, 1.0,
  6915. 0.0, 0.0,
  6916. 1.0, 1.0,
  6917. 1.0, 0.0,
  6918. ]);
  6919. const CLARITY_IDENTITY = [0, 0, 0, 0, 1, 0, 0, 0, 0];
  6920. const COLOR_MATRIX_IDENTITY$1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
  6921. const TEXTURE_TRANSPARENT_INDEX = 0;
  6922. const TEXTURE_PREVIEW_BLEND_INDEX = 1;
  6923. const TEXTURE_PREVIEW_MARKUP_INDEX = 2;
  6924. const TEXTURE_PREVIEW_INDEX = 3;
  6925. const TEXTURE_SHAPE_INDEX = 4;
  6926. const COLOR_TRANSPARENT = [0, 0, 0, 0];
  6927. const NO_CORNERS = [0, 0, 0, 0];
  6928. const calculateBackgroundUVMap = (width, height, backgroundSize, backgroundPosition, viewPixelDensity) => {
  6929. if (!backgroundSize || !backgroundPosition)
  6930. return RECT_UV;
  6931. const x = backgroundPosition.x / backgroundSize.width;
  6932. const y = backgroundPosition.y / backgroundSize.height;
  6933. let w = width / backgroundSize.width / viewPixelDensity;
  6934. let h = height / backgroundSize.height / viewPixelDensity;
  6935. w -= x;
  6936. h -= y;
  6937. // prettier-ignore
  6938. // B D
  6939. // | \ |
  6940. // A C
  6941. // bottom left
  6942. const ax = -x;
  6943. const ay = h;
  6944. // top left
  6945. const bx = -x;
  6946. const by = -y;
  6947. // bottom right
  6948. const cx = w;
  6949. const cy = h;
  6950. // top right
  6951. const dx = w;
  6952. const dy = -y;
  6953. return new Float32Array([
  6954. ax,
  6955. ay,
  6956. bx,
  6957. by,
  6958. cx,
  6959. cy,
  6960. dx,
  6961. dy,
  6962. ]);
  6963. };
  6964. const limitCornerRadius = (r, size) => {
  6965. return Math.floor(clamp(r, 0, Math.min((size.width - 1) * 0.5, (size.height - 1) * 0.5)));
  6966. };
  6967. var createWebGLCanvas = (canvas) => {
  6968. const viewSize = { width: 0, height: 0 };
  6969. const viewSizeVisual = { width: 0, height: 0 };
  6970. const textureSizeLimit = getWebGLTextureSizeLimit() || 1024;
  6971. let viewAspectRatio;
  6972. let viewPixelDensity;
  6973. const markupMatrixCanvas = mat4Create();
  6974. const markupMatrixFrameBuffer = mat4Create();
  6975. let markupMatrix;
  6976. let maskTop;
  6977. let maskRight;
  6978. let maskBottom;
  6979. let maskLeft;
  6980. let maskOpacity;
  6981. let maskBounds;
  6982. let IMAGE_MASK_FEATHER; // updated when viewport is resized
  6983. let RECT_MASK_FEATHER;
  6984. let CANVAS_COLOR_R = 0;
  6985. let CANVAS_COLOR_G = 0;
  6986. let CANVAS_COLOR_B = 0;
  6987. const indexTextureMap = new Map([]);
  6988. // resize view
  6989. const resize = (width, height, pixelDensity) => {
  6990. // density
  6991. viewPixelDensity = pixelDensity;
  6992. // visual size
  6993. viewSizeVisual.width = width;
  6994. viewSizeVisual.height = height;
  6995. // size
  6996. viewSize.width = width * viewPixelDensity;
  6997. viewSize.height = height * viewPixelDensity;
  6998. // calculate the aspect ratio, we use this to determine quad size
  6999. viewAspectRatio = getAspectRatio(viewSize.width, viewSize.height);
  7000. // sync dimensions with image data
  7001. canvas.width = viewSize.width;
  7002. canvas.height = viewSize.height;
  7003. // update canvas markup matrix
  7004. mat4Ortho(markupMatrixCanvas, 0, viewSize.width, viewSize.height, 0, -1, 1);
  7005. IMAGE_MASK_FEATHER = [1, 0, 1, 0, 1, viewSizeVisual.width, 1, viewSizeVisual.width];
  7006. };
  7007. // fov is fixed
  7008. const FOV = degToRad(30);
  7009. const FOV_TAN_HALF = Math.tan(FOV / 2);
  7010. // get gl drawing context
  7011. const gl = getWebGLContext(canvas, {
  7012. antialias: false,
  7013. alpha: false,
  7014. premultipliedAlpha: true,
  7015. });
  7016. // no drawing context received, exit
  7017. if (!gl)
  7018. return;
  7019. // enable derivatives
  7020. gl.getExtension('OES_standard_derivatives');
  7021. // toggle gl settings
  7022. gl.disable(gl.DEPTH_TEST);
  7023. // set blend mode, we need it for alpha blending
  7024. gl.enable(gl.BLEND);
  7025. /*
  7026. https://webglfundamentals.org/webgl/lessons/webgl-and-alpha.html
  7027. most if not all Canvas 2D implementations work with pre-multiplied alpha.
  7028. That means when you transfer them to WebGL and UNPACK_PREMULTIPLY_ALPHA_WEBGL
  7029. is false WebGL will convert them back to un-premultipiled.
  7030. With pre-multiplied alpha on, [1, .5, .5, 0] does not exist, it's always [0, 0, 0, 0]
  7031. */
  7032. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  7033. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  7034. // something to look into:
  7035. // gl.UNPACK_COLORSPACE_CONVERSION_WEBGL
  7036. const transparentTexture = gl.createTexture();
  7037. gl.bindTexture(gl.TEXTURE_2D, transparentTexture);
  7038. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, // width
  7039. 1, // height
  7040. 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(COLOR_TRANSPARENT) // transparent background
  7041. );
  7042. indexTextureMap.set(TEXTURE_TRANSPARENT_INDEX, transparentTexture);
  7043. // create image markup texture and framebuffer
  7044. const imageMarkupTexture = gl.createTexture();
  7045. indexTextureMap.set(TEXTURE_PREVIEW_MARKUP_INDEX, imageMarkupTexture);
  7046. const markupFramebuffer = gl.createFramebuffer();
  7047. // create image blend texture and framebuffer
  7048. const imageBlendTexture = gl.createTexture();
  7049. indexTextureMap.set(TEXTURE_PREVIEW_BLEND_INDEX, imageBlendTexture);
  7050. const blendFramebuffer = gl.createFramebuffer();
  7051. // color mask not set (this needs to run otherwise Firefox 93+ renders incorrectly)
  7052. gl.colorMask(true, true, true, true);
  7053. gl.clearColor(0, 0, 0, 0);
  7054. gl.clear(gl.COLOR_BUFFER_BIT);
  7055. // #region image
  7056. // create default pixel drawing program, supports what we need
  7057. const imageShader = createShader(gl, imageVertexShader, imageFragmentShader, ['aPosition', 'aTexCoord'], [
  7058. 'uMatrix',
  7059. 'uTexture',
  7060. 'uTextureBlend',
  7061. 'uTextureMarkup',
  7062. 'uTextureSize',
  7063. 'uColorGamma',
  7064. 'uColorVignette',
  7065. 'uColorOffset',
  7066. 'uColorMatrix',
  7067. 'uClarityKernel',
  7068. 'uClarityKernelWeight',
  7069. 'uOpacity',
  7070. 'uMaskOpacity',
  7071. 'uMaskBounds',
  7072. 'uMaskCornerRadius',
  7073. 'uMaskFeather',
  7074. 'uFillColor',
  7075. 'uOverlayColor',
  7076. ]);
  7077. // create image buffers
  7078. const imagePositionsBuffer = gl.createBuffer();
  7079. const texturePositionsBuffer = gl.createBuffer();
  7080. gl.bindBuffer(gl.ARRAY_BUFFER, texturePositionsBuffer);
  7081. gl.bufferData(gl.ARRAY_BUFFER, RECT_UV, gl.STATIC_DRAW);
  7082. const drawImage = (texture, textureSize, originX, originY, translateX, translateY, rotateX, rotateY, rotateZ, scale, colorMatrix = COLOR_MATRIX_IDENTITY$1, opacity = 1, clarity, gamma = 1, vignette = 0, maskFeather = IMAGE_MASK_FEATHER, maskCornerRadius = NO_CORNERS, imageBackgroundColor = COLOR_TRANSPARENT, imageOverlayColor = COLOR_TRANSPARENT, enableMarkup = false, enableBlend = false) => {
  7083. // update image texture
  7084. const imageWidth = textureSize.width * viewPixelDensity;
  7085. const imageHeight = textureSize.height * viewPixelDensity;
  7086. const l = imageWidth * -0.5;
  7087. const t = imageHeight * 0.5;
  7088. const r = imageWidth * 0.5;
  7089. const b = imageHeight * -0.5;
  7090. // prettier-ignore
  7091. // B D
  7092. // | \ |
  7093. // A C
  7094. const imagePositions = new Float32Array([
  7095. l, b, 0,
  7096. l, t, 0,
  7097. r, b, 0,
  7098. r, t, 0,
  7099. ]);
  7100. gl.bindBuffer(gl.ARRAY_BUFFER, imagePositionsBuffer);
  7101. gl.bufferData(gl.ARRAY_BUFFER, imagePositions, gl.STATIC_DRAW);
  7102. // move image backwards so it's presented in actual pixel size
  7103. const viewZ = // 1. we calculate the z offset required to have the
  7104. // image height match the view height
  7105. /* /|
  7106. / |
  7107. / | height / 2
  7108. / |
  7109. f / 2 /__z_|
  7110. \ |
  7111. \ |
  7112. \ |
  7113. \ |
  7114. \|
  7115. */
  7116. (textureSize.height / 2 / FOV_TAN_HALF) *
  7117. // 2. we want to render the image at the actual height, viewsize / height gets us results in a 1:1 presentation
  7118. (viewSize.height / textureSize.height) *
  7119. // 3. z has to be negative, therefor multiply by -1
  7120. -1;
  7121. // convert to pixel density
  7122. translateX *= viewPixelDensity;
  7123. translateY *= viewPixelDensity;
  7124. originX *= viewPixelDensity;
  7125. originY *= viewPixelDensity;
  7126. // get shader params
  7127. const { program, locations } = imageShader;
  7128. // apply
  7129. const matrix = mat4Create();
  7130. mat4Perspective(matrix, FOV, viewAspectRatio, 1, -viewZ * 2);
  7131. // move image
  7132. mat4Translate(matrix, translateX, -translateY, viewZ);
  7133. // set rotation origin in view
  7134. mat4Translate(matrix, originX, -originY, 0);
  7135. // rotate image
  7136. mat4RotateZ(matrix, -rotateZ);
  7137. // resize
  7138. mat4Scale(matrix, scale);
  7139. // reset rotation origin
  7140. mat4Translate(matrix, -originX, originY, 0);
  7141. // flip
  7142. mat4RotateY(matrix, rotateY);
  7143. mat4RotateX(matrix, rotateX);
  7144. //
  7145. // tell context to draw preview
  7146. //
  7147. gl.useProgram(program);
  7148. gl.enableVertexAttribArray(locations.aPosition);
  7149. gl.enableVertexAttribArray(locations.aTexCoord);
  7150. // set up texture
  7151. gl.uniform1i(locations.uTexture, TEXTURE_PREVIEW_INDEX);
  7152. gl.uniform2f(locations.uTextureSize, textureSize.width, textureSize.height);
  7153. gl.activeTexture(gl.TEXTURE0 + TEXTURE_PREVIEW_INDEX);
  7154. gl.bindTexture(gl.TEXTURE_2D, texture);
  7155. // set up blend texture
  7156. const blendTextureIndex = enableBlend
  7157. ? TEXTURE_PREVIEW_BLEND_INDEX
  7158. : TEXTURE_TRANSPARENT_INDEX;
  7159. const blendTexture = indexTextureMap.get(blendTextureIndex);
  7160. gl.uniform1i(locations.uTextureBlend, blendTextureIndex);
  7161. gl.activeTexture(gl.TEXTURE0 + blendTextureIndex);
  7162. gl.bindTexture(gl.TEXTURE_2D, blendTexture);
  7163. // set up markup texture
  7164. const markupTextureIndex = enableMarkup
  7165. ? TEXTURE_PREVIEW_MARKUP_INDEX
  7166. : TEXTURE_TRANSPARENT_INDEX;
  7167. const markupTexture = indexTextureMap.get(markupTextureIndex);
  7168. gl.uniform1i(locations.uTextureMarkup, markupTextureIndex);
  7169. gl.activeTexture(gl.TEXTURE0 + markupTextureIndex);
  7170. gl.bindTexture(gl.TEXTURE_2D, markupTexture);
  7171. // set up buffers
  7172. gl.bindBuffer(gl.ARRAY_BUFFER, imagePositionsBuffer);
  7173. gl.vertexAttribPointer(locations.aPosition, 3, gl.FLOAT, false, 0, 0);
  7174. gl.bindBuffer(gl.ARRAY_BUFFER, texturePositionsBuffer);
  7175. gl.vertexAttribPointer(locations.aTexCoord, 2, gl.FLOAT, false, 0, 0);
  7176. // update matrix
  7177. gl.uniformMatrix4fv(locations.uMatrix, false, matrix);
  7178. // overlay color
  7179. gl.uniform4fv(locations.uOverlayColor, imageOverlayColor);
  7180. gl.uniform4fv(locations.uFillColor, imageBackgroundColor);
  7181. // convolution
  7182. let clarityWeight;
  7183. if (!clarity || arrayEqual(clarity, CLARITY_IDENTITY)) {
  7184. clarity = CLARITY_IDENTITY;
  7185. clarityWeight = -1;
  7186. }
  7187. else {
  7188. clarityWeight = clarity.reduce((prev, curr) => prev + curr, 0);
  7189. clarityWeight = clarityWeight <= 0 ? 1 : clarityWeight;
  7190. }
  7191. gl.uniform1fv(locations.uClarityKernel, clarity);
  7192. gl.uniform1f(locations.uClarityKernelWeight, clarityWeight);
  7193. gl.uniform1f(locations.uColorGamma, 1.0 / gamma);
  7194. gl.uniform1f(locations.uColorVignette, vignette);
  7195. // set color matrix values
  7196. gl.uniform4f(locations.uColorOffset, colorMatrix[4], colorMatrix[9], colorMatrix[14], colorMatrix[19]);
  7197. gl.uniformMatrix4fv(locations.uColorMatrix, false, [
  7198. colorMatrix[0],
  7199. colorMatrix[1],
  7200. colorMatrix[2],
  7201. colorMatrix[3],
  7202. colorMatrix[5],
  7203. colorMatrix[6],
  7204. colorMatrix[7],
  7205. colorMatrix[8],
  7206. colorMatrix[10],
  7207. colorMatrix[11],
  7208. colorMatrix[12],
  7209. colorMatrix[13],
  7210. colorMatrix[15],
  7211. colorMatrix[16],
  7212. colorMatrix[17],
  7213. colorMatrix[18],
  7214. ]);
  7215. // opacity level
  7216. gl.uniform1f(locations.uOpacity, opacity);
  7217. // mask
  7218. gl.uniform1f(locations.uMaskOpacity, maskOpacity);
  7219. gl.uniform1fv(locations.uMaskBounds, maskBounds);
  7220. gl.uniform1fv(locations.uMaskCornerRadius, maskCornerRadius.map((v) => v * viewPixelDensity));
  7221. gl.uniform1fv(locations.uMaskFeather, maskFeather.map((v, i) => (i % 2 === 0 ? v : v * viewPixelDensity)));
  7222. gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  7223. gl.disableVertexAttribArray(locations.aPosition);
  7224. gl.disableVertexAttribArray(locations.aTexCoord);
  7225. };
  7226. //#endregion
  7227. // #region path
  7228. const pathShader = createShader(gl, pathVertexShader, pathFragmentShader, ['aPosition', 'aNormal', 'aMiter'], ['uColor', 'uCanvasColor', 'uMatrix', 'uWidth', 'uMaskBounds', 'uMaskOpacity']);
  7229. const pathBuffer = gl.createBuffer();
  7230. const strokePath = (points, width, color, close = false) => {
  7231. const { program, locations } = pathShader;
  7232. gl.useProgram(program);
  7233. gl.enableVertexAttribArray(locations.aPosition);
  7234. gl.enableVertexAttribArray(locations.aNormal);
  7235. gl.enableVertexAttribArray(locations.aMiter);
  7236. const vertices = createPathVertices(points, close);
  7237. const stride = Float32Array.BYTES_PER_ELEMENT * 5;
  7238. const normalOffset = Float32Array.BYTES_PER_ELEMENT * 2; // at position 2
  7239. const miterOffset = Float32Array.BYTES_PER_ELEMENT * 4; // at position 4
  7240. gl.uniform1f(locations.uWidth, width); // add 1 so we can feather the edges
  7241. gl.uniform4fv(locations.uColor, color);
  7242. gl.uniformMatrix4fv(locations.uMatrix, false, markupMatrix);
  7243. gl.uniform4f(locations.uCanvasColor, CANVAS_COLOR_R, CANVAS_COLOR_G, CANVAS_COLOR_B, 1);
  7244. gl.uniform1fv(locations.uMaskBounds, maskBounds);
  7245. gl.uniform1f(locations.uMaskOpacity, maskOpacity);
  7246. gl.bindBuffer(gl.ARRAY_BUFFER, pathBuffer);
  7247. gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  7248. gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, stride, 0);
  7249. gl.vertexAttribPointer(locations.aNormal, 2, gl.FLOAT, false, stride, normalOffset);
  7250. gl.vertexAttribPointer(locations.aMiter, 1, gl.FLOAT, false, stride, miterOffset);
  7251. gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 5);
  7252. gl.disableVertexAttribArray(locations.aPosition);
  7253. gl.disableVertexAttribArray(locations.aNormal);
  7254. gl.disableVertexAttribArray(locations.aMiter);
  7255. };
  7256. //#endregion
  7257. // #region triangle
  7258. const triangleShader = createShader(gl, triangleVertexShader, triangleFragmentShader, ['aPosition'], ['uColor', 'uCanvasColor', 'uMatrix', 'uMaskBounds', 'uMaskOpacity']);
  7259. const triangleBuffer = gl.createBuffer();
  7260. const fillTriangle = (vertices, backgroundColor) => {
  7261. const { program, locations } = triangleShader;
  7262. gl.useProgram(program);
  7263. gl.enableVertexAttribArray(locations.aPosition);
  7264. gl.uniform4fv(locations.uColor, backgroundColor);
  7265. gl.uniformMatrix4fv(locations.uMatrix, false, markupMatrix);
  7266. gl.uniform1fv(locations.uMaskBounds, maskBounds);
  7267. gl.uniform1f(locations.uMaskOpacity, maskOpacity);
  7268. gl.uniform4f(locations.uCanvasColor, CANVAS_COLOR_R, CANVAS_COLOR_G, CANVAS_COLOR_B, 1);
  7269. gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);
  7270. gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  7271. gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, 0, 0);
  7272. gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 2);
  7273. gl.disableVertexAttribArray(locations.aPosition);
  7274. return vertices;
  7275. };
  7276. //#endregion
  7277. // #region rect
  7278. const rectShaderAttributes = ['aPosition', 'aTexCoord', 'aRectCoord'];
  7279. const rectShaderUniforms = [
  7280. 'uTexture',
  7281. 'uColor',
  7282. 'uMatrix',
  7283. 'uCanvasColor',
  7284. 'uTextureColor',
  7285. 'uTextureOpacity',
  7286. 'uPosition',
  7287. 'uSize',
  7288. 'uMaskBounds',
  7289. 'uMaskOpacity',
  7290. 'uMaskFeather',
  7291. 'uCornerRadius',
  7292. 'uInverted',
  7293. ];
  7294. const rectShader = createShader(gl, rectVertexShader, rectFragmentShader, rectShaderAttributes, rectShaderUniforms);
  7295. const rectBuffer = gl.createBuffer();
  7296. const rectTextureBuffer = gl.createBuffer();
  7297. const rectCornerBuffer = gl.createBuffer();
  7298. const fillRect = (vertices, width, height, cornerRadius, backgroundColor, backgroundImage = transparentTexture, opacity = 1.0, colorFilter = COLOR_TRANSPARENT, uv = RECT_UV, maskFeather = RECT_MASK_FEATHER, inverted) => {
  7299. const { program, locations } = rectShader;
  7300. gl.useProgram(program);
  7301. gl.enableVertexAttribArray(locations.aPosition);
  7302. gl.enableVertexAttribArray(locations.aTexCoord);
  7303. gl.enableVertexAttribArray(locations.aRectCoord);
  7304. gl.uniform4fv(locations.uColor, backgroundColor);
  7305. gl.uniform2fv(locations.uSize, [width, height]);
  7306. gl.uniform2fv(locations.uPosition, [vertices[2], vertices[3]]);
  7307. gl.uniform1i(locations.uInverted, inverted ? 1 : 0);
  7308. gl.uniform1fv(locations.uCornerRadius, cornerRadius);
  7309. gl.uniform4f(locations.uCanvasColor, CANVAS_COLOR_R, CANVAS_COLOR_G, CANVAS_COLOR_B, 1);
  7310. // mask
  7311. gl.uniform1fv(locations.uMaskFeather, maskFeather.map((v, i) => (i % 2 === 0 ? v : v * viewPixelDensity)));
  7312. gl.uniform1fv(locations.uMaskBounds, maskBounds);
  7313. gl.uniform1f(locations.uMaskOpacity, maskOpacity);
  7314. gl.uniformMatrix4fv(locations.uMatrix, false, markupMatrix);
  7315. gl.uniform1i(locations.uTexture, TEXTURE_SHAPE_INDEX);
  7316. gl.uniform4fv(locations.uTextureColor, colorFilter);
  7317. gl.uniform1f(locations.uTextureOpacity, opacity);
  7318. gl.activeTexture(gl.TEXTURE0 + TEXTURE_SHAPE_INDEX);
  7319. gl.bindTexture(gl.TEXTURE_2D, backgroundImage);
  7320. gl.bindBuffer(gl.ARRAY_BUFFER, rectTextureBuffer);
  7321. gl.bufferData(gl.ARRAY_BUFFER, uv, gl.STATIC_DRAW);
  7322. gl.vertexAttribPointer(locations.aTexCoord, 2, gl.FLOAT, false, 0, 0);
  7323. // we use these coordinates combined with the size of the rect to interpolate and alias edges
  7324. gl.bindBuffer(gl.ARRAY_BUFFER, rectCornerBuffer);
  7325. gl.bufferData(gl.ARRAY_BUFFER, RECT_UV, gl.STATIC_DRAW);
  7326. gl.vertexAttribPointer(locations.aRectCoord, 2, gl.FLOAT, false, 0, 0);
  7327. gl.bindBuffer(gl.ARRAY_BUFFER, rectBuffer);
  7328. gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  7329. gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, 0, 0);
  7330. gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 2);
  7331. gl.disableVertexAttribArray(locations.aPosition);
  7332. gl.disableVertexAttribArray(locations.aTexCoord);
  7333. gl.disableVertexAttribArray(locations.aRectCoord);
  7334. return vertices;
  7335. };
  7336. //#endregion
  7337. // #region ellipse
  7338. const ellipseShader = createShader(gl, ellipseVertexShader, ellipseFragmentShader, ['aPosition', 'aTexCoord'], [
  7339. 'uTexture',
  7340. 'uTextureOpacity',
  7341. 'uColor',
  7342. 'uCanvasColor',
  7343. 'uMatrix',
  7344. 'uRadius',
  7345. 'uInverted',
  7346. 'uMaskBounds',
  7347. 'uMaskOpacity',
  7348. ]);
  7349. const ellipseBuffer = gl.createBuffer();
  7350. const ellipseTextureBuffer = gl.createBuffer();
  7351. const fillEllipse = (vertices, width, height, backgroundColor, backgroundImage = transparentTexture, uv = RECT_UV, opacity = 1.0, inverted = false) => {
  7352. const { program, locations } = ellipseShader;
  7353. gl.useProgram(program);
  7354. gl.enableVertexAttribArray(locations.aPosition);
  7355. gl.enableVertexAttribArray(locations.aTexCoord);
  7356. gl.uniformMatrix4fv(locations.uMatrix, false, markupMatrix);
  7357. gl.uniform2fv(locations.uRadius, [width * 0.5, height * 0.5]);
  7358. gl.uniform1i(locations.uInverted, inverted ? 1 : 0);
  7359. gl.uniform4fv(locations.uColor, backgroundColor);
  7360. gl.uniform4f(locations.uCanvasColor, CANVAS_COLOR_R, CANVAS_COLOR_G, CANVAS_COLOR_B, 1);
  7361. gl.uniform1fv(locations.uMaskBounds, maskBounds);
  7362. gl.uniform1f(locations.uMaskOpacity, maskOpacity);
  7363. gl.uniform1i(locations.uTexture, TEXTURE_SHAPE_INDEX);
  7364. gl.uniform1f(locations.uTextureOpacity, opacity);
  7365. gl.activeTexture(gl.TEXTURE0 + TEXTURE_SHAPE_INDEX);
  7366. gl.bindTexture(gl.TEXTURE_2D, backgroundImage);
  7367. gl.bindBuffer(gl.ARRAY_BUFFER, ellipseTextureBuffer);
  7368. gl.bufferData(gl.ARRAY_BUFFER, uv, gl.STATIC_DRAW);
  7369. gl.vertexAttribPointer(locations.aTexCoord, 2, gl.FLOAT, false, 0, 0);
  7370. gl.bindBuffer(gl.ARRAY_BUFFER, ellipseBuffer);
  7371. gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  7372. gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, 0, 0);
  7373. gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 2);
  7374. gl.disableVertexAttribArray(locations.aPosition);
  7375. gl.disableVertexAttribArray(locations.aTexCoord);
  7376. };
  7377. //#endregion
  7378. //
  7379. // draw calls
  7380. //
  7381. const drawPath = (points, strokeWidth, strokeColor, strokeClose, opacity) => {
  7382. // is no line
  7383. if (points.length < 2)
  7384. return;
  7385. strokePath(points.map((p) => ({
  7386. x: p.x * viewPixelDensity,
  7387. y: p.y * viewPixelDensity,
  7388. })), strokeWidth * viewPixelDensity, applyOpacity(strokeColor, opacity), strokeClose);
  7389. };
  7390. const drawTriangle = (points, rotation = 0, flipX = false, flipY = false, backgroundColor, opacity) => {
  7391. if (!backgroundColor)
  7392. return;
  7393. const clonedPoints = points.map((p) => ({
  7394. x: p.x * viewPixelDensity,
  7395. y: p.y * viewPixelDensity,
  7396. }));
  7397. const center = convexPolyCentroid(clonedPoints);
  7398. if (flipX || flipY)
  7399. vectorsFlip(clonedPoints, flipX, flipY, center.x, center.y);
  7400. vectorsRotate(clonedPoints, rotation, center.x, center.y);
  7401. const vertices = trianglePointToVertices(clonedPoints);
  7402. fillTriangle(vertices, applyOpacity(backgroundColor, opacity));
  7403. };
  7404. const drawRect = (rect, rotation = 0, flipX = false, flipY = false, cornerRadius, backgroundColor, backgroundImage, backgroundSize = undefined, backgroundPosition = undefined, backgroundUVMap = undefined, strokeWidth, strokeColor, opacity, maskFeather = undefined, colorize, inverted) => {
  7405. // clone first
  7406. const rectOut = rectMultiply(rectClone(rect), viewPixelDensity);
  7407. // has radius, doesn't matter for coordinates
  7408. const cornerRadiusOut = cornerRadius
  7409. .map((r) => limitCornerRadius(r || 0, rect))
  7410. .map((r) => r * viewPixelDensity);
  7411. // should fill
  7412. if (backgroundColor || backgroundImage) {
  7413. // adjust for edge anti-aliasing, if we don't do this the
  7414. // visible rectangle will be 1 pixel smaller than the actual rectangle
  7415. const rectFill = rectClone(rectOut);
  7416. rectFill.x -= 0.5;
  7417. rectFill.y -= 0.5;
  7418. rectFill.width += 1;
  7419. rectFill.height += 1;
  7420. const points = createRectPoints(rectFill, rotation, flipX, flipY);
  7421. const vertices = rectPointsToVertices(points);
  7422. let color;
  7423. if (colorize) {
  7424. color = applyOpacity(colorize);
  7425. // as 0 transparancy is used to test if the colorize filter should be applied we set it to 0.001
  7426. if (color[3] === 0)
  7427. color[3] = 0.001;
  7428. }
  7429. fillRect(vertices, rectFill.width, rectFill.height, cornerRadiusOut, applyOpacity(backgroundColor, opacity), backgroundImage, opacity, color, backgroundUVMap
  7430. ? new Float32Array(backgroundUVMap)
  7431. : calculateBackgroundUVMap(rectFill.width, rectFill.height, backgroundSize, backgroundPosition, viewPixelDensity), maskFeather, inverted);
  7432. }
  7433. // should draw outline
  7434. if (strokeWidth) {
  7435. // fixes issue where stroke would render weirdly
  7436. strokeWidth = Math.min(strokeWidth, rectOut.width, rectOut.height);
  7437. strokePath(
  7438. // rect out is already multiplied by pixel density
  7439. createRectOutline(rectOut.x, rectOut.y, rectOut.width, rectOut.height, rotation, cornerRadiusOut, flipX, flipY), strokeWidth * viewPixelDensity, applyOpacity(strokeColor, opacity), true);
  7440. }
  7441. };
  7442. const drawEllipse = (center, rx, ry, rotation, flipX, flipY, backgroundColor, backgroundImage, backgroundSize = undefined, backgroundPosition = undefined, backgroundUVMap = undefined, strokeWidth, strokeColor, opacity, inverted) => {
  7443. const rectOut = rectMultiply(rectCreate(center.x - rx, center.y - ry, rx * 2, ry * 2), viewPixelDensity);
  7444. if (backgroundColor || backgroundImage) {
  7445. // adjust for edge anti-aliasing, if we don't do this the
  7446. // visible rectangle will be 1 pixel smaller than the actual rectangle
  7447. const rectFill = rectClone(rectOut);
  7448. rectFill.x -= 0.5;
  7449. rectFill.y -= 0.5;
  7450. rectFill.width += 1.0;
  7451. rectFill.height += 1.0;
  7452. const points = createRectPoints(rectFill, rotation, flipX, flipY);
  7453. const vertices = rectPointsToVertices(points);
  7454. fillEllipse(vertices, rectFill.width, rectFill.height, applyOpacity(backgroundColor, opacity), backgroundImage, backgroundUVMap
  7455. ? new Float32Array(backgroundUVMap)
  7456. : calculateBackgroundUVMap(rectFill.width, rectFill.height, backgroundSize, backgroundPosition, viewPixelDensity), opacity, inverted);
  7457. }
  7458. if (strokeWidth)
  7459. strokePath(
  7460. // rect out is already multiplied by pixeldensity
  7461. createEllipseOutline(rectOut.x, rectOut.y, rectOut.width, rectOut.height, rotation, flipX, flipY), strokeWidth * viewPixelDensity, applyOpacity(strokeColor, opacity), true);
  7462. };
  7463. //#endregion
  7464. const glTextures = new Map();
  7465. // let currentMarkupFrameBufferSize = { width: 0, height: 0 };
  7466. const imageFramebufferSize = {};
  7467. imageFramebufferSize[TEXTURE_PREVIEW_MARKUP_INDEX] = { width: 0, height: 0 };
  7468. imageFramebufferSize[TEXTURE_PREVIEW_BLEND_INDEX] = { width: 0, height: 0 };
  7469. const drawToImageFramebuffer = (index, buffer, imageSize) => {
  7470. const textureScalar = Math.min(textureSizeLimit / imageSize.width, textureSizeLimit / imageSize.height, 1);
  7471. const textureWidth = Math.floor(textureScalar * imageSize.width);
  7472. const textureHeight = Math.floor(textureScalar * imageSize.height);
  7473. if (!sizeEqual(imageSize, imageFramebufferSize[index])) {
  7474. // update preview markup texture
  7475. gl.bindTexture(gl.TEXTURE_2D, indexTextureMap.get(index));
  7476. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureWidth, textureHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  7477. // set the filtering, we don't need mips
  7478. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  7479. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  7480. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  7481. gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
  7482. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, indexTextureMap.get(index), 0);
  7483. // remember so we know when to update the framebuffer
  7484. imageFramebufferSize[index] = imageSize;
  7485. }
  7486. else {
  7487. gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
  7488. }
  7489. // switch transformMatrix
  7490. const w = imageSize.width * viewPixelDensity;
  7491. const h = imageSize.height * viewPixelDensity;
  7492. mat4Ortho(markupMatrixFrameBuffer, 0, w, h, 0, -1, 1);
  7493. mat4Translate(markupMatrixFrameBuffer, 0, h, 0);
  7494. mat4ScaleX(markupMatrixFrameBuffer, 1);
  7495. mat4ScaleY(markupMatrixFrameBuffer, -1);
  7496. markupMatrix = markupMatrixFrameBuffer;
  7497. // framebuffer lives in image space
  7498. gl.viewport(0, 0, textureWidth, textureHeight);
  7499. // always transparent
  7500. gl.colorMask(true, true, true, true);
  7501. gl.clearColor(0, 0, 0, 0);
  7502. gl.clear(gl.COLOR_BUFFER_BIT);
  7503. // update rect mask
  7504. RECT_MASK_FEATHER = [
  7505. 1,
  7506. 0,
  7507. 1,
  7508. 0,
  7509. 1,
  7510. Math.max(viewSize.width, imageSize.width),
  7511. 1,
  7512. Math.max(viewSize.width, imageSize.width),
  7513. ];
  7514. };
  7515. return {
  7516. // draw api
  7517. drawPath,
  7518. drawTriangle,
  7519. drawRect,
  7520. drawEllipse,
  7521. drawImage,
  7522. // texture filters
  7523. textureFilterNearest: gl.NEAREST,
  7524. textureFilterLinear: gl.LINEAR,
  7525. //#region texture management
  7526. textureCreate: () => {
  7527. return gl.createTexture();
  7528. },
  7529. textureUpdate: (texture, source, options) => {
  7530. glTextures.set(texture, source);
  7531. return updateTexture(gl, texture, source, options);
  7532. },
  7533. textureSize: (texture) => {
  7534. return sizeCreateFromAny(glTextures.get(texture));
  7535. },
  7536. textureDelete: (texture) => {
  7537. const source = glTextures.get(texture);
  7538. if (source instanceof HTMLCanvasElement && !source.dataset.retain)
  7539. releaseCanvas(source);
  7540. glTextures.delete(texture);
  7541. gl.deleteTexture(texture);
  7542. },
  7543. //#endregion
  7544. setCanvasColor(color) {
  7545. CANVAS_COLOR_R = color[0];
  7546. CANVAS_COLOR_G = color[1];
  7547. CANVAS_COLOR_B = color[2];
  7548. },
  7549. drawToCanvas() {
  7550. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  7551. // switch transformMatrix
  7552. markupMatrix = markupMatrixCanvas;
  7553. // tell webgl about the viewport
  7554. gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  7555. // black (or other color depending on background)
  7556. gl.colorMask(true, true, true, false);
  7557. gl.clearColor(CANVAS_COLOR_R, CANVAS_COLOR_G, CANVAS_COLOR_B, 1);
  7558. // gl.clearColor(0.25, 0.25, 0.25, 1); // for debugging
  7559. gl.clear(gl.COLOR_BUFFER_BIT);
  7560. // update rect mask
  7561. RECT_MASK_FEATHER = [1, 0, 1, 0, 1, viewSize.width, 1, viewSize.width];
  7562. },
  7563. drawToImageBlendBuffer(imageSize) {
  7564. drawToImageFramebuffer(TEXTURE_PREVIEW_BLEND_INDEX, blendFramebuffer, imageSize);
  7565. },
  7566. drawToImageOverlayBuffer(imageSize) {
  7567. drawToImageFramebuffer(TEXTURE_PREVIEW_MARKUP_INDEX, markupFramebuffer, imageSize);
  7568. },
  7569. // set mask
  7570. enableMask(rect, opacity) {
  7571. const maskX = rect.x * viewPixelDensity;
  7572. const maskY = rect.y * viewPixelDensity;
  7573. const maskWidth = rect.width * viewPixelDensity;
  7574. const maskHeight = rect.height * viewPixelDensity;
  7575. maskLeft = maskX;
  7576. maskRight = maskLeft + maskWidth;
  7577. maskTop = viewSize.height - maskY;
  7578. maskBottom = viewSize.height - (maskY + maskHeight);
  7579. maskOpacity = 1.0 - opacity;
  7580. maskBounds = [maskTop, maskRight, maskBottom, maskLeft];
  7581. },
  7582. disableMask() {
  7583. maskLeft = 0;
  7584. maskRight = viewSize.width;
  7585. maskTop = viewSize.height;
  7586. maskBottom = 0;
  7587. maskOpacity = 1;
  7588. maskBounds = [maskTop, maskRight, maskBottom, maskLeft];
  7589. },
  7590. // canvas
  7591. resize,
  7592. release() {
  7593. canvas.width = 1;
  7594. canvas.height = 1;
  7595. },
  7596. };
  7597. };
  7598. var isImageBitmap = (obj) => 'close' in obj;
  7599. /* src/core/ui/components/Canvas.svelte generated by Svelte v3.37.0 */
  7600. function create_fragment$M(ctx) {
  7601. let div;
  7602. let canvas_1;
  7603. let mounted;
  7604. let dispose;
  7605. return {
  7606. c() {
  7607. div = element("div");
  7608. canvas_1 = element("canvas");
  7609. attr(div, "class", "PinturaCanvas");
  7610. },
  7611. m(target, anchor) {
  7612. insert(target, div, anchor);
  7613. append(div, canvas_1);
  7614. /*canvas_1_binding*/ ctx[24](canvas_1);
  7615. if (!mounted) {
  7616. dispose = [
  7617. listen(canvas_1, "measure", /*measure_handler*/ ctx[25]),
  7618. action_destroyer(measurable.call(null, canvas_1))
  7619. ];
  7620. mounted = true;
  7621. }
  7622. },
  7623. p: noop,
  7624. i: noop,
  7625. o: noop,
  7626. d(detaching) {
  7627. if (detaching) detach(div);
  7628. /*canvas_1_binding*/ ctx[24](null);
  7629. mounted = false;
  7630. run_all(dispose);
  7631. }
  7632. };
  7633. }
  7634. function instance$M($$self, $$props, $$invalidate) {
  7635. let canDraw;
  7636. let drawUpdate;
  7637. let $background;
  7638. let $maskOpacityStore;
  7639. let $mask;
  7640. let $imageOverlayColor;
  7641. let $maskFrameOpacityStore;
  7642. const blendWithCanvasBackground = (back, front) => {
  7643. const [bR, bG, bB] = back;
  7644. const [fR, fG, fB, fA] = front;
  7645. return [fR * fA + bR * (1 - fA), fG * fA + bG * (1 - fA), fB * fA + bB * (1 - fA), 1];
  7646. };
  7647. // used to dispatch the 'measure' event
  7648. const dispatch = createEventDispatcher();
  7649. let { animate } = $$props;
  7650. let { maskRect } = $$props;
  7651. let { maskOpacity = 1 } = $$props;
  7652. let { maskFrameOpacity = 0.95 } = $$props;
  7653. let { pixelRatio = 1 } = $$props;
  7654. let { backgroundColor } = $$props;
  7655. let { willRender = passthrough } = $$props;
  7656. let { loadImageData = passthrough } = $$props;
  7657. let { images = [] } = $$props;
  7658. let { interfaceImages = [] } = $$props;
  7659. // internal props
  7660. let canvas;
  7661. let canvasGL = null;
  7662. let width = null;
  7663. let height = null;
  7664. //
  7665. // springyness for main preview
  7666. //
  7667. const updateSpring = (spring, value) => spring.set(value, { hard: !animate });
  7668. const SPRING_PROPS = { precision: 0.0001 };
  7669. const SPRING_PROPS_FRACTION = { precision: SPRING_PROPS.precision * 0.01 };
  7670. // Editor UI
  7671. const background = tweened(undefined, { duration: 250 });
  7672. component_subscribe($$self, background, value => $$invalidate(20, $background = value));
  7673. const maskOpacityStore = spring(1, SPRING_PROPS_FRACTION);
  7674. component_subscribe($$self, maskOpacityStore, value => $$invalidate(21, $maskOpacityStore = value));
  7675. const maskFrameOpacityStore = spring(1, SPRING_PROPS_FRACTION);
  7676. component_subscribe($$self, maskFrameOpacityStore, value => $$invalidate(30, $maskFrameOpacityStore = value));
  7677. const mask = writable();
  7678. component_subscribe($$self, mask, value => $$invalidate(28, $mask = value));
  7679. const imageOverlayColor = writable();
  7680. component_subscribe($$self, imageOverlayColor, value => $$invalidate(29, $imageOverlayColor = value));
  7681. //#region texture loading and binding
  7682. const TEXT_TEXTURE_MEASURE_CONTEXT = createSimpleContext();
  7683. const Textures = new Map([]);
  7684. const getImageTexture = (image, imageRendering) => {
  7685. // no texture yet for this source
  7686. if (!Textures.has(image)) {
  7687. // is in loading state when is same as source
  7688. Textures.set(image, image);
  7689. // get texture filter mode
  7690. const filter = imageRendering === "pixelated"
  7691. ? canvasGL.textureFilterNearest
  7692. : canvasGL.textureFilterLinear;
  7693. // already loaded
  7694. if (!isString(image) && (isImageBitmap(image) || isImageData(image) || isCanvas(image))) {
  7695. // create texture
  7696. const texture = canvasGL.textureCreate();
  7697. // udpate texture in gl canvas
  7698. canvasGL.textureUpdate(texture, image, { filter });
  7699. // update state we now have a texture
  7700. Textures.set(image, texture);
  7701. } else // need to load the image
  7702. {
  7703. loadImageData(image).then(data => {
  7704. // create texture
  7705. const texture = canvasGL.textureCreate();
  7706. // udpate texture in gl canvas
  7707. canvasGL.textureUpdate(texture, data, { filter });
  7708. // update state we now have a texture
  7709. Textures.set(image, texture);
  7710. // need to redraw because texture is now available
  7711. requestAnimationFrame(drawUpdate);
  7712. }).catch(err => {
  7713. console.error(err);
  7714. });
  7715. }
  7716. }
  7717. return Textures.get(image);
  7718. };
  7719. const getTextTexture = shape => {
  7720. let { text, textAlign, fontFamily, fontSize, fontWeight, fontVariant, fontStyle, lineHeight, width } = shape;
  7721. // we need this context to correctly wrap text
  7722. updateTextContext(TEXT_TEXTURE_MEASURE_CONTEXT, {
  7723. fontSize,
  7724. fontFamily,
  7725. fontWeight,
  7726. fontVariant,
  7727. fontStyle,
  7728. textAlign
  7729. });
  7730. // wrap the text
  7731. const textString = width
  7732. ? wrapText(TEXT_TEXTURE_MEASURE_CONTEXT, text, width)
  7733. : text;
  7734. // create UID for this texture so we can cache it and fetch it later on
  7735. const textUID = shapeTextUID({ ...shape, text: textString });
  7736. // get texture unit assigned to this specific text shape
  7737. if (!Textures.has(textUID)) {
  7738. // TODO: Create power of 2 texture and update texture instead of delete -> replace
  7739. // we need to create a new texture
  7740. const ctx = createSimpleContext();
  7741. updateTextContext(ctx, {
  7742. fontSize,
  7743. fontFamily,
  7744. fontWeight,
  7745. fontVariant,
  7746. fontStyle,
  7747. textAlign
  7748. });
  7749. // calculate canvas height
  7750. resizeContextToFitText(ctx, textString, {
  7751. fontSize,
  7752. fontFamily,
  7753. fontWeight,
  7754. fontVariant,
  7755. fontStyle,
  7756. textAlign,
  7757. lineHeight
  7758. });
  7759. const contextMinWidth = ctx.canvas.width;
  7760. // scale context to account for italic styles
  7761. ctx.canvas.width += textPadding;
  7762. // context resized, we now need to re-apply style
  7763. updateTextContext(ctx, {
  7764. fontSize,
  7765. fontFamily,
  7766. fontWeight,
  7767. fontVariant,
  7768. fontStyle,
  7769. textAlign,
  7770. color: [1, 0, 1], // color we'll replace in the shader
  7771. });
  7772. // if so, draw text and update texture
  7773. drawText$1(ctx, textString, {
  7774. fontSize,
  7775. textAlign,
  7776. lineHeight,
  7777. lineWidth: contextMinWidth
  7778. });
  7779. Textures.set(textUID, canvasGL.textureUpdate(canvasGL.textureCreate(), ctx.canvas, { filter: canvasGL.textureFilterLinear }));
  7780. }
  7781. return Textures.get(textUID);
  7782. };
  7783. const getShapeTexture = shape => {
  7784. let texture;
  7785. // let's create textures for backgrounds and texts
  7786. if (shape.backgroundImage) {
  7787. texture = getImageTexture(shape.backgroundImage, shape.backgroundImageRendering);
  7788. } else if (isString(shape.text)) {
  7789. if (shape.width && shape.width < 1 || shape.height && shape.height < 1) return undefined;
  7790. texture = getTextTexture(shape);
  7791. }
  7792. return texture;
  7793. };
  7794. const isTexture = texture => texture instanceof WebGLTexture;
  7795. const releaseUnusedTextures = usedTextures => {
  7796. Textures.forEach((registeredTexture, key) => {
  7797. const isUsed = !!usedTextures.find(usedTexture => usedTexture === registeredTexture);
  7798. // stil used, no need to release
  7799. if (isUsed) return;
  7800. // remove this texture
  7801. Textures.delete(key);
  7802. canvasGL.textureDelete(registeredTexture);
  7803. });
  7804. };
  7805. //#endregion
  7806. //#region drawing
  7807. const drawImageHelper = ({ data, size, origin, translation, rotation, scale, colorMatrix, opacity, convolutionMatrix, gamma, vignette, maskFeather, maskCornerRadius, backgroundColor, overlayColor, enableShapes, enableBlend }) => {
  7808. // calculate opaque backgroundColor if backgroundColor is transparent and visible
  7809. if (backgroundColor && backgroundColor[3] < 1 && backgroundColor[3] > 0) {
  7810. backgroundColor = blendWithCanvasBackground($background, backgroundColor);
  7811. }
  7812. // gets texture to use for this image
  7813. const texture = getImageTexture(data);
  7814. // draw the image
  7815. canvasGL.drawImage(texture, size, origin.x, origin.y, translation.x, translation.y, rotation.x, rotation.y, rotation.z, scale, colorMatrix, clamp(opacity, 0, 1), convolutionMatrix, gamma, vignette, maskFeather, maskCornerRadius, backgroundColor, overlayColor, enableShapes, enableBlend);
  7816. return texture;
  7817. };
  7818. const backgroundCornersToUVMap = ([tl, tr, br, bl]) => {
  7819. // tl, tr, br, bl -> bl, tl, br, tr
  7820. // prettier-ignore
  7821. // B D
  7822. // | \ |
  7823. // A C
  7824. return [bl.x, bl.y, tl.x, tl.y, br.x, br.y, tr.x, tr.y];
  7825. };
  7826. const drawShapes = (shapes = []) => {
  7827. return shapes.map(shape => {
  7828. // only show texture if shape is finished loading
  7829. let shapeTexture = !shape._isLoading && getShapeTexture(shape);
  7830. // get the webgl texture
  7831. let texture = isTexture(shapeTexture) ? shapeTexture : undefined;
  7832. if (isArray(shape.points)) {
  7833. // is triangle
  7834. if (shape.points.length === 3 && shape.backgroundColor) {
  7835. canvasGL.drawTriangle(shape.points, shape.rotation, shape.flipX, shape.flipY, shape.backgroundColor, shape.strokeWidth, shape.strokeColor, shape.opacity);
  7836. } else // is normal path
  7837. {
  7838. canvasGL.drawPath(shape.points, shape.strokeWidth, shape.strokeColor, shape.pathClose, shape.opacity);
  7839. }
  7840. } else // is ellipse
  7841. if (isNumber(shape.rx) && isNumber(shape.ry)) {
  7842. let backgroundSize;
  7843. let backgroundPosition;
  7844. canvasGL.drawEllipse(shape, shape.rx, shape.ry, shape.rotation, shape.flipX, shape.flipY, shape.backgroundColor, texture, backgroundSize, backgroundPosition, shape.backgroundCorners && backgroundCornersToUVMap(shape.backgroundCorners), shape.strokeWidth, shape.strokeColor, shape.opacity, shape.inverted);
  7845. } else // is rect
  7846. if (isString(shape.text) && texture || shape.width) {
  7847. const textureSize = texture && canvasGL.textureSize(texture);
  7848. let colorize = undefined;
  7849. let shapeRect;
  7850. let shapeCornerRadius = [
  7851. shape.cornerRadius,
  7852. shape.cornerRadius,
  7853. shape.cornerRadius,
  7854. shape.cornerRadius
  7855. ];
  7856. if (shape.width) {
  7857. shapeRect = shape;
  7858. } else {
  7859. shapeRect = { x: shape.x, y: shape.y, ...textureSize };
  7860. }
  7861. let backgroundSize;
  7862. let backgroundPosition;
  7863. if (textureSize) {
  7864. // background should be scaled
  7865. if (shape.backgroundImage && shape.backgroundSize) {
  7866. // always respect texture aspect ratio
  7867. const textureAspectRatio = getAspectRatio(textureSize.width, textureSize.height);
  7868. // adjust position of background
  7869. if (shape.backgroundSize === "contain") {
  7870. const rect = rectContainRect(shape, textureAspectRatio, shapeRect);
  7871. backgroundSize = sizeCreateFromRect(rect);
  7872. backgroundPosition = vectorCreate((shape.width - backgroundSize.width) * 0.5, (shape.height - backgroundSize.height) * 0.5);
  7873. } else if (shape.backgroundSize === "cover") {
  7874. const rect = rectCoverRect(shape, textureAspectRatio, shapeRect);
  7875. backgroundSize = sizeCreateFromRect(rect);
  7876. backgroundPosition = vectorCreate(rect.x, rect.y);
  7877. backgroundPosition = vectorCreate((shape.width - backgroundSize.width) * 0.5, (shape.height - backgroundSize.height) * 0.5);
  7878. } else {
  7879. backgroundSize = shape.backgroundSize;
  7880. backgroundPosition = shape.backgroundPosition;
  7881. }
  7882. } else // is text, "background" should be texture size and be positioned based on alignment
  7883. if (shape.text && shape.width) {
  7884. // position texture based on text alignment
  7885. backgroundSize = textureSize;
  7886. backgroundPosition = vectorCreate(0, 0);
  7887. // auto height
  7888. if (!shape.height) shape.height = textureSize.height;
  7889. // textPadding so text doesn't clip on left and right edges
  7890. shape.x -= textPadding;
  7891. shape.width += textPadding * 2;
  7892. if (shape.textAlign === "left") {
  7893. backgroundPosition.x = textPadding;
  7894. }
  7895. if (shape.textAlign === "center") {
  7896. backgroundPosition.x = textPadding * 0.5 + (shape.width - textureSize.width) * 0.5;
  7897. }
  7898. if (shape.textAlign === "right") {
  7899. backgroundPosition.x = shape.width - textureSize.width;
  7900. }
  7901. } else if (shape.text) {
  7902. backgroundPosition = vectorCreate(0, 0);
  7903. backgroundSize = {
  7904. width: shapeRect.width,
  7905. height: shapeRect.height
  7906. };
  7907. // texture is slightly larger because of text padding, need to compensate for this in single line mode
  7908. shapeRect.width -= textPadding;
  7909. }
  7910. if (shape.text) colorize = shape.color;
  7911. }
  7912. canvasGL.drawRect(shapeRect, shape.rotation, shape.flipX, shape.flipY, shapeCornerRadius, shape.backgroundColor, texture, backgroundSize, backgroundPosition, shape.backgroundCorners && backgroundCornersToUVMap(shape.backgroundCorners), shape.strokeWidth, shape.strokeColor, shape.opacity, undefined, colorize, shape.inverted);
  7913. }
  7914. return shapeTexture;
  7915. }).filter(Boolean);
  7916. };
  7917. // redraws state
  7918. const usedTextures = [];
  7919. const redraw = () => {
  7920. // reset array of textures used in this draw call
  7921. usedTextures.length = 0;
  7922. // get top image shortcut
  7923. const imagesTop = images[0];
  7924. // allow dev to inject more shapes
  7925. const { blendShapes, annotationShapes, interfaceShapes, decorationShapes, frameShapes } = willRender({
  7926. // top image state shortcut
  7927. opacity: imagesTop.opacity,
  7928. rotation: imagesTop.rotation,
  7929. scale: imagesTop.scale,
  7930. // active images
  7931. images,
  7932. // canvas size
  7933. size: sizeCreate(width, height),
  7934. // canvas background
  7935. backgroundColor: [...$background]
  7936. });
  7937. const canvasBackgroundColor = [...$background];
  7938. const imagesMask = $mask;
  7939. const imagesMaskOpacity = clamp($maskOpacityStore, 0, 1);
  7940. const imagesOverlayColor = $imageOverlayColor;
  7941. const imagesSize = imagesTop.size;
  7942. const imagesBackgroundColor = imagesTop.backgroundColor;
  7943. // no need to draw to blend framebuffer if no redactions
  7944. const hasBlendShapes = blendShapes.length > 0;
  7945. // no need to draw to markup framebuffer if no annotations
  7946. const hasAnnotations = annotationShapes.length > 0;
  7947. // if image has background color
  7948. const hasImageBackgroundColor = imagesBackgroundColor[3] > 0;
  7949. // if the overlay is transparent so we can see the canvas
  7950. const hasTransparentOverlay = imagesMaskOpacity < 1;
  7951. // set canvas background color to image background color if is defined
  7952. if (hasTransparentOverlay && hasImageBackgroundColor) {
  7953. const backR = canvasBackgroundColor[0];
  7954. const backG = canvasBackgroundColor[1];
  7955. const backB = canvasBackgroundColor[2];
  7956. const frontA = 1 - imagesMaskOpacity;
  7957. const frontR = imagesBackgroundColor[0] * frontA;
  7958. const frontG = imagesBackgroundColor[1] * frontA;
  7959. const frontB = imagesBackgroundColor[2] * frontA;
  7960. const fA = 1 - frontA;
  7961. canvasBackgroundColor[0] = frontR + backR * fA;
  7962. canvasBackgroundColor[1] = frontG + backG * fA;
  7963. canvasBackgroundColor[2] = frontB + backB * fA;
  7964. canvasBackgroundColor[3] = 1;
  7965. }
  7966. canvasGL.setCanvasColor(canvasBackgroundColor);
  7967. // if has blend shapes draw blend shapes to framebuffer
  7968. // TODO: only run this if blend shapes have changed
  7969. if (hasBlendShapes) {
  7970. canvasGL.disableMask();
  7971. canvasGL.drawToImageBlendBuffer(imagesSize);
  7972. usedTextures.push(...drawShapes(blendShapes));
  7973. }
  7974. // if has annotations draw annotation shapes to framebuffer
  7975. // TODO: only run this if annotations have changed
  7976. if (hasAnnotations) {
  7977. canvasGL.disableMask();
  7978. canvasGL.drawToImageOverlayBuffer(imagesSize);
  7979. usedTextures.push(...drawShapes(annotationShapes));
  7980. }
  7981. // switch to canvas drawing for other elements
  7982. canvasGL.drawToCanvas();
  7983. canvasGL.enableMask(imagesMask, imagesMaskOpacity);
  7984. // draw a colored rectangle behind main preview image
  7985. if (hasImageBackgroundColor) {
  7986. canvasGL.drawRect(imagesMask, 0, false, false, [0, 0, 0, 0], blendWithCanvasBackground($background, imagesBackgroundColor));
  7987. }
  7988. usedTextures.push(...[...images].reverse().map(image => {
  7989. return drawImageHelper({
  7990. ...image,
  7991. // enable drawing markup if defined
  7992. enableShapes: hasAnnotations,
  7993. // enable drawing redactions if defined
  7994. enableBlend: hasBlendShapes,
  7995. // mask and overlay positions
  7996. mask: imagesMask,
  7997. maskOpacity: imagesMaskOpacity,
  7998. overlayColor: imagesOverlayColor
  7999. });
  8000. }));
  8001. // TODO: move vignette here (draw with colorized circular gradient texture instead of in shader)
  8002. // draw decorations shapes relative to crop
  8003. canvasGL.enableMask(imagesMask, 1);
  8004. usedTextures.push(...drawShapes(decorationShapes));
  8005. // draw frames
  8006. if (frameShapes.length) {
  8007. const shapesInside = frameShapes.filter(shape => !shape.expandsCanvas);
  8008. const shapesOutside = frameShapes.filter(shape => shape.expandsCanvas);
  8009. if (shapesInside.length) {
  8010. usedTextures.push(...drawShapes(shapesInside));
  8011. }
  8012. if (shapesOutside.length) {
  8013. // the half pixel helps mask the outside shapes at the correct position
  8014. canvasGL.enableMask(
  8015. {
  8016. x: imagesMask.x + 0.5,
  8017. y: imagesMask.y + 0.5,
  8018. width: imagesMask.width - 1,
  8019. height: imagesMask.height - 1
  8020. },
  8021. $maskFrameOpacityStore
  8022. );
  8023. usedTextures.push(...drawShapes(shapesOutside));
  8024. }
  8025. }
  8026. // crop mask not used for interface
  8027. canvasGL.disableMask();
  8028. // frames rendered on the outside
  8029. // draw custom interface shapes
  8030. usedTextures.push(...drawShapes(interfaceShapes));
  8031. interfaceImages.forEach(image => {
  8032. canvasGL.enableMask(image.mask, image.maskOpacity);
  8033. // draw background fill
  8034. if (image.backgroundColor) {
  8035. canvasGL.drawRect(image.mask, 0, false, false, image.maskCornerRadius, image.backgroundColor, undefined, undefined, undefined, undefined, undefined, image.opacity, image.maskFeather);
  8036. }
  8037. // draw image
  8038. drawImageHelper({
  8039. ...image,
  8040. // update translation to apply `offset` from top left
  8041. translation: {
  8042. x: image.translation.x + image.offset.x - width * 0.5,
  8043. y: image.translation.y + image.offset.y - height * 0.5
  8044. }
  8045. });
  8046. });
  8047. canvasGL.disableMask();
  8048. // determine which textures can be dropped
  8049. releaseUnusedTextures(usedTextures);
  8050. };
  8051. //#endregion
  8052. //#region set up
  8053. // throttled redrawer
  8054. let lastDraw = Date.now();
  8055. const redrawThrottled = () => {
  8056. const now = Date.now();
  8057. const dist = now - lastDraw;
  8058. if (dist < 48) return;
  8059. lastDraw = now;
  8060. redraw();
  8061. };
  8062. // returns the render function to use for this browser context
  8063. const selectFittingRenderFunction = () => isSoftwareRendering() ? redrawThrottled : redraw;
  8064. // after DOM has been altered, redraw to canvas
  8065. afterUpdate(() => drawUpdate());
  8066. // hook up canvas to WebGL drawer
  8067. onMount(() => $$invalidate(19, canvasGL = createWebGLCanvas(canvas)));
  8068. // clean up canvas
  8069. onDestroy(() => {
  8070. // if canvas wasn't created we don't need to release it
  8071. if (!canvasGL) return;
  8072. // done drawing
  8073. canvasGL.release();
  8074. // force release canvas for Safari
  8075. releaseCanvas(TEXT_TEXTURE_MEASURE_CONTEXT.canvas);
  8076. });
  8077. function canvas_1_binding($$value) {
  8078. binding_callbacks[$$value ? "unshift" : "push"](() => {
  8079. canvas = $$value;
  8080. $$invalidate(2, canvas);
  8081. });
  8082. }
  8083. const measure_handler = e => {
  8084. $$invalidate(0, width = e.detail.width);
  8085. $$invalidate(1, height = e.detail.height);
  8086. dispatch("measure", { width, height });
  8087. };
  8088. $$self.$$set = $$props => {
  8089. if ("animate" in $$props) $$invalidate(9, animate = $$props.animate);
  8090. if ("maskRect" in $$props) $$invalidate(10, maskRect = $$props.maskRect);
  8091. if ("maskOpacity" in $$props) $$invalidate(11, maskOpacity = $$props.maskOpacity);
  8092. if ("maskFrameOpacity" in $$props) $$invalidate(12, maskFrameOpacity = $$props.maskFrameOpacity);
  8093. if ("pixelRatio" in $$props) $$invalidate(13, pixelRatio = $$props.pixelRatio);
  8094. if ("backgroundColor" in $$props) $$invalidate(14, backgroundColor = $$props.backgroundColor);
  8095. if ("willRender" in $$props) $$invalidate(15, willRender = $$props.willRender);
  8096. if ("loadImageData" in $$props) $$invalidate(16, loadImageData = $$props.loadImageData);
  8097. if ("images" in $$props) $$invalidate(17, images = $$props.images);
  8098. if ("interfaceImages" in $$props) $$invalidate(18, interfaceImages = $$props.interfaceImages);
  8099. };
  8100. $$self.$$.update = () => {
  8101. if ($$self.$$.dirty[0] & /*backgroundColor*/ 16384) {
  8102. backgroundColor && updateSpring(background, backgroundColor);
  8103. }
  8104. if ($$self.$$.dirty[0] & /*maskOpacity*/ 2048) {
  8105. updateSpring(maskOpacityStore, isNumber(maskOpacity) ? maskOpacity : 1);
  8106. }
  8107. if ($$self.$$.dirty[0] & /*maskFrameOpacity*/ 4096) {
  8108. updateSpring(maskFrameOpacityStore, isNumber(maskFrameOpacity) ? maskFrameOpacity : 1);
  8109. }
  8110. if ($$self.$$.dirty[0] & /*maskRect*/ 1024) {
  8111. maskRect && mask.set(maskRect);
  8112. }
  8113. if ($$self.$$.dirty[0] & /*$background, $maskOpacityStore*/ 3145728) {
  8114. $background && imageOverlayColor.set([
  8115. $background[0],
  8116. $background[1],
  8117. $background[2],
  8118. clamp($maskOpacityStore, 0, 1)
  8119. ]);
  8120. }
  8121. if ($$self.$$.dirty[0] & /*canvasGL, width, height, images*/ 655363) {
  8122. // can draw view
  8123. $$invalidate(23, canDraw = !!(canvasGL && width && height && images.length));
  8124. }
  8125. if ($$self.$$.dirty[0] & /*width, height, canvasGL, pixelRatio*/ 532483) {
  8126. // observe width and height changes and resize the canvas proportionally
  8127. width && height && canvasGL && canvasGL.resize(width, height, pixelRatio);
  8128. }
  8129. if ($$self.$$.dirty[0] & /*canDraw*/ 8388608) {
  8130. // switch to draw method when can draw
  8131. $$invalidate(22, drawUpdate = canDraw ? selectFittingRenderFunction() : noop$1);
  8132. }
  8133. if ($$self.$$.dirty[0] & /*canDraw, drawUpdate*/ 12582912) {
  8134. // if can draw state is updated and we have a draw update function, time to redraw
  8135. canDraw && drawUpdate && drawUpdate();
  8136. }
  8137. };
  8138. return [
  8139. width,
  8140. height,
  8141. canvas,
  8142. dispatch,
  8143. background,
  8144. maskOpacityStore,
  8145. maskFrameOpacityStore,
  8146. mask,
  8147. imageOverlayColor,
  8148. animate,
  8149. maskRect,
  8150. maskOpacity,
  8151. maskFrameOpacity,
  8152. pixelRatio,
  8153. backgroundColor,
  8154. willRender,
  8155. loadImageData,
  8156. images,
  8157. interfaceImages,
  8158. canvasGL,
  8159. $background,
  8160. $maskOpacityStore,
  8161. drawUpdate,
  8162. canDraw,
  8163. canvas_1_binding,
  8164. measure_handler
  8165. ];
  8166. }
  8167. class Canvas extends SvelteComponent {
  8168. constructor(options) {
  8169. super();
  8170. init(
  8171. this,
  8172. options,
  8173. instance$M,
  8174. create_fragment$M,
  8175. safe_not_equal,
  8176. {
  8177. animate: 9,
  8178. maskRect: 10,
  8179. maskOpacity: 11,
  8180. maskFrameOpacity: 12,
  8181. pixelRatio: 13,
  8182. backgroundColor: 14,
  8183. willRender: 15,
  8184. loadImageData: 16,
  8185. images: 17,
  8186. interfaceImages: 18
  8187. },
  8188. [-1, -1]
  8189. );
  8190. }
  8191. }
  8192. var arrayJoin = (arr, filter = Boolean, str = ' ') => arr.filter(filter).join(str);
  8193. /* src/core/ui/components/TabList.svelte generated by Svelte v3.37.0 */
  8194. function get_each_context$9(ctx, list, i) {
  8195. const child_ctx = ctx.slice();
  8196. child_ctx[17] = list[i];
  8197. return child_ctx;
  8198. }
  8199. const get_default_slot_changes$1 = dirty => ({ tab: dirty & /*tabNodes*/ 4 });
  8200. const get_default_slot_context$1 = ctx => ({ tab: /*tab*/ ctx[17] });
  8201. // (52:0) {#if shouldRender}
  8202. function create_if_block$e(ctx) {
  8203. let ul;
  8204. let each_blocks = [];
  8205. let each_1_lookup = new Map();
  8206. let ul_class_value;
  8207. let current;
  8208. let each_value = /*tabNodes*/ ctx[2];
  8209. const get_key = ctx => /*tab*/ ctx[17].id;
  8210. for (let i = 0; i < each_value.length; i += 1) {
  8211. let child_ctx = get_each_context$9(ctx, each_value, i);
  8212. let key = get_key(child_ctx);
  8213. each_1_lookup.set(key, each_blocks[i] = create_each_block$9(key, child_ctx));
  8214. }
  8215. return {
  8216. c() {
  8217. ul = element("ul");
  8218. for (let i = 0; i < each_blocks.length; i += 1) {
  8219. each_blocks[i].c();
  8220. }
  8221. attr(ul, "class", ul_class_value = arrayJoin(["PinturaTabList", /*klass*/ ctx[0]]));
  8222. attr(ul, "role", "tablist");
  8223. attr(ul, "data-layout", /*layout*/ ctx[1]);
  8224. },
  8225. m(target, anchor) {
  8226. insert(target, ul, anchor);
  8227. for (let i = 0; i < each_blocks.length; i += 1) {
  8228. each_blocks[i].m(ul, null);
  8229. }
  8230. /*ul_binding*/ ctx[14](ul);
  8231. current = true;
  8232. },
  8233. p(ctx, dirty) {
  8234. if (dirty & /*tabNodes, handleKeyTab, handleClickTab, $$scope*/ 1124) {
  8235. each_value = /*tabNodes*/ ctx[2];
  8236. group_outros();
  8237. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, ul, outro_and_destroy_block, create_each_block$9, null, get_each_context$9);
  8238. check_outros();
  8239. }
  8240. if (!current || dirty & /*klass*/ 1 && ul_class_value !== (ul_class_value = arrayJoin(["PinturaTabList", /*klass*/ ctx[0]]))) {
  8241. attr(ul, "class", ul_class_value);
  8242. }
  8243. if (!current || dirty & /*layout*/ 2) {
  8244. attr(ul, "data-layout", /*layout*/ ctx[1]);
  8245. }
  8246. },
  8247. i(local) {
  8248. if (current) return;
  8249. for (let i = 0; i < each_value.length; i += 1) {
  8250. transition_in(each_blocks[i]);
  8251. }
  8252. current = true;
  8253. },
  8254. o(local) {
  8255. for (let i = 0; i < each_blocks.length; i += 1) {
  8256. transition_out(each_blocks[i]);
  8257. }
  8258. current = false;
  8259. },
  8260. d(detaching) {
  8261. if (detaching) detach(ul);
  8262. for (let i = 0; i < each_blocks.length; i += 1) {
  8263. each_blocks[i].d();
  8264. }
  8265. /*ul_binding*/ ctx[14](null);
  8266. }
  8267. };
  8268. }
  8269. // (59:8) {#each tabNodes as tab (tab.id)}
  8270. function create_each_block$9(key_1, ctx) {
  8271. let li;
  8272. let button;
  8273. let button_disabled_value;
  8274. let t;
  8275. let li_aria_controls_value;
  8276. let li_id_value;
  8277. let li_aria_selected_value;
  8278. let current;
  8279. let mounted;
  8280. let dispose;
  8281. const default_slot_template = /*#slots*/ ctx[11].default;
  8282. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[10], get_default_slot_context$1);
  8283. function keydown_handler(...args) {
  8284. return /*keydown_handler*/ ctx[12](/*tab*/ ctx[17], ...args);
  8285. }
  8286. function click_handler(...args) {
  8287. return /*click_handler*/ ctx[13](/*tab*/ ctx[17], ...args);
  8288. }
  8289. return {
  8290. key: key_1,
  8291. first: null,
  8292. c() {
  8293. li = element("li");
  8294. button = element("button");
  8295. if (default_slot) default_slot.c();
  8296. t = space();
  8297. button.disabled = button_disabled_value = /*tab*/ ctx[17].disabled;
  8298. attr(li, "role", "tab");
  8299. attr(li, "aria-controls", li_aria_controls_value = /*tab*/ ctx[17].href.substr(1));
  8300. attr(li, "id", li_id_value = /*tab*/ ctx[17].tabId);
  8301. attr(li, "aria-selected", li_aria_selected_value = /*tab*/ ctx[17].selected);
  8302. this.first = li;
  8303. },
  8304. m(target, anchor) {
  8305. insert(target, li, anchor);
  8306. append(li, button);
  8307. if (default_slot) {
  8308. default_slot.m(button, null);
  8309. }
  8310. append(li, t);
  8311. current = true;
  8312. if (!mounted) {
  8313. dispose = [
  8314. listen(button, "keydown", keydown_handler),
  8315. listen(button, "click", click_handler)
  8316. ];
  8317. mounted = true;
  8318. }
  8319. },
  8320. p(new_ctx, dirty) {
  8321. ctx = new_ctx;
  8322. if (default_slot) {
  8323. if (default_slot.p && dirty & /*$$scope, tabNodes*/ 1028) {
  8324. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[10], dirty, get_default_slot_changes$1, get_default_slot_context$1);
  8325. }
  8326. }
  8327. if (!current || dirty & /*tabNodes*/ 4 && button_disabled_value !== (button_disabled_value = /*tab*/ ctx[17].disabled)) {
  8328. button.disabled = button_disabled_value;
  8329. }
  8330. if (!current || dirty & /*tabNodes*/ 4 && li_aria_controls_value !== (li_aria_controls_value = /*tab*/ ctx[17].href.substr(1))) {
  8331. attr(li, "aria-controls", li_aria_controls_value);
  8332. }
  8333. if (!current || dirty & /*tabNodes*/ 4 && li_id_value !== (li_id_value = /*tab*/ ctx[17].tabId)) {
  8334. attr(li, "id", li_id_value);
  8335. }
  8336. if (!current || dirty & /*tabNodes*/ 4 && li_aria_selected_value !== (li_aria_selected_value = /*tab*/ ctx[17].selected)) {
  8337. attr(li, "aria-selected", li_aria_selected_value);
  8338. }
  8339. },
  8340. i(local) {
  8341. if (current) return;
  8342. transition_in(default_slot, local);
  8343. current = true;
  8344. },
  8345. o(local) {
  8346. transition_out(default_slot, local);
  8347. current = false;
  8348. },
  8349. d(detaching) {
  8350. if (detaching) detach(li);
  8351. if (default_slot) default_slot.d(detaching);
  8352. mounted = false;
  8353. run_all(dispose);
  8354. }
  8355. };
  8356. }
  8357. function create_fragment$L(ctx) {
  8358. let if_block_anchor;
  8359. let current;
  8360. let if_block = /*shouldRender*/ ctx[4] && create_if_block$e(ctx);
  8361. return {
  8362. c() {
  8363. if (if_block) if_block.c();
  8364. if_block_anchor = empty();
  8365. },
  8366. m(target, anchor) {
  8367. if (if_block) if_block.m(target, anchor);
  8368. insert(target, if_block_anchor, anchor);
  8369. current = true;
  8370. },
  8371. p(ctx, [dirty]) {
  8372. if (/*shouldRender*/ ctx[4]) {
  8373. if (if_block) {
  8374. if_block.p(ctx, dirty);
  8375. if (dirty & /*shouldRender*/ 16) {
  8376. transition_in(if_block, 1);
  8377. }
  8378. } else {
  8379. if_block = create_if_block$e(ctx);
  8380. if_block.c();
  8381. transition_in(if_block, 1);
  8382. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  8383. }
  8384. } else if (if_block) {
  8385. group_outros();
  8386. transition_out(if_block, 1, 1, () => {
  8387. if_block = null;
  8388. });
  8389. check_outros();
  8390. }
  8391. },
  8392. i(local) {
  8393. if (current) return;
  8394. transition_in(if_block);
  8395. current = true;
  8396. },
  8397. o(local) {
  8398. transition_out(if_block);
  8399. current = false;
  8400. },
  8401. d(detaching) {
  8402. if (if_block) if_block.d(detaching);
  8403. if (detaching) detach(if_block_anchor);
  8404. }
  8405. };
  8406. }
  8407. function instance$L($$self, $$props, $$invalidate) {
  8408. let tabNodes;
  8409. let shouldRender;
  8410. let { $$slots: slots = {}, $$scope } = $$props;
  8411. let root;
  8412. let { class: klass = undefined } = $$props;
  8413. let { name } = $$props;
  8414. let { selected } = $$props;
  8415. let { tabs = [] } = $$props;
  8416. let { layout = undefined } = $$props;
  8417. const dispatch = createEventDispatcher();
  8418. const focusTab = index => {
  8419. const tab = root.querySelectorAll("[role=\"tab\"] button")[index];
  8420. if (!tab) return;
  8421. tab.focus();
  8422. };
  8423. const handleClickTab = (e, id) => {
  8424. e.preventDefault();
  8425. e.stopPropagation();
  8426. dispatch("select", id);
  8427. };
  8428. const handleKeyTab = ({ key }, id) => {
  8429. if (!(/arrow/i).test(key)) return;
  8430. const index = tabs.findIndex(tab => tab.id === id);
  8431. // next
  8432. if ((/right|down/i).test(key)) return focusTab(index < tabs.length - 1 ? index + 1 : 0);
  8433. // prev
  8434. if ((/left|up/i).test(key)) return focusTab(index > 0 ? index - 1 : tabs.length - 1);
  8435. };
  8436. const keydown_handler = (tab, e) => handleKeyTab(e, tab.id);
  8437. const click_handler = (tab, e) => handleClickTab(e, tab.id);
  8438. function ul_binding($$value) {
  8439. binding_callbacks[$$value ? "unshift" : "push"](() => {
  8440. root = $$value;
  8441. $$invalidate(3, root);
  8442. });
  8443. }
  8444. $$self.$$set = $$props => {
  8445. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  8446. if ("name" in $$props) $$invalidate(7, name = $$props.name);
  8447. if ("selected" in $$props) $$invalidate(8, selected = $$props.selected);
  8448. if ("tabs" in $$props) $$invalidate(9, tabs = $$props.tabs);
  8449. if ("layout" in $$props) $$invalidate(1, layout = $$props.layout);
  8450. if ("$$scope" in $$props) $$invalidate(10, $$scope = $$props.$$scope);
  8451. };
  8452. $$self.$$.update = () => {
  8453. if ($$self.$$.dirty & /*tabs, selected, name*/ 896) {
  8454. $$invalidate(2, tabNodes = tabs.map(tab => {
  8455. const isActive = tab.id === selected;
  8456. return {
  8457. ...tab,
  8458. tabId: `tab-${name}-${tab.id}`,
  8459. href: `#panel-${name}-${tab.id}`,
  8460. selected: isActive
  8461. };
  8462. }));
  8463. }
  8464. if ($$self.$$.dirty & /*tabNodes*/ 4) {
  8465. $$invalidate(4, shouldRender = tabNodes.length > 1);
  8466. }
  8467. };
  8468. return [
  8469. klass,
  8470. layout,
  8471. tabNodes,
  8472. root,
  8473. shouldRender,
  8474. handleClickTab,
  8475. handleKeyTab,
  8476. name,
  8477. selected,
  8478. tabs,
  8479. $$scope,
  8480. slots,
  8481. keydown_handler,
  8482. click_handler,
  8483. ul_binding
  8484. ];
  8485. }
  8486. class TabList extends SvelteComponent {
  8487. constructor(options) {
  8488. super();
  8489. init(this, options, instance$L, create_fragment$L, safe_not_equal, {
  8490. class: 0,
  8491. name: 7,
  8492. selected: 8,
  8493. tabs: 9,
  8494. layout: 1
  8495. });
  8496. }
  8497. }
  8498. /* src/core/ui/components/TabPanels.svelte generated by Svelte v3.37.0 */
  8499. const get_default_slot_changes_1 = dirty => ({ panel: dirty & /*panelNodes*/ 16 });
  8500. const get_default_slot_context_1 = ctx => ({
  8501. panel: /*panelNodes*/ ctx[4][0].id,
  8502. panelIsActive: true
  8503. });
  8504. function get_each_context$8(ctx, list, i) {
  8505. const child_ctx = ctx.slice();
  8506. child_ctx[14] = list[i].id;
  8507. child_ctx[15] = list[i].draw;
  8508. child_ctx[16] = list[i].panelId;
  8509. child_ctx[17] = list[i].tabindex;
  8510. child_ctx[18] = list[i].labelledBy;
  8511. child_ctx[19] = list[i].hidden;
  8512. child_ctx[3] = list[i].visible;
  8513. return child_ctx;
  8514. }
  8515. const get_default_slot_changes = dirty => ({
  8516. panel: dirty & /*panelNodes*/ 16,
  8517. panelIsActive: dirty & /*panelNodes*/ 16
  8518. });
  8519. const get_default_slot_context = ctx => ({
  8520. panel: /*id*/ ctx[14],
  8521. panelIsActive: !/*hidden*/ ctx[19]
  8522. });
  8523. // (56:0) {:else}
  8524. function create_else_block$5(ctx) {
  8525. let div1;
  8526. let div0;
  8527. let div0_class_value;
  8528. let current;
  8529. let mounted;
  8530. let dispose;
  8531. const default_slot_template = /*#slots*/ ctx[11].default;
  8532. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[10], get_default_slot_context_1);
  8533. return {
  8534. c() {
  8535. div1 = element("div");
  8536. div0 = element("div");
  8537. if (default_slot) default_slot.c();
  8538. attr(div0, "class", div0_class_value = arrayJoin([/*panelClass*/ ctx[1]]));
  8539. attr(div1, "class", /*klass*/ ctx[0]);
  8540. attr(div1, "style", /*style*/ ctx[2]);
  8541. },
  8542. m(target, anchor) {
  8543. insert(target, div1, anchor);
  8544. append(div1, div0);
  8545. if (default_slot) {
  8546. default_slot.m(div0, null);
  8547. }
  8548. current = true;
  8549. if (!mounted) {
  8550. dispose = [
  8551. listen(div1, "measure", /*measure_handler_1*/ ctx[13]),
  8552. action_destroyer(measurable.call(null, div1))
  8553. ];
  8554. mounted = true;
  8555. }
  8556. },
  8557. p(ctx, dirty) {
  8558. if (default_slot) {
  8559. if (default_slot.p && dirty & /*$$scope, panelNodes*/ 1040) {
  8560. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[10], dirty, get_default_slot_changes_1, get_default_slot_context_1);
  8561. }
  8562. }
  8563. if (!current || dirty & /*panelClass*/ 2 && div0_class_value !== (div0_class_value = arrayJoin([/*panelClass*/ ctx[1]]))) {
  8564. attr(div0, "class", div0_class_value);
  8565. }
  8566. if (!current || dirty & /*klass*/ 1) {
  8567. attr(div1, "class", /*klass*/ ctx[0]);
  8568. }
  8569. if (!current || dirty & /*style*/ 4) {
  8570. attr(div1, "style", /*style*/ ctx[2]);
  8571. }
  8572. },
  8573. i(local) {
  8574. if (current) return;
  8575. transition_in(default_slot, local);
  8576. current = true;
  8577. },
  8578. o(local) {
  8579. transition_out(default_slot, local);
  8580. current = false;
  8581. },
  8582. d(detaching) {
  8583. if (detaching) detach(div1);
  8584. if (default_slot) default_slot.d(detaching);
  8585. mounted = false;
  8586. run_all(dispose);
  8587. }
  8588. };
  8589. }
  8590. // (35:0) {#if shouldRender}
  8591. function create_if_block$d(ctx) {
  8592. let div;
  8593. let each_blocks = [];
  8594. let each_1_lookup = new Map();
  8595. let div_class_value;
  8596. let current;
  8597. let mounted;
  8598. let dispose;
  8599. let each_value = /*panelNodes*/ ctx[4];
  8600. const get_key = ctx => /*id*/ ctx[14];
  8601. for (let i = 0; i < each_value.length; i += 1) {
  8602. let child_ctx = get_each_context$8(ctx, each_value, i);
  8603. let key = get_key(child_ctx);
  8604. each_1_lookup.set(key, each_blocks[i] = create_each_block$8(key, child_ctx));
  8605. }
  8606. return {
  8607. c() {
  8608. div = element("div");
  8609. for (let i = 0; i < each_blocks.length; i += 1) {
  8610. each_blocks[i].c();
  8611. }
  8612. attr(div, "class", div_class_value = arrayJoin(["PinturaTabPanels", /*klass*/ ctx[0]]));
  8613. attr(div, "style", /*style*/ ctx[2]);
  8614. },
  8615. m(target, anchor) {
  8616. insert(target, div, anchor);
  8617. for (let i = 0; i < each_blocks.length; i += 1) {
  8618. each_blocks[i].m(div, null);
  8619. }
  8620. current = true;
  8621. if (!mounted) {
  8622. dispose = [
  8623. listen(div, "measure", /*measure_handler*/ ctx[12]),
  8624. action_destroyer(measurable.call(null, div, { observePosition: true }))
  8625. ];
  8626. mounted = true;
  8627. }
  8628. },
  8629. p(ctx, dirty) {
  8630. if (dirty & /*arrayJoin, panelClass, panelNodes, $$scope*/ 1042) {
  8631. each_value = /*panelNodes*/ ctx[4];
  8632. group_outros();
  8633. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, div, outro_and_destroy_block, create_each_block$8, null, get_each_context$8);
  8634. check_outros();
  8635. }
  8636. if (!current || dirty & /*klass*/ 1 && div_class_value !== (div_class_value = arrayJoin(["PinturaTabPanels", /*klass*/ ctx[0]]))) {
  8637. attr(div, "class", div_class_value);
  8638. }
  8639. if (!current || dirty & /*style*/ 4) {
  8640. attr(div, "style", /*style*/ ctx[2]);
  8641. }
  8642. },
  8643. i(local) {
  8644. if (current) return;
  8645. for (let i = 0; i < each_value.length; i += 1) {
  8646. transition_in(each_blocks[i]);
  8647. }
  8648. current = true;
  8649. },
  8650. o(local) {
  8651. for (let i = 0; i < each_blocks.length; i += 1) {
  8652. transition_out(each_blocks[i]);
  8653. }
  8654. current = false;
  8655. },
  8656. d(detaching) {
  8657. if (detaching) detach(div);
  8658. for (let i = 0; i < each_blocks.length; i += 1) {
  8659. each_blocks[i].d();
  8660. }
  8661. mounted = false;
  8662. run_all(dispose);
  8663. }
  8664. };
  8665. }
  8666. // (52:16) {#if draw}
  8667. function create_if_block_1$e(ctx) {
  8668. let current;
  8669. const default_slot_template = /*#slots*/ ctx[11].default;
  8670. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[10], get_default_slot_context);
  8671. return {
  8672. c() {
  8673. if (default_slot) default_slot.c();
  8674. },
  8675. m(target, anchor) {
  8676. if (default_slot) {
  8677. default_slot.m(target, anchor);
  8678. }
  8679. current = true;
  8680. },
  8681. p(ctx, dirty) {
  8682. if (default_slot) {
  8683. if (default_slot.p && dirty & /*$$scope, panelNodes*/ 1040) {
  8684. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[10], dirty, get_default_slot_changes, get_default_slot_context);
  8685. }
  8686. }
  8687. },
  8688. i(local) {
  8689. if (current) return;
  8690. transition_in(default_slot, local);
  8691. current = true;
  8692. },
  8693. o(local) {
  8694. transition_out(default_slot, local);
  8695. current = false;
  8696. },
  8697. d(detaching) {
  8698. if (default_slot) default_slot.d(detaching);
  8699. }
  8700. };
  8701. }
  8702. // (43:8) {#each panelNodes as { id, draw, panelId, tabindex, labelledBy, hidden, visible }
  8703. function create_each_block$8(key_1, ctx) {
  8704. let div;
  8705. let t;
  8706. let div_class_value;
  8707. let div_hidden_value;
  8708. let div_id_value;
  8709. let div_tabindex_value;
  8710. let div_aria_labelledby_value;
  8711. let div_data_inert_value;
  8712. let current;
  8713. let if_block = /*draw*/ ctx[15] && create_if_block_1$e(ctx);
  8714. return {
  8715. key: key_1,
  8716. first: null,
  8717. c() {
  8718. div = element("div");
  8719. if (if_block) if_block.c();
  8720. t = space();
  8721. attr(div, "class", div_class_value = arrayJoin(["PinturaTabPanel", /*panelClass*/ ctx[1]]));
  8722. div.hidden = div_hidden_value = /*hidden*/ ctx[19];
  8723. attr(div, "id", div_id_value = /*panelId*/ ctx[16]);
  8724. attr(div, "tabindex", div_tabindex_value = /*tabindex*/ ctx[17]);
  8725. attr(div, "aria-labelledby", div_aria_labelledby_value = /*labelledBy*/ ctx[18]);
  8726. attr(div, "data-inert", div_data_inert_value = !/*visible*/ ctx[3]);
  8727. this.first = div;
  8728. },
  8729. m(target, anchor) {
  8730. insert(target, div, anchor);
  8731. if (if_block) if_block.m(div, null);
  8732. append(div, t);
  8733. current = true;
  8734. },
  8735. p(new_ctx, dirty) {
  8736. ctx = new_ctx;
  8737. if (/*draw*/ ctx[15]) {
  8738. if (if_block) {
  8739. if_block.p(ctx, dirty);
  8740. if (dirty & /*panelNodes*/ 16) {
  8741. transition_in(if_block, 1);
  8742. }
  8743. } else {
  8744. if_block = create_if_block_1$e(ctx);
  8745. if_block.c();
  8746. transition_in(if_block, 1);
  8747. if_block.m(div, t);
  8748. }
  8749. } else if (if_block) {
  8750. group_outros();
  8751. transition_out(if_block, 1, 1, () => {
  8752. if_block = null;
  8753. });
  8754. check_outros();
  8755. }
  8756. if (!current || dirty & /*panelClass*/ 2 && div_class_value !== (div_class_value = arrayJoin(["PinturaTabPanel", /*panelClass*/ ctx[1]]))) {
  8757. attr(div, "class", div_class_value);
  8758. }
  8759. if (!current || dirty & /*panelNodes*/ 16 && div_hidden_value !== (div_hidden_value = /*hidden*/ ctx[19])) {
  8760. div.hidden = div_hidden_value;
  8761. }
  8762. if (!current || dirty & /*panelNodes*/ 16 && div_id_value !== (div_id_value = /*panelId*/ ctx[16])) {
  8763. attr(div, "id", div_id_value);
  8764. }
  8765. if (!current || dirty & /*panelNodes*/ 16 && div_tabindex_value !== (div_tabindex_value = /*tabindex*/ ctx[17])) {
  8766. attr(div, "tabindex", div_tabindex_value);
  8767. }
  8768. if (!current || dirty & /*panelNodes*/ 16 && div_aria_labelledby_value !== (div_aria_labelledby_value = /*labelledBy*/ ctx[18])) {
  8769. attr(div, "aria-labelledby", div_aria_labelledby_value);
  8770. }
  8771. if (!current || dirty & /*panelNodes*/ 16 && div_data_inert_value !== (div_data_inert_value = !/*visible*/ ctx[3])) {
  8772. attr(div, "data-inert", div_data_inert_value);
  8773. }
  8774. },
  8775. i(local) {
  8776. if (current) return;
  8777. transition_in(if_block);
  8778. current = true;
  8779. },
  8780. o(local) {
  8781. transition_out(if_block);
  8782. current = false;
  8783. },
  8784. d(detaching) {
  8785. if (detaching) detach(div);
  8786. if (if_block) if_block.d();
  8787. }
  8788. };
  8789. }
  8790. function create_fragment$K(ctx) {
  8791. let current_block_type_index;
  8792. let if_block;
  8793. let if_block_anchor;
  8794. let current;
  8795. const if_block_creators = [create_if_block$d, create_else_block$5];
  8796. const if_blocks = [];
  8797. function select_block_type(ctx, dirty) {
  8798. if (/*shouldRender*/ ctx[5]) return 0;
  8799. return 1;
  8800. }
  8801. current_block_type_index = select_block_type(ctx);
  8802. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  8803. return {
  8804. c() {
  8805. if_block.c();
  8806. if_block_anchor = empty();
  8807. },
  8808. m(target, anchor) {
  8809. if_blocks[current_block_type_index].m(target, anchor);
  8810. insert(target, if_block_anchor, anchor);
  8811. current = true;
  8812. },
  8813. p(ctx, [dirty]) {
  8814. let previous_block_index = current_block_type_index;
  8815. current_block_type_index = select_block_type(ctx);
  8816. if (current_block_type_index === previous_block_index) {
  8817. if_blocks[current_block_type_index].p(ctx, dirty);
  8818. } else {
  8819. group_outros();
  8820. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  8821. if_blocks[previous_block_index] = null;
  8822. });
  8823. check_outros();
  8824. if_block = if_blocks[current_block_type_index];
  8825. if (!if_block) {
  8826. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  8827. if_block.c();
  8828. } else {
  8829. if_block.p(ctx, dirty);
  8830. }
  8831. transition_in(if_block, 1);
  8832. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  8833. }
  8834. },
  8835. i(local) {
  8836. if (current) return;
  8837. transition_in(if_block);
  8838. current = true;
  8839. },
  8840. o(local) {
  8841. transition_out(if_block);
  8842. current = false;
  8843. },
  8844. d(detaching) {
  8845. if_blocks[current_block_type_index].d(detaching);
  8846. if (detaching) detach(if_block_anchor);
  8847. }
  8848. };
  8849. }
  8850. function instance$K($$self, $$props, $$invalidate) {
  8851. let panelNodes;
  8852. let shouldRender;
  8853. let { $$slots: slots = {}, $$scope } = $$props;
  8854. let { class: klass = undefined } = $$props;
  8855. let { name } = $$props;
  8856. let { selected } = $$props;
  8857. let { visible = undefined } = $$props;
  8858. let { panelClass = undefined } = $$props;
  8859. let { panels = [] } = $$props;
  8860. let { style = undefined } = $$props;
  8861. const drawCache = {};
  8862. function measure_handler(event) {
  8863. bubble($$self, event);
  8864. }
  8865. function measure_handler_1(event) {
  8866. bubble($$self, event);
  8867. }
  8868. $$self.$$set = $$props => {
  8869. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  8870. if ("name" in $$props) $$invalidate(6, name = $$props.name);
  8871. if ("selected" in $$props) $$invalidate(7, selected = $$props.selected);
  8872. if ("visible" in $$props) $$invalidate(3, visible = $$props.visible);
  8873. if ("panelClass" in $$props) $$invalidate(1, panelClass = $$props.panelClass);
  8874. if ("panels" in $$props) $$invalidate(8, panels = $$props.panels);
  8875. if ("style" in $$props) $$invalidate(2, style = $$props.style);
  8876. if ("$$scope" in $$props) $$invalidate(10, $$scope = $$props.$$scope);
  8877. };
  8878. $$self.$$.update = () => {
  8879. if ($$self.$$.dirty & /*panels, selected, visible, name, drawCache*/ 968) {
  8880. $$invalidate(4, panelNodes = panels.map(id => {
  8881. const isActive = id === selected;
  8882. const isVisible = visible ? visible.indexOf(id) !== -1 : true;
  8883. // remember that this tab was active so we keep drawing it even when it's inactive
  8884. if (isActive) $$invalidate(9, drawCache[id] = true, drawCache);
  8885. return {
  8886. id,
  8887. panelId: `panel-${name}-${id}`,
  8888. labelledBy: `tab-${name}-${id}`,
  8889. hidden: !isActive,
  8890. visible: isVisible,
  8891. tabindex: isActive ? 0 : -1,
  8892. draw: isActive || drawCache[id]
  8893. };
  8894. }));
  8895. }
  8896. if ($$self.$$.dirty & /*panelNodes*/ 16) {
  8897. $$invalidate(5, shouldRender = panelNodes.length > 1);
  8898. }
  8899. };
  8900. return [
  8901. klass,
  8902. panelClass,
  8903. style,
  8904. visible,
  8905. panelNodes,
  8906. shouldRender,
  8907. name,
  8908. selected,
  8909. panels,
  8910. drawCache,
  8911. $$scope,
  8912. slots,
  8913. measure_handler,
  8914. measure_handler_1
  8915. ];
  8916. }
  8917. class TabPanels extends SvelteComponent {
  8918. constructor(options) {
  8919. super();
  8920. init(this, options, instance$K, create_fragment$K, safe_not_equal, {
  8921. class: 0,
  8922. name: 6,
  8923. selected: 7,
  8924. visible: 3,
  8925. panelClass: 1,
  8926. panels: 8,
  8927. style: 2
  8928. });
  8929. }
  8930. }
  8931. /* src/core/ui/components/Panel.svelte generated by Svelte v3.37.0 */
  8932. function create_fragment$J(ctx) {
  8933. let div;
  8934. let switch_instance;
  8935. let updating_name;
  8936. let div_class_value;
  8937. let current;
  8938. const switch_instance_spread_levels = [/*componentProps*/ ctx[7]];
  8939. function switch_instance_name_binding(value) {
  8940. /*switch_instance_name_binding*/ ctx[19](value);
  8941. }
  8942. var switch_value = /*componentView*/ ctx[11];
  8943. function switch_props(ctx) {
  8944. let switch_instance_props = {};
  8945. for (let i = 0; i < switch_instance_spread_levels.length; i += 1) {
  8946. switch_instance_props = assign(switch_instance_props, switch_instance_spread_levels[i]);
  8947. }
  8948. if (/*panelName*/ ctx[5] !== void 0) {
  8949. switch_instance_props.name = /*panelName*/ ctx[5];
  8950. }
  8951. return { props: switch_instance_props };
  8952. }
  8953. if (switch_value) {
  8954. switch_instance = new switch_value(switch_props(ctx));
  8955. binding_callbacks.push(() => bind(switch_instance, "name", switch_instance_name_binding));
  8956. /*switch_instance_binding*/ ctx[20](switch_instance);
  8957. switch_instance.$on("measure", /*measure_handler*/ ctx[21]);
  8958. }
  8959. return {
  8960. c() {
  8961. div = element("div");
  8962. if (switch_instance) create_component(switch_instance.$$.fragment);
  8963. attr(div, "data-util", /*panelName*/ ctx[5]);
  8964. attr(div, "class", div_class_value = arrayJoin(["PinturaPanel", /*klass*/ ctx[2]]));
  8965. attr(div, "style", /*style*/ ctx[6]);
  8966. },
  8967. m(target, anchor) {
  8968. insert(target, div, anchor);
  8969. if (switch_instance) {
  8970. mount_component(switch_instance, div, null);
  8971. }
  8972. current = true;
  8973. },
  8974. p(ctx, [dirty]) {
  8975. const switch_instance_changes = (dirty & /*componentProps*/ 128)
  8976. ? get_spread_update(switch_instance_spread_levels, [get_spread_object(/*componentProps*/ ctx[7])])
  8977. : {};
  8978. if (!updating_name && dirty & /*panelName*/ 32) {
  8979. updating_name = true;
  8980. switch_instance_changes.name = /*panelName*/ ctx[5];
  8981. add_flush_callback(() => updating_name = false);
  8982. }
  8983. if (switch_value !== (switch_value = /*componentView*/ ctx[11])) {
  8984. if (switch_instance) {
  8985. group_outros();
  8986. const old_component = switch_instance;
  8987. transition_out(old_component.$$.fragment, 1, 0, () => {
  8988. destroy_component(old_component, 1);
  8989. });
  8990. check_outros();
  8991. }
  8992. if (switch_value) {
  8993. switch_instance = new switch_value(switch_props(ctx));
  8994. binding_callbacks.push(() => bind(switch_instance, "name", switch_instance_name_binding));
  8995. /*switch_instance_binding*/ ctx[20](switch_instance);
  8996. switch_instance.$on("measure", /*measure_handler*/ ctx[21]);
  8997. create_component(switch_instance.$$.fragment);
  8998. transition_in(switch_instance.$$.fragment, 1);
  8999. mount_component(switch_instance, div, null);
  9000. } else {
  9001. switch_instance = null;
  9002. }
  9003. } else if (switch_value) {
  9004. switch_instance.$set(switch_instance_changes);
  9005. }
  9006. if (!current || dirty & /*panelName*/ 32) {
  9007. attr(div, "data-util", /*panelName*/ ctx[5]);
  9008. }
  9009. if (!current || dirty & /*klass*/ 4 && div_class_value !== (div_class_value = arrayJoin(["PinturaPanel", /*klass*/ ctx[2]]))) {
  9010. attr(div, "class", div_class_value);
  9011. }
  9012. if (!current || dirty & /*style*/ 64) {
  9013. attr(div, "style", /*style*/ ctx[6]);
  9014. }
  9015. },
  9016. i(local) {
  9017. if (current) return;
  9018. if (switch_instance) transition_in(switch_instance.$$.fragment, local);
  9019. current = true;
  9020. },
  9021. o(local) {
  9022. if (switch_instance) transition_out(switch_instance.$$.fragment, local);
  9023. current = false;
  9024. },
  9025. d(detaching) {
  9026. if (detaching) detach(div);
  9027. /*switch_instance_binding*/ ctx[20](null);
  9028. if (switch_instance) destroy_component(switch_instance);
  9029. }
  9030. };
  9031. }
  9032. function instance$J($$self, $$props, $$invalidate) {
  9033. let style;
  9034. let componentProps;
  9035. let $opacityClamped;
  9036. let $isActivePrivateStore;
  9037. const dispatch = createEventDispatcher();
  9038. let { isActive = true } = $$props;
  9039. let { isAnimated = true } = $$props;
  9040. let { stores } = $$props;
  9041. let { content } = $$props;
  9042. let { component } = $$props;
  9043. let { locale } = $$props;
  9044. let { class: klass = undefined } = $$props;
  9045. // we remember the view rect in this variable
  9046. let rect;
  9047. const opacity = spring(0);
  9048. const opacityClamped = derived(opacity, $opacity => clamp($opacity, 0, 1));
  9049. component_subscribe($$self, opacityClamped, value => $$invalidate(18, $opacityClamped = value));
  9050. // throw hide / show events
  9051. let isHidden = !isActive;
  9052. // create active store so can be used in derived stores
  9053. const isActivePrivateStore = writable(isActive);
  9054. component_subscribe($$self, isActivePrivateStore, value => $$invalidate(22, $isActivePrivateStore = value));
  9055. const stateProps = {
  9056. isActive: derived(isActivePrivateStore, $isActivePrivateStore => $isActivePrivateStore),
  9057. isActiveFraction: derived(opacityClamped, $opacityClamped => $opacityClamped),
  9058. isVisible: derived(opacityClamped, $opacityClamped => $opacityClamped > 0)
  9059. };
  9060. // build the component props
  9061. const componentView = content.view;
  9062. const componentExportedProps = getComponentExportedProps(componentView);
  9063. const componentComputedProps = Object.keys(content.props || {}).reduce(
  9064. (computedProps, key) => {
  9065. if (!componentExportedProps.includes(key)) return computedProps;
  9066. computedProps[key] = content.props[key];
  9067. return computedProps;
  9068. },
  9069. {}
  9070. );
  9071. const componentComputedStateProps = Object.keys(stateProps).reduce(
  9072. (computedStateProps, key) => {
  9073. if (!componentExportedProps.includes(key)) return computedStateProps;
  9074. computedStateProps[key] = stateProps[key];
  9075. return computedStateProps;
  9076. },
  9077. {}
  9078. );
  9079. // class used on panel element
  9080. let panelName;
  9081. // we use the `hasBeenMounted` bool to block rect updates until the entire panel is ready
  9082. let hasBeenMounted = false;
  9083. onMount(() => {
  9084. $$invalidate(4, hasBeenMounted = true);
  9085. });
  9086. function switch_instance_name_binding(value) {
  9087. panelName = value;
  9088. $$invalidate(5, panelName);
  9089. }
  9090. function switch_instance_binding($$value) {
  9091. binding_callbacks[$$value ? "unshift" : "push"](() => {
  9092. component = $$value;
  9093. $$invalidate(0, component);
  9094. });
  9095. }
  9096. const measure_handler = e => {
  9097. if (!hasBeenMounted || !isActive) return;
  9098. $$invalidate(3, rect = e.detail);
  9099. dispatch("measure", { ...rect });
  9100. };
  9101. $$self.$$set = $$props => {
  9102. if ("isActive" in $$props) $$invalidate(1, isActive = $$props.isActive);
  9103. if ("isAnimated" in $$props) $$invalidate(12, isAnimated = $$props.isAnimated);
  9104. if ("stores" in $$props) $$invalidate(13, stores = $$props.stores);
  9105. if ("content" in $$props) $$invalidate(14, content = $$props.content);
  9106. if ("component" in $$props) $$invalidate(0, component = $$props.component);
  9107. if ("locale" in $$props) $$invalidate(15, locale = $$props.locale);
  9108. if ("class" in $$props) $$invalidate(2, klass = $$props.class);
  9109. };
  9110. $$self.$$.update = () => {
  9111. if ($$self.$$.dirty & /*rect, isActive, component*/ 11) {
  9112. // when the view rect changes and the panel is in active state or became active, dispatch measure event
  9113. if (rect && isActive && component) dispatch("measure", rect);
  9114. }
  9115. if ($$self.$$.dirty & /*isActive, isAnimated*/ 4098) {
  9116. opacity.set(isActive ? 1 : 0, { hard: !isAnimated });
  9117. }
  9118. if ($$self.$$.dirty & /*$opacityClamped, isHidden*/ 393216) {
  9119. if ($opacityClamped <= 0 && !isHidden) {
  9120. $$invalidate(17, isHidden = true);
  9121. } else if ($opacityClamped > 0 && isHidden) {
  9122. $$invalidate(17, isHidden = false);
  9123. }
  9124. }
  9125. if ($$self.$$.dirty & /*hasBeenMounted, isHidden*/ 131088) {
  9126. hasBeenMounted && dispatch(isHidden ? "hide" : "show");
  9127. }
  9128. if ($$self.$$.dirty & /*$opacityClamped*/ 262144) {
  9129. dispatch("fade", $opacityClamped);
  9130. }
  9131. if ($$self.$$.dirty & /*$opacityClamped*/ 262144) {
  9132. // only set opacity prop if is below 0
  9133. $$invalidate(6, style = $opacityClamped < 1
  9134. ? `opacity: ${$opacityClamped}`
  9135. : undefined);
  9136. }
  9137. if ($$self.$$.dirty & /*isActive*/ 2) {
  9138. set_store_value(isActivePrivateStore, $isActivePrivateStore = isActive, $isActivePrivateStore);
  9139. }
  9140. if ($$self.$$.dirty & /*stores, locale*/ 40960) {
  9141. $$invalidate(7, componentProps = {
  9142. ...componentComputedProps,
  9143. ...componentComputedStateProps,
  9144. stores,
  9145. locale
  9146. });
  9147. }
  9148. };
  9149. return [
  9150. component,
  9151. isActive,
  9152. klass,
  9153. rect,
  9154. hasBeenMounted,
  9155. panelName,
  9156. style,
  9157. componentProps,
  9158. dispatch,
  9159. opacityClamped,
  9160. isActivePrivateStore,
  9161. componentView,
  9162. isAnimated,
  9163. stores,
  9164. content,
  9165. locale,
  9166. opacity,
  9167. isHidden,
  9168. $opacityClamped,
  9169. switch_instance_name_binding,
  9170. switch_instance_binding,
  9171. measure_handler
  9172. ];
  9173. }
  9174. class Panel extends SvelteComponent {
  9175. constructor(options) {
  9176. super();
  9177. init(this, options, instance$J, create_fragment$J, safe_not_equal, {
  9178. isActive: 1,
  9179. isAnimated: 12,
  9180. stores: 13,
  9181. content: 14,
  9182. component: 0,
  9183. locale: 15,
  9184. class: 2,
  9185. opacity: 16
  9186. });
  9187. }
  9188. get opacity() {
  9189. return this.$$.ctx[16];
  9190. }
  9191. }
  9192. /* src/core/ui/components/Icon.svelte generated by Svelte v3.37.0 */
  9193. function create_fragment$I(ctx) {
  9194. let svg;
  9195. let svg_viewBox_value;
  9196. let current;
  9197. const default_slot_template = /*#slots*/ ctx[5].default;
  9198. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[4], null);
  9199. return {
  9200. c() {
  9201. svg = svg_element("svg");
  9202. if (default_slot) default_slot.c();
  9203. attr(svg, "class", /*klass*/ ctx[3]);
  9204. attr(svg, "style", /*style*/ ctx[2]);
  9205. attr(svg, "width", /*width*/ ctx[0]);
  9206. attr(svg, "height", /*height*/ ctx[1]);
  9207. attr(svg, "viewBox", svg_viewBox_value = "0 0 " + /*width*/ ctx[0] + "\n " + /*height*/ ctx[1]);
  9208. attr(svg, "xmlns", "http://www.w3.org/2000/svg");
  9209. attr(svg, "aria-hidden", "true");
  9210. attr(svg, "focusable", "false");
  9211. attr(svg, "stroke-linecap", "round");
  9212. attr(svg, "stroke-linejoin", "round");
  9213. },
  9214. m(target, anchor) {
  9215. insert(target, svg, anchor);
  9216. if (default_slot) {
  9217. default_slot.m(svg, null);
  9218. }
  9219. current = true;
  9220. },
  9221. p(ctx, [dirty]) {
  9222. if (default_slot) {
  9223. if (default_slot.p && dirty & /*$$scope*/ 16) {
  9224. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[4], dirty, null, null);
  9225. }
  9226. }
  9227. if (!current || dirty & /*klass*/ 8) {
  9228. attr(svg, "class", /*klass*/ ctx[3]);
  9229. }
  9230. if (!current || dirty & /*style*/ 4) {
  9231. attr(svg, "style", /*style*/ ctx[2]);
  9232. }
  9233. if (!current || dirty & /*width*/ 1) {
  9234. attr(svg, "width", /*width*/ ctx[0]);
  9235. }
  9236. if (!current || dirty & /*height*/ 2) {
  9237. attr(svg, "height", /*height*/ ctx[1]);
  9238. }
  9239. if (!current || dirty & /*width, height*/ 3 && svg_viewBox_value !== (svg_viewBox_value = "0 0 " + /*width*/ ctx[0] + "\n " + /*height*/ ctx[1])) {
  9240. attr(svg, "viewBox", svg_viewBox_value);
  9241. }
  9242. },
  9243. i(local) {
  9244. if (current) return;
  9245. transition_in(default_slot, local);
  9246. current = true;
  9247. },
  9248. o(local) {
  9249. transition_out(default_slot, local);
  9250. current = false;
  9251. },
  9252. d(detaching) {
  9253. if (detaching) detach(svg);
  9254. if (default_slot) default_slot.d(detaching);
  9255. }
  9256. };
  9257. }
  9258. function instance$I($$self, $$props, $$invalidate) {
  9259. let { $$slots: slots = {}, $$scope } = $$props;
  9260. let { width = 24 } = $$props;
  9261. let { height = 24 } = $$props;
  9262. let { style = undefined } = $$props;
  9263. let { class: klass = undefined } = $$props;
  9264. $$self.$$set = $$props => {
  9265. if ("width" in $$props) $$invalidate(0, width = $$props.width);
  9266. if ("height" in $$props) $$invalidate(1, height = $$props.height);
  9267. if ("style" in $$props) $$invalidate(2, style = $$props.style);
  9268. if ("class" in $$props) $$invalidate(3, klass = $$props.class);
  9269. if ("$$scope" in $$props) $$invalidate(4, $$scope = $$props.$$scope);
  9270. };
  9271. return [width, height, style, klass, $$scope, slots];
  9272. }
  9273. class Icon extends SvelteComponent {
  9274. constructor(options) {
  9275. super();
  9276. init(this, options, instance$I, create_fragment$I, safe_not_equal, { width: 0, height: 1, style: 2, class: 3 });
  9277. }
  9278. }
  9279. var isEventTarget = (e, element) => element === e.target || element.contains(e.target);
  9280. /* src/core/ui/components/Button.svelte generated by Svelte v3.37.0 */
  9281. function create_if_block_1$d(ctx) {
  9282. let icon_1;
  9283. let current;
  9284. icon_1 = new Icon({
  9285. props: {
  9286. class: "PinturaButtonIcon",
  9287. $$slots: { default: [create_default_slot$h] },
  9288. $$scope: { ctx }
  9289. }
  9290. });
  9291. return {
  9292. c() {
  9293. create_component(icon_1.$$.fragment);
  9294. },
  9295. m(target, anchor) {
  9296. mount_component(icon_1, target, anchor);
  9297. current = true;
  9298. },
  9299. p(ctx, dirty) {
  9300. const icon_1_changes = {};
  9301. if (dirty & /*$$scope, icon*/ 1048578) {
  9302. icon_1_changes.$$scope = { dirty, ctx };
  9303. }
  9304. icon_1.$set(icon_1_changes);
  9305. },
  9306. i(local) {
  9307. if (current) return;
  9308. transition_in(icon_1.$$.fragment, local);
  9309. current = true;
  9310. },
  9311. o(local) {
  9312. transition_out(icon_1.$$.fragment, local);
  9313. current = false;
  9314. },
  9315. d(detaching) {
  9316. destroy_component(icon_1, detaching);
  9317. }
  9318. };
  9319. }
  9320. // (44:16) <Icon class="PinturaButtonIcon">
  9321. function create_default_slot$h(ctx) {
  9322. let g;
  9323. return {
  9324. c() {
  9325. g = svg_element("g");
  9326. },
  9327. m(target, anchor) {
  9328. insert(target, g, anchor);
  9329. g.innerHTML = /*icon*/ ctx[1];
  9330. },
  9331. p(ctx, dirty) {
  9332. if (dirty & /*icon*/ 2) g.innerHTML = /*icon*/ ctx[1]; },
  9333. d(detaching) {
  9334. if (detaching) detach(g);
  9335. }
  9336. };
  9337. }
  9338. // (50:12) {#if label}
  9339. function create_if_block$c(ctx) {
  9340. let span;
  9341. let t;
  9342. return {
  9343. c() {
  9344. span = element("span");
  9345. t = text(/*label*/ ctx[0]);
  9346. attr(span, "class", /*elLabelClass*/ ctx[11]);
  9347. },
  9348. m(target, anchor) {
  9349. insert(target, span, anchor);
  9350. append(span, t);
  9351. },
  9352. p(ctx, dirty) {
  9353. if (dirty & /*label*/ 1) set_data(t, /*label*/ ctx[0]);
  9354. if (dirty & /*elLabelClass*/ 2048) {
  9355. attr(span, "class", /*elLabelClass*/ ctx[11]);
  9356. }
  9357. },
  9358. d(detaching) {
  9359. if (detaching) detach(span);
  9360. }
  9361. };
  9362. }
  9363. // (41:10)
  9364. function fallback_block$2(ctx) {
  9365. let span;
  9366. let t;
  9367. let current;
  9368. let if_block0 = /*icon*/ ctx[1] && create_if_block_1$d(ctx);
  9369. let if_block1 = /*label*/ ctx[0] && create_if_block$c(ctx);
  9370. return {
  9371. c() {
  9372. span = element("span");
  9373. if (if_block0) if_block0.c();
  9374. t = space();
  9375. if (if_block1) if_block1.c();
  9376. attr(span, "class", /*elButtonInnerClass*/ ctx[9]);
  9377. },
  9378. m(target, anchor) {
  9379. insert(target, span, anchor);
  9380. if (if_block0) if_block0.m(span, null);
  9381. append(span, t);
  9382. if (if_block1) if_block1.m(span, null);
  9383. current = true;
  9384. },
  9385. p(ctx, dirty) {
  9386. if (/*icon*/ ctx[1]) {
  9387. if (if_block0) {
  9388. if_block0.p(ctx, dirty);
  9389. if (dirty & /*icon*/ 2) {
  9390. transition_in(if_block0, 1);
  9391. }
  9392. } else {
  9393. if_block0 = create_if_block_1$d(ctx);
  9394. if_block0.c();
  9395. transition_in(if_block0, 1);
  9396. if_block0.m(span, t);
  9397. }
  9398. } else if (if_block0) {
  9399. group_outros();
  9400. transition_out(if_block0, 1, 1, () => {
  9401. if_block0 = null;
  9402. });
  9403. check_outros();
  9404. }
  9405. if (/*label*/ ctx[0]) {
  9406. if (if_block1) {
  9407. if_block1.p(ctx, dirty);
  9408. } else {
  9409. if_block1 = create_if_block$c(ctx);
  9410. if_block1.c();
  9411. if_block1.m(span, null);
  9412. }
  9413. } else if (if_block1) {
  9414. if_block1.d(1);
  9415. if_block1 = null;
  9416. }
  9417. if (!current || dirty & /*elButtonInnerClass*/ 512) {
  9418. attr(span, "class", /*elButtonInnerClass*/ ctx[9]);
  9419. }
  9420. },
  9421. i(local) {
  9422. if (current) return;
  9423. transition_in(if_block0);
  9424. current = true;
  9425. },
  9426. o(local) {
  9427. transition_out(if_block0);
  9428. current = false;
  9429. },
  9430. d(detaching) {
  9431. if (detaching) detach(span);
  9432. if (if_block0) if_block0.d();
  9433. if (if_block1) if_block1.d();
  9434. }
  9435. };
  9436. }
  9437. function create_fragment$H(ctx) {
  9438. let button;
  9439. let current;
  9440. let mounted;
  9441. let dispose;
  9442. const default_slot_template = /*#slots*/ ctx[18].default;
  9443. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[20], null);
  9444. const default_slot_or_fallback = default_slot || fallback_block$2(ctx);
  9445. return {
  9446. c() {
  9447. button = element("button");
  9448. if (default_slot_or_fallback) default_slot_or_fallback.c();
  9449. attr(button, "type", /*type*/ ctx[4]);
  9450. attr(button, "style", /*style*/ ctx[2]);
  9451. button.disabled = /*disabled*/ ctx[3];
  9452. attr(button, "class", /*elButtonClass*/ ctx[10]);
  9453. attr(button, "title", /*label*/ ctx[0]);
  9454. },
  9455. m(target, anchor) {
  9456. insert(target, button, anchor);
  9457. if (default_slot_or_fallback) {
  9458. default_slot_or_fallback.m(button, null);
  9459. }
  9460. /*button_binding*/ ctx[19](button);
  9461. current = true;
  9462. if (!mounted) {
  9463. dispose = [
  9464. listen(button, "keydown", function () {
  9465. if (is_function(/*onkeydown*/ ctx[6])) /*onkeydown*/ ctx[6].apply(this, arguments);
  9466. }),
  9467. listen(button, "click", function () {
  9468. if (is_function(/*onclick*/ ctx[5])) /*onclick*/ ctx[5].apply(this, arguments);
  9469. }),
  9470. action_destroyer(/*action*/ ctx[7].call(null, button))
  9471. ];
  9472. mounted = true;
  9473. }
  9474. },
  9475. p(new_ctx, [dirty]) {
  9476. ctx = new_ctx;
  9477. if (default_slot) {
  9478. if (default_slot.p && dirty & /*$$scope*/ 1048576) {
  9479. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[20], dirty, null, null);
  9480. }
  9481. } else {
  9482. if (default_slot_or_fallback && default_slot_or_fallback.p && dirty & /*elButtonInnerClass, elLabelClass, label, icon*/ 2563) {
  9483. default_slot_or_fallback.p(ctx, dirty);
  9484. }
  9485. }
  9486. if (!current || dirty & /*type*/ 16) {
  9487. attr(button, "type", /*type*/ ctx[4]);
  9488. }
  9489. if (!current || dirty & /*style*/ 4) {
  9490. attr(button, "style", /*style*/ ctx[2]);
  9491. }
  9492. if (!current || dirty & /*disabled*/ 8) {
  9493. button.disabled = /*disabled*/ ctx[3];
  9494. }
  9495. if (!current || dirty & /*elButtonClass*/ 1024) {
  9496. attr(button, "class", /*elButtonClass*/ ctx[10]);
  9497. }
  9498. if (!current || dirty & /*label*/ 1) {
  9499. attr(button, "title", /*label*/ ctx[0]);
  9500. }
  9501. },
  9502. i(local) {
  9503. if (current) return;
  9504. transition_in(default_slot_or_fallback, local);
  9505. current = true;
  9506. },
  9507. o(local) {
  9508. transition_out(default_slot_or_fallback, local);
  9509. current = false;
  9510. },
  9511. d(detaching) {
  9512. if (detaching) detach(button);
  9513. if (default_slot_or_fallback) default_slot_or_fallback.d(detaching);
  9514. /*button_binding*/ ctx[19](null);
  9515. mounted = false;
  9516. run_all(dispose);
  9517. }
  9518. };
  9519. }
  9520. function instance$H($$self, $$props, $$invalidate) {
  9521. let elButtonInnerClass;
  9522. let elButtonClass;
  9523. let elLabelClass;
  9524. let { $$slots: slots = {}, $$scope } = $$props;
  9525. let { class: klass = undefined } = $$props;
  9526. let { label = undefined } = $$props;
  9527. let { labelClass = undefined } = $$props;
  9528. let { innerClass = undefined } = $$props;
  9529. let { hideLabel = false } = $$props;
  9530. let { icon = undefined } = $$props;
  9531. let { style = undefined } = $$props;
  9532. let { disabled = undefined } = $$props;
  9533. let { type = "button" } = $$props;
  9534. let { onclick = undefined } = $$props;
  9535. let { onkeydown = undefined } = $$props;
  9536. let { action = () => {
  9537. } } = $$props;
  9538. let root;
  9539. const isEventTarget$1 = e => isEventTarget(e, root);
  9540. const getElement = () => root;
  9541. function button_binding($$value) {
  9542. binding_callbacks[$$value ? "unshift" : "push"](() => {
  9543. root = $$value;
  9544. $$invalidate(8, root);
  9545. });
  9546. }
  9547. $$self.$$set = $$props => {
  9548. if ("class" in $$props) $$invalidate(12, klass = $$props.class);
  9549. if ("label" in $$props) $$invalidate(0, label = $$props.label);
  9550. if ("labelClass" in $$props) $$invalidate(13, labelClass = $$props.labelClass);
  9551. if ("innerClass" in $$props) $$invalidate(14, innerClass = $$props.innerClass);
  9552. if ("hideLabel" in $$props) $$invalidate(15, hideLabel = $$props.hideLabel);
  9553. if ("icon" in $$props) $$invalidate(1, icon = $$props.icon);
  9554. if ("style" in $$props) $$invalidate(2, style = $$props.style);
  9555. if ("disabled" in $$props) $$invalidate(3, disabled = $$props.disabled);
  9556. if ("type" in $$props) $$invalidate(4, type = $$props.type);
  9557. if ("onclick" in $$props) $$invalidate(5, onclick = $$props.onclick);
  9558. if ("onkeydown" in $$props) $$invalidate(6, onkeydown = $$props.onkeydown);
  9559. if ("action" in $$props) $$invalidate(7, action = $$props.action);
  9560. if ("$$scope" in $$props) $$invalidate(20, $$scope = $$props.$$scope);
  9561. };
  9562. $$self.$$.update = () => {
  9563. if ($$self.$$.dirty & /*innerClass*/ 16384) {
  9564. $$invalidate(9, elButtonInnerClass = arrayJoin(["PinturaButtonInner", innerClass]));
  9565. }
  9566. if ($$self.$$.dirty & /*hideLabel, klass*/ 36864) {
  9567. $$invalidate(10, elButtonClass = arrayJoin(["PinturaButton", hideLabel && "PinturaButtonIconOnly", klass]));
  9568. }
  9569. if ($$self.$$.dirty & /*hideLabel, labelClass*/ 40960) {
  9570. $$invalidate(11, elLabelClass = arrayJoin([hideLabel ? "implicit" : "PinturaButtonLabel", labelClass]));
  9571. }
  9572. };
  9573. return [
  9574. label,
  9575. icon,
  9576. style,
  9577. disabled,
  9578. type,
  9579. onclick,
  9580. onkeydown,
  9581. action,
  9582. root,
  9583. elButtonInnerClass,
  9584. elButtonClass,
  9585. elLabelClass,
  9586. klass,
  9587. labelClass,
  9588. innerClass,
  9589. hideLabel,
  9590. isEventTarget$1,
  9591. getElement,
  9592. slots,
  9593. button_binding,
  9594. $$scope
  9595. ];
  9596. }
  9597. class Button extends SvelteComponent {
  9598. constructor(options) {
  9599. super();
  9600. init(this, options, instance$H, create_fragment$H, safe_not_equal, {
  9601. class: 12,
  9602. label: 0,
  9603. labelClass: 13,
  9604. innerClass: 14,
  9605. hideLabel: 15,
  9606. icon: 1,
  9607. style: 2,
  9608. disabled: 3,
  9609. type: 4,
  9610. onclick: 5,
  9611. onkeydown: 6,
  9612. action: 7,
  9613. isEventTarget: 16,
  9614. getElement: 17
  9615. });
  9616. }
  9617. get isEventTarget() {
  9618. return this.$$.ctx[16];
  9619. }
  9620. get getElement() {
  9621. return this.$$.ctx[17];
  9622. }
  9623. }
  9624. var arrayRemove = (array, predicate) => {
  9625. const index = array.findIndex(predicate);
  9626. if (index >= 0)
  9627. return array.splice(index, 1);
  9628. return undefined;
  9629. };
  9630. // svelte
  9631. // constants
  9632. const INERTIA_THRESHOLD = 0.25; // when force of velocity exceeds this value we drift
  9633. const INERTIA_DISTANCE_MULTIPLIER = 50;
  9634. const INERTIA_DURATION_MULTIPLIER = 80;
  9635. const TAP_DURATION_MAX = 300;
  9636. const TAP_DISTANCE_MAX = 64;
  9637. const DOUBLE_TAP_DURATION_MAX = 700;
  9638. const DOUBLE_TAP_DISTANCE_MAX = 128;
  9639. const isContextMenuAction = (e) => isNumber(e.button) && e.button !== 0;
  9640. var interactable = (node, options = {}) => {
  9641. // set defaults
  9642. const { inertia = false, matchTarget = false, pinch = false, getEventPosition = (e) => vectorCreate(e.clientX, e.clientY), } = options;
  9643. //
  9644. // helpers
  9645. //
  9646. function dispatch(type, detail) {
  9647. node.dispatchEvent(new CustomEvent(type, { detail }));
  9648. }
  9649. function resetInertia() {
  9650. if (inertiaTweenUnsubscribe)
  9651. inertiaTweenUnsubscribe();
  9652. inertiaTweenUnsubscribe = undefined;
  9653. }
  9654. //#region pointer registry
  9655. const pointers = [];
  9656. const addPointer = (e) => {
  9657. const pointer = {
  9658. timeStamp: e.timeStamp,
  9659. timeStampInitial: e.timeStamp,
  9660. position: getEventPosition(e),
  9661. origin: getEventPosition(e),
  9662. velocity: vectorCreateEmpty(),
  9663. translation: vectorCreateEmpty(),
  9664. interactionState: undefined,
  9665. event: e,
  9666. };
  9667. pointers.push(pointer);
  9668. pointer.interactionState = getInteractionState(pointers);
  9669. };
  9670. const removePointer = (e) => {
  9671. const pointer = arrayRemove(pointers, (pointer) => pointer.event.pointerId === e.pointerId);
  9672. if (pointer)
  9673. return pointer[0];
  9674. };
  9675. const getPointerIndex = (e) => pointers.findIndex((pointer) => pointer.event.pointerId === e.pointerId);
  9676. const flattenPointerOrigin = (pointer) => {
  9677. pointer.origin.x = pointer.position.x;
  9678. pointer.origin.y = pointer.position.y;
  9679. pointer.translation.x = 0;
  9680. pointer.translation.y = 0;
  9681. };
  9682. const updatePointer = (e) => {
  9683. const pointer = getPointer(e);
  9684. if (!pointer)
  9685. return;
  9686. const { timeStamp } = e;
  9687. // position
  9688. const eventPosition = getEventPosition(e);
  9689. // duration between previous interaction and new interaction, an interaction duration cannot be faster than 1 millisecond
  9690. const interactionDuration = Math.max(1, timeStamp - pointer.timeStamp);
  9691. // calculate velocity
  9692. pointer.velocity.x = (eventPosition.x - pointer.position.x) / interactionDuration;
  9693. pointer.velocity.y = (eventPosition.y - pointer.position.y) / interactionDuration;
  9694. // update the translation
  9695. pointer.translation.x = eventPosition.x - pointer.origin.x;
  9696. pointer.translation.y = eventPosition.y - pointer.origin.y;
  9697. // set new state
  9698. pointer.timeStamp = timeStamp;
  9699. pointer.position.x = eventPosition.x;
  9700. pointer.position.y = eventPosition.y;
  9701. pointer.event = e;
  9702. };
  9703. const getPointer = (e) => {
  9704. const i = getPointerIndex(e);
  9705. if (i < 0)
  9706. return;
  9707. return pointers[i];
  9708. };
  9709. const isSingleTouching = () => pointers.length === 1;
  9710. const isMultiTouching = () => pointers.length === 2;
  9711. const getDistance = (pointers, position) => {
  9712. const distanceTotal = pointers.reduce((prev, curr) => {
  9713. prev += vectorDistance(position, curr.position);
  9714. return prev;
  9715. }, 0);
  9716. return distanceTotal / pointers.length;
  9717. };
  9718. const getInteractionState = (pointers) => {
  9719. const center = vectorCenter(pointers.map((pointer) => pointer.position));
  9720. const distance = getDistance(pointers, center);
  9721. return {
  9722. center,
  9723. distance,
  9724. velocity: vectorCenter(pointers.map((pointer) => pointer.velocity)),
  9725. translation: vectorCenter(pointers.map((pointer) => pointer.translation)),
  9726. };
  9727. };
  9728. //#endregion
  9729. let inertiaTween;
  9730. let inertiaTweenUnsubscribe;
  9731. let pinchOffsetDistance;
  9732. let currentTranslation;
  9733. let currentScale;
  9734. let isGesture;
  9735. let lastTapTimeStamp = 0;
  9736. let lastTapPosition = undefined;
  9737. // start handling interactions
  9738. node.addEventListener('pointerdown', handlePointerdown);
  9739. function handlePointerdown(e) {
  9740. // ignore more than two pointers for now
  9741. if (isMultiTouching())
  9742. return;
  9743. // not interested in context menu
  9744. if (isContextMenuAction(e))
  9745. return;
  9746. // target should equal node, if it doesn't user might have clicked one of the nodes children
  9747. if (matchTarget && e.target !== node)
  9748. return;
  9749. // stop any previous inertia tweens
  9750. resetInertia();
  9751. // register this pointer
  9752. addPointer(e);
  9753. // if is first pointer we need to init the drag gesture
  9754. if (isSingleTouching()) {
  9755. // handle pointer events
  9756. document.documentElement.addEventListener('pointermove', handlePointermove);
  9757. document.documentElement.addEventListener('pointerup', handlePointerup);
  9758. document.documentElement.addEventListener('pointercancel', handlePointerup);
  9759. // clear vars
  9760. isGesture = false;
  9761. currentScale = 1;
  9762. currentTranslation = vectorCreateEmpty();
  9763. pinchOffsetDistance = undefined;
  9764. dispatch('interactionstart', {
  9765. origin: vectorClone(getPointer(e).origin),
  9766. });
  9767. }
  9768. else if (pinch) {
  9769. isGesture = true;
  9770. pinchOffsetDistance = vectorDistance(pointers[0].position, pointers[1].position);
  9771. currentTranslation.x += pointers[0].translation.x;
  9772. currentTranslation.y += pointers[0].translation.y;
  9773. flattenPointerOrigin(pointers[0]);
  9774. }
  9775. }
  9776. //
  9777. // pointer move can only be a primary event (other pointers are not handled)
  9778. //
  9779. let moveLast = Date.now();
  9780. function handlePointermove(e) {
  9781. // prevent selection of text (Safari)
  9782. e.preventDefault();
  9783. // update pointer state
  9784. updatePointer(e);
  9785. let translation = vectorClone(pointers[0].translation);
  9786. let scalar = currentScale;
  9787. if (pinch && isMultiTouching()) {
  9788. // current pinch distance
  9789. const pinchCurrentDistance = vectorDistance(pointers[0].position, pointers[1].position);
  9790. // to find out scalar we calculate the difference between the pinch offset and the new pinch
  9791. const pinchScalar = pinchCurrentDistance / pinchOffsetDistance;
  9792. // add to existing scalar
  9793. scalar *= pinchScalar;
  9794. // current offset
  9795. vectorAdd(translation, pointers[1].translation);
  9796. }
  9797. translation.x += currentTranslation.x;
  9798. translation.y += currentTranslation.y;
  9799. // skip update event if last interaction was less than 16 ms ago
  9800. const now = Date.now();
  9801. const dist = now - moveLast;
  9802. if (dist < 16)
  9803. return;
  9804. moveLast = now;
  9805. dispatch('interactionupdate', {
  9806. translation,
  9807. scalar: pinch ? scalar : undefined,
  9808. });
  9809. }
  9810. //
  9811. // pointer up can only be a primary event (other pointers are not handled)
  9812. //
  9813. function handlePointerup(e) {
  9814. // test if is my pointer that was released, as we're listining on document it could be other pointers
  9815. if (!getPointer(e))
  9816. return;
  9817. // remove pointer from active pointers array
  9818. const removedPointer = removePointer(e);
  9819. // store current size
  9820. if (pinch && isSingleTouching()) {
  9821. // calculate current scale
  9822. const pinchCurrentDistance = vectorDistance(pointers[0].position, removedPointer.position);
  9823. currentScale *= pinchCurrentDistance / pinchOffsetDistance;
  9824. currentTranslation.x += pointers[0].translation.x + removedPointer.translation.x;
  9825. currentTranslation.y += pointers[0].translation.y + removedPointer.translation.y;
  9826. flattenPointerOrigin(pointers[0]);
  9827. }
  9828. // check if this was a tap
  9829. let isTap = false;
  9830. let isDoubleTap = false;
  9831. if (!isGesture && removedPointer) {
  9832. const interactionEnd = performance.now();
  9833. const interactionDuration = interactionEnd - removedPointer.timeStampInitial;
  9834. const interactionDistanceSquared = vectorDistanceSquared(removedPointer.translation);
  9835. isTap =
  9836. interactionDistanceSquared < TAP_DISTANCE_MAX &&
  9837. interactionDuration < TAP_DURATION_MAX;
  9838. isDoubleTap = !!(lastTapPosition &&
  9839. isTap &&
  9840. interactionEnd - lastTapTimeStamp < DOUBLE_TAP_DURATION_MAX &&
  9841. vectorDistanceSquared(lastTapPosition, removedPointer.position) <
  9842. DOUBLE_TAP_DISTANCE_MAX);
  9843. if (isTap) {
  9844. lastTapPosition = vectorClone(removedPointer.position);
  9845. lastTapTimeStamp = interactionEnd;
  9846. }
  9847. }
  9848. // we wait till last multi-touch interaction is finished, all pointers need to be de-registered before proceeding
  9849. if (pointers.length > 0)
  9850. return;
  9851. // stop listening
  9852. document.documentElement.removeEventListener('pointermove', handlePointermove);
  9853. document.documentElement.removeEventListener('pointerup', handlePointerup);
  9854. document.documentElement.removeEventListener('pointercancel', handlePointerup);
  9855. const translation = vectorClone(removedPointer.translation);
  9856. const velocity = vectorClone(removedPointer.velocity);
  9857. // allows cancelling inertia from release handler
  9858. let inertiaPrevented = false;
  9859. // user has released interaction
  9860. dispatch('interactionrelease', {
  9861. isTap,
  9862. isDoubleTap,
  9863. translation,
  9864. scalar: currentScale,
  9865. preventInertia: () => (inertiaPrevented = true),
  9866. });
  9867. // stop intantly if not a lot of force applied
  9868. const force = vectorDistance(velocity);
  9869. if (inertiaPrevented || !inertia || force < INERTIA_THRESHOLD) {
  9870. return handleEnd(translation, { isTap, isDoubleTap });
  9871. }
  9872. // drift
  9873. inertiaTween = tweened(vectorClone(translation), {
  9874. easing: circOut,
  9875. duration: force * INERTIA_DURATION_MULTIPLIER,
  9876. });
  9877. inertiaTween
  9878. .set({
  9879. x: translation.x + velocity.x * INERTIA_DISTANCE_MULTIPLIER,
  9880. y: translation.y + velocity.y * INERTIA_DISTANCE_MULTIPLIER,
  9881. })
  9882. .then(() => {
  9883. // if has unsubscribed (tween was reset)
  9884. if (!inertiaTweenUnsubscribe)
  9885. return;
  9886. // go!
  9887. handleEnd(get_store_value(inertiaTween), { isTap, isDoubleTap });
  9888. });
  9889. inertiaTweenUnsubscribe = inertiaTween.subscribe(handleInertiaUpdate);
  9890. }
  9891. function handleInertiaUpdate(inertiaTranslation) {
  9892. // if is same as previous position, ignore
  9893. if (!inertiaTranslation)
  9894. return; // || vectorEqual(inertiaTranslation, translation)) return;
  9895. // this will handle drift interactions
  9896. dispatch('interactionupdate', {
  9897. translation: inertiaTranslation,
  9898. scalar: pinch ? currentScale : undefined,
  9899. });
  9900. }
  9901. function handleEnd(translation, tapState) {
  9902. resetInertia();
  9903. dispatch('interactionend', {
  9904. ...tapState,
  9905. translation,
  9906. scalar: pinch ? currentScale : undefined,
  9907. });
  9908. }
  9909. return {
  9910. destroy() {
  9911. resetInertia();
  9912. node.removeEventListener('pointerdown', handlePointerdown);
  9913. },
  9914. };
  9915. };
  9916. var nudgeable = (element, options = {}) => {
  9917. // if added as action on non focusable element you should add tabindex=0 attribute
  9918. const { direction = undefined, shiftMultiplier = 10, bubbles = false, stopKeydownPropagation = true, } = options;
  9919. const isHorizontalDirection = direction === 'horizontal';
  9920. const isVerticalDirection = direction === 'vertical';
  9921. const handleKeydown = (e) => {
  9922. const { key } = e;
  9923. const isShift = e.shiftKey;
  9924. const isVerticalAction = /up|down/i.test(key);
  9925. const isHorizontalAction = /left|right/i.test(key);
  9926. // no directional key
  9927. if (!isHorizontalAction && !isVerticalAction)
  9928. return;
  9929. // is horizontal but up or down pressed
  9930. if (isHorizontalDirection && isVerticalAction)
  9931. return;
  9932. // is vertical but left or right pressed
  9933. if (isVerticalDirection && isHorizontalAction)
  9934. return;
  9935. // if holding shift move by a factor 10
  9936. const multiplier = isShift ? shiftMultiplier : 1;
  9937. if (stopKeydownPropagation)
  9938. e.stopPropagation();
  9939. element.dispatchEvent(new CustomEvent('nudge', {
  9940. bubbles,
  9941. detail: vectorCreate((/left/i.test(key) ? -1 : /right/i.test(key) ? 1 : 0) * multiplier, (/up/i.test(key) ? -1 : /down/i.test(key) ? 1 : 0) * multiplier),
  9942. }));
  9943. };
  9944. element.addEventListener('keydown', handleKeydown);
  9945. return {
  9946. destroy() {
  9947. element.removeEventListener('keydown', handleKeydown);
  9948. },
  9949. };
  9950. };
  9951. function elastify(translation, dist) {
  9952. return dist * Math.sign(translation) * Math.log10(1 + Math.abs(translation) / dist);
  9953. }
  9954. const elastifyRects = (a, b, dist) => {
  9955. if (!b)
  9956. return rectClone(a);
  9957. const left = a.x + elastify(b.x - a.x, dist);
  9958. const right = a.x + a.width + elastify(b.x + b.width - (a.x + a.width), dist);
  9959. const top = a.y + elastify(b.y - a.y, dist);
  9960. const bottom = a.y + a.height + elastify(b.y + b.height - (a.y + a.height), dist);
  9961. return {
  9962. x: left,
  9963. y: top,
  9964. width: right - left,
  9965. height: bottom - top,
  9966. };
  9967. };
  9968. var unitToPixels = (value, element) => {
  9969. if (!value)
  9970. return;
  9971. if (/em/.test(value))
  9972. return parseInt(value, 10) * 16;
  9973. if (/px/.test(value))
  9974. return parseInt(value, 10);
  9975. };
  9976. var getWheelDelta = (e) => {
  9977. let d = e.detail || 0;
  9978. // @ts-ignore
  9979. const { deltaX, deltaY, wheelDelta, wheelDeltaX, wheelDeltaY } = e;
  9980. // "detect" x axis interaction for MacOS trackpad
  9981. if (isNumber(wheelDeltaX) && Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)) {
  9982. // blink & webkit
  9983. d = wheelDeltaX / -120;
  9984. }
  9985. else if (isNumber(deltaX) && Math.abs(deltaX) > Math.abs(deltaY)) {
  9986. // quantum
  9987. d = deltaX / 20;
  9988. }
  9989. // @ts-ignore
  9990. else if (wheelDelta || wheelDeltaY) {
  9991. // blink & webkit
  9992. d = (wheelDelta || wheelDeltaY) / -120;
  9993. }
  9994. if (!d) {
  9995. // quantum
  9996. d = deltaY / 20;
  9997. }
  9998. return d;
  9999. };
  10000. /* src/core/ui/components/Scrollable.svelte generated by Svelte v3.37.0 */
  10001. function create_fragment$G(ctx) {
  10002. let div1;
  10003. let div0;
  10004. let div1_class_value;
  10005. let nudgeable_action;
  10006. let current;
  10007. let mounted;
  10008. let dispose;
  10009. const default_slot_template = /*#slots*/ ctx[37].default;
  10010. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[36], null);
  10011. return {
  10012. c() {
  10013. div1 = element("div");
  10014. div0 = element("div");
  10015. if (default_slot) default_slot.c();
  10016. attr(div0, "style", /*childStyle*/ ctx[6]);
  10017. attr(div1, "class", div1_class_value = arrayJoin(["PinturaScrollable", /*klass*/ ctx[0]]));
  10018. attr(div1, "style", /*overflowStyle*/ ctx[4]);
  10019. attr(div1, "data-direction", /*scrollDirection*/ ctx[1]);
  10020. attr(div1, "data-state", /*containerState*/ ctx[5]);
  10021. },
  10022. m(target, anchor) {
  10023. insert(target, div1, anchor);
  10024. append(div1, div0);
  10025. if (default_slot) {
  10026. default_slot.m(div0, null);
  10027. }
  10028. /*div1_binding*/ ctx[39](div1);
  10029. current = true;
  10030. if (!mounted) {
  10031. dispose = [
  10032. listen(div0, "interactionstart", /*handleDragStart*/ ctx[9]),
  10033. listen(div0, "interactionupdate", /*handleDragMove*/ ctx[11]),
  10034. listen(div0, "interactionend", /*handleDragEnd*/ ctx[12]),
  10035. listen(div0, "interactionrelease", /*handleDragRelease*/ ctx[10]),
  10036. action_destroyer(interactable.call(null, div0, { inertia: true })),
  10037. listen(div0, "measure", /*measure_handler*/ ctx[38]),
  10038. action_destroyer(measurable.call(null, div0)),
  10039. listen(div1, "wheel", /*handleWheel*/ ctx[14], { passive: false }),
  10040. listen(div1, "scroll", /*handleScroll*/ ctx[16]),
  10041. listen(div1, "focusin", /*handleFocus*/ ctx[15]),
  10042. listen(div1, "nudge", /*handleNudge*/ ctx[17]),
  10043. listen(div1, "measure", /*handleResizeScrollContainer*/ ctx[13]),
  10044. action_destroyer(measurable.call(null, div1, { observePosition: true })),
  10045. action_destroyer(nudgeable_action = nudgeable.call(null, div1, {
  10046. direction: /*scrollDirection*/ ctx[1] === "x"
  10047. ? "horizontal"
  10048. : "vertical",
  10049. stopKeydownPropagation: false
  10050. }))
  10051. ];
  10052. mounted = true;
  10053. }
  10054. },
  10055. p(ctx, dirty) {
  10056. if (default_slot) {
  10057. if (default_slot.p && dirty[1] & /*$$scope*/ 32) {
  10058. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[36], dirty, null, null);
  10059. }
  10060. }
  10061. if (!current || dirty[0] & /*childStyle*/ 64) {
  10062. attr(div0, "style", /*childStyle*/ ctx[6]);
  10063. }
  10064. if (!current || dirty[0] & /*klass*/ 1 && div1_class_value !== (div1_class_value = arrayJoin(["PinturaScrollable", /*klass*/ ctx[0]]))) {
  10065. attr(div1, "class", div1_class_value);
  10066. }
  10067. if (!current || dirty[0] & /*overflowStyle*/ 16) {
  10068. attr(div1, "style", /*overflowStyle*/ ctx[4]);
  10069. }
  10070. if (!current || dirty[0] & /*scrollDirection*/ 2) {
  10071. attr(div1, "data-direction", /*scrollDirection*/ ctx[1]);
  10072. }
  10073. if (!current || dirty[0] & /*containerState*/ 32) {
  10074. attr(div1, "data-state", /*containerState*/ ctx[5]);
  10075. }
  10076. if (nudgeable_action && is_function(nudgeable_action.update) && dirty[0] & /*scrollDirection*/ 2) nudgeable_action.update.call(null, {
  10077. direction: /*scrollDirection*/ ctx[1] === "x"
  10078. ? "horizontal"
  10079. : "vertical",
  10080. stopKeydownPropagation: false
  10081. });
  10082. },
  10083. i(local) {
  10084. if (current) return;
  10085. transition_in(default_slot, local);
  10086. current = true;
  10087. },
  10088. o(local) {
  10089. transition_out(default_slot, local);
  10090. current = false;
  10091. },
  10092. d(detaching) {
  10093. if (detaching) detach(div1);
  10094. if (default_slot) default_slot.d(detaching);
  10095. /*div1_binding*/ ctx[39](null);
  10096. mounted = false;
  10097. run_all(dispose);
  10098. }
  10099. };
  10100. }
  10101. function instance$G($$self, $$props, $$invalidate) {
  10102. let size;
  10103. let axis;
  10104. let containerStyle;
  10105. let containerFeatherSize;
  10106. let overflows;
  10107. let containerState;
  10108. let childStyle;
  10109. let $scrollOffset;
  10110. let $keysPressedStore;
  10111. let { $$slots: slots = {}, $$scope } = $$props;
  10112. const dispatch = createEventDispatcher();
  10113. const keysPressedStore = getContext("keysPressed");
  10114. component_subscribe($$self, keysPressedStore, value => $$invalidate(46, $keysPressedStore = value));
  10115. let scrollState = "idle";
  10116. let scrollOrigin;
  10117. let scrollRect;
  10118. let scrollContainerRect;
  10119. let scrollReleased;
  10120. let scrollOffset = spring(0);
  10121. component_subscribe($$self, scrollOffset, value => $$invalidate(34, $scrollOffset = value));
  10122. let { class: klass = undefined } = $$props;
  10123. let { scrollBlockInteractionDist = 5 } = $$props;
  10124. let { scrollStep = 10 } = $$props; // the distance multiplier for each mouse scroll interaction (delta)
  10125. let { scrollFocusMargin = 64 } = $$props; // the margin used around elements to decided where to move the focus so elements are positioned into view with some spacing around them, this allows peaking at next/previous elements
  10126. let { scrollDirection = "x" } = $$props;
  10127. let { scrollAutoCancel = false } = $$props;
  10128. let { elasticity = 0 } = $$props;
  10129. let { onscroll = noop$1 } = $$props;
  10130. let { maskFeatherSize = undefined } = $$props;
  10131. let { maskFeatherStartOpacity = undefined } = $$props;
  10132. let { maskFeatherEndOpacity = undefined } = $$props;
  10133. let { scroll = undefined } = $$props;
  10134. // logic
  10135. let container;
  10136. let overflowStyle = "";
  10137. // is scroll in reset state
  10138. let scrollAtRest = true;
  10139. // triggers onscroll callback
  10140. scrollOffset.subscribe(value => {
  10141. const pos = vectorCreateEmpty();
  10142. pos[scrollDirection] = value;
  10143. onscroll(pos);
  10144. });
  10145. const limitOffsetToContainer = offset => Math.max(Math.min(0, offset), scrollContainerRect[size] - scrollRect[size]);
  10146. let scrollFirstMove;
  10147. let scrollCancelled;
  10148. let scrollTranslationPrev;
  10149. const isHorizontalTranslation = translation => {
  10150. const velocity = vectorApply(vectorCreate(translation.x - scrollTranslationPrev.x, translation.y - scrollTranslationPrev.y), Math.abs);
  10151. scrollTranslationPrev = vectorClone(translation);
  10152. const speed = vectorDistanceSquared(velocity);
  10153. const diff = velocity.x - velocity.y;
  10154. return !(speed > 1 && diff < -0.5);
  10155. };
  10156. const handleDragStart = () => {
  10157. // not overflowing so no need to handle
  10158. if (!overflows) return;
  10159. scrollCancelled = false;
  10160. scrollFirstMove = true;
  10161. scrollTranslationPrev = vectorCreate(0, 0);
  10162. scrollReleased = false;
  10163. $$invalidate(28, scrollState = "idle");
  10164. scrollOrigin = get_store_value(scrollOffset);
  10165. };
  10166. const handleDragRelease = ({ detail }) => {
  10167. if (!overflows) return;
  10168. scrollReleased = true;
  10169. $$invalidate(28, scrollState = "idle");
  10170. };
  10171. const handleDragMove = ({ detail }) => {
  10172. if (!overflows) return;
  10173. if (scrollCancelled) return;
  10174. // fixes problem with single move event fired when clicking
  10175. if (scrollFirstMove) {
  10176. scrollFirstMove = false;
  10177. if (vectorDistanceSquared(detail.translation) < 0.1) return;
  10178. }
  10179. if (scrollAutoCancel && scrollDirection === "x" && !isHorizontalTranslation(detail.translation)) {
  10180. scrollCancelled = true;
  10181. return;
  10182. }
  10183. setScrollOffset(scrollOrigin + detail.translation[scrollDirection], { elastic: true });
  10184. };
  10185. const handleDragEnd = ({ detail }) => {
  10186. if (!overflows) return;
  10187. if (scrollCancelled) return;
  10188. const offset = scrollOrigin + detail.translation[scrollDirection];
  10189. const offsetLimited = limitOffsetToContainer(offset);
  10190. scrollAtRest = false;
  10191. scrollOffset.set(offsetLimited).then(res => {
  10192. if (!scrollReleased) return;
  10193. scrollAtRest = true;
  10194. });
  10195. };
  10196. const handleResizeScrollContainer = ({ detail }) => {
  10197. $$invalidate(29, scrollContainerRect = detail);
  10198. dispatch("measure", {
  10199. x: detail.x,
  10200. y: detail.y,
  10201. width: detail.width,
  10202. height: detail.height
  10203. });
  10204. };
  10205. const setScrollOffset = (offset, options = {}) => {
  10206. const { elastic = false, animate = false } = options;
  10207. // prevents clicks on child elements if the container is being scrolled
  10208. if (Math.abs(offset) > scrollBlockInteractionDist && scrollState === "idle" && !scrollReleased) {
  10209. $$invalidate(28, scrollState = "scrolling");
  10210. }
  10211. const offsetLimited = limitOffsetToContainer(offset);
  10212. const offsetVisual = elastic && elasticity && !scrollReleased
  10213. ? offsetLimited + elastify(offset - offsetLimited, elasticity)
  10214. : offsetLimited;
  10215. let snapToPosition = true;
  10216. if (animate) {
  10217. snapToPosition = false;
  10218. } else if (!scrollAtRest) {
  10219. snapToPosition = !scrollReleased;
  10220. }
  10221. scrollAtRest = false;
  10222. scrollOffset.set(offsetVisual, { hard: snapToPosition }).then(res => {
  10223. if (!scrollReleased) return;
  10224. scrollAtRest = true;
  10225. });
  10226. };
  10227. const handleWheel = e => {
  10228. // don't do anything if isn't overflowing
  10229. if (!overflows) return;
  10230. // scroll down -> move to right/down
  10231. // scroll up -> move to left/up
  10232. // don't run default actions, prevent other actions from running
  10233. e.preventDefault();
  10234. e.stopPropagation();
  10235. // apply wheel delta to offset
  10236. const delta = getWheelDelta(e);
  10237. const offset = get_store_value(scrollOffset);
  10238. setScrollOffset(offset + delta * scrollStep, { animate: true });
  10239. };
  10240. const handleFocus = e => {
  10241. // don't do anything if isn't overflowing
  10242. if (!overflows) return;
  10243. // ignore this handler if is dragging
  10244. if (!scrollReleased && !$keysPressedStore.length) return;
  10245. let target = e.target;
  10246. // when a target is marked as implicit we use its parent elemetn
  10247. if (e.target.classList.contains("implicit")) target = target.parentNode;
  10248. // get bounds
  10249. const start = target[scrollDirection === "x" ? "offsetLeft" : "offsetTop"]; //.offsetLeft;
  10250. const space = target[scrollDirection === "x" ? "offsetWidth" : "offsetHeight"]; //.offsetWidth;
  10251. const end = start + space;
  10252. // we need to know the current offset of the scroll so we can determine if the target is in view
  10253. const currentScrollOffset = get_store_value(scrollOffset);
  10254. // the margin around elements to keep in mind when focussing items
  10255. const margin = scrollFocusMargin + maskFeatherSize;
  10256. if (currentScrollOffset + start < margin) {
  10257. setScrollOffset(-start + margin);
  10258. } else if (currentScrollOffset + end > scrollContainerRect[size] - margin) {
  10259. setScrollOffset(scrollContainerRect[size] - end - margin, { animate: true });
  10260. }
  10261. };
  10262. const handleScroll = () => {
  10263. // the scroll handler corrects auto browser scroll,
  10264. // is triggered when browser tries to focus an
  10265. // element outside of the scrollcontiner
  10266. $$invalidate(3, container[scrollDirection === "x" ? "scrollLeft" : "scrollTop"] = 0, container);
  10267. };
  10268. const handleNudge = ({ detail }) => {
  10269. const delta = -2 * detail[scrollDirection];
  10270. const offset = get_store_value(scrollOffset);
  10271. setScrollOffset(offset + delta * scrollStep, { animate: true });
  10272. };
  10273. const measure_handler = e => $$invalidate(2, scrollRect = e.detail);
  10274. function div1_binding($$value) {
  10275. binding_callbacks[$$value ? "unshift" : "push"](() => {
  10276. container = $$value;
  10277. $$invalidate(3, container);
  10278. });
  10279. }
  10280. $$self.$$set = $$props => {
  10281. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  10282. if ("scrollBlockInteractionDist" in $$props) $$invalidate(21, scrollBlockInteractionDist = $$props.scrollBlockInteractionDist);
  10283. if ("scrollStep" in $$props) $$invalidate(22, scrollStep = $$props.scrollStep);
  10284. if ("scrollFocusMargin" in $$props) $$invalidate(23, scrollFocusMargin = $$props.scrollFocusMargin);
  10285. if ("scrollDirection" in $$props) $$invalidate(1, scrollDirection = $$props.scrollDirection);
  10286. if ("scrollAutoCancel" in $$props) $$invalidate(24, scrollAutoCancel = $$props.scrollAutoCancel);
  10287. if ("elasticity" in $$props) $$invalidate(25, elasticity = $$props.elasticity);
  10288. if ("onscroll" in $$props) $$invalidate(26, onscroll = $$props.onscroll);
  10289. if ("maskFeatherSize" in $$props) $$invalidate(20, maskFeatherSize = $$props.maskFeatherSize);
  10290. if ("maskFeatherStartOpacity" in $$props) $$invalidate(18, maskFeatherStartOpacity = $$props.maskFeatherStartOpacity);
  10291. if ("maskFeatherEndOpacity" in $$props) $$invalidate(19, maskFeatherEndOpacity = $$props.maskFeatherEndOpacity);
  10292. if ("scroll" in $$props) $$invalidate(27, scroll = $$props.scroll);
  10293. if ("$$scope" in $$props) $$invalidate(36, $$scope = $$props.$$scope);
  10294. };
  10295. $$self.$$.update = () => {
  10296. if ($$self.$$.dirty[0] & /*scrollDirection*/ 2) {
  10297. $$invalidate(30, size = scrollDirection === "x" ? "width" : "height");
  10298. }
  10299. if ($$self.$$.dirty[0] & /*scrollDirection*/ 2) {
  10300. $$invalidate(31, axis = scrollDirection.toUpperCase());
  10301. }
  10302. if ($$self.$$.dirty[0] & /*container*/ 8) {
  10303. $$invalidate(32, containerStyle = container && getComputedStyle(container));
  10304. }
  10305. if ($$self.$$.dirty[0] & /*container*/ 8 | $$self.$$.dirty[1] & /*containerStyle*/ 2) {
  10306. $$invalidate(33, containerFeatherSize = containerStyle && unitToPixels(containerStyle.getPropertyValue("--scrollable-feather-size")));
  10307. }
  10308. if ($$self.$$.dirty[0] & /*scrollContainerRect, scrollRect, size, maskFeatherStartOpacity, maskFeatherEndOpacity*/ 1611399172 | $$self.$$.dirty[1] & /*$scrollOffset, containerFeatherSize*/ 12) {
  10309. if ($scrollOffset != null && scrollContainerRect && containerFeatherSize != null && scrollRect) {
  10310. const startOffset = -1 * $scrollOffset / containerFeatherSize;
  10311. const endOffset = -(scrollContainerRect[size] - scrollRect[size] - $scrollOffset) / containerFeatherSize;
  10312. $$invalidate(18, maskFeatherStartOpacity = clamp(1 - startOffset, 0, 1));
  10313. $$invalidate(19, maskFeatherEndOpacity = clamp(1 - endOffset, 0, 1));
  10314. $$invalidate(20, maskFeatherSize = containerFeatherSize);
  10315. $$invalidate(4, overflowStyle = `--scrollable-feather-start-opacity: ${maskFeatherStartOpacity};--scrollable-feather-end-opacity: ${maskFeatherEndOpacity}`);
  10316. }
  10317. }
  10318. if ($$self.$$.dirty[0] & /*container, scroll*/ 134217736) {
  10319. // update scroll position
  10320. if (container && scroll !== undefined) {
  10321. if (isNumber(scroll)) setScrollOffset(scroll); else setScrollOffset(scroll.scrollOffset, scroll);
  10322. }
  10323. }
  10324. if ($$self.$$.dirty[0] & /*scrollContainerRect, scrollRect, size*/ 1610612740) {
  10325. $$invalidate(35, overflows = scrollContainerRect && scrollRect
  10326. ? scrollRect[size] > scrollContainerRect[size]
  10327. : undefined);
  10328. }
  10329. if ($$self.$$.dirty[0] & /*scrollState*/ 268435456 | $$self.$$.dirty[1] & /*overflows*/ 16) {
  10330. $$invalidate(5, containerState = arrayJoin([scrollState, overflows ? "overflows" : undefined]));
  10331. }
  10332. if ($$self.$$.dirty[1] & /*overflows, axis, $scrollOffset*/ 25) {
  10333. $$invalidate(6, childStyle = overflows
  10334. ? `transform: translate${axis}(${$scrollOffset}px)`
  10335. : undefined);
  10336. }
  10337. };
  10338. return [
  10339. klass,
  10340. scrollDirection,
  10341. scrollRect,
  10342. container,
  10343. overflowStyle,
  10344. containerState,
  10345. childStyle,
  10346. keysPressedStore,
  10347. scrollOffset,
  10348. handleDragStart,
  10349. handleDragRelease,
  10350. handleDragMove,
  10351. handleDragEnd,
  10352. handleResizeScrollContainer,
  10353. handleWheel,
  10354. handleFocus,
  10355. handleScroll,
  10356. handleNudge,
  10357. maskFeatherStartOpacity,
  10358. maskFeatherEndOpacity,
  10359. maskFeatherSize,
  10360. scrollBlockInteractionDist,
  10361. scrollStep,
  10362. scrollFocusMargin,
  10363. scrollAutoCancel,
  10364. elasticity,
  10365. onscroll,
  10366. scroll,
  10367. scrollState,
  10368. scrollContainerRect,
  10369. size,
  10370. axis,
  10371. containerStyle,
  10372. containerFeatherSize,
  10373. $scrollOffset,
  10374. overflows,
  10375. $$scope,
  10376. slots,
  10377. measure_handler,
  10378. div1_binding
  10379. ];
  10380. }
  10381. class Scrollable extends SvelteComponent {
  10382. constructor(options) {
  10383. super();
  10384. init(
  10385. this,
  10386. options,
  10387. instance$G,
  10388. create_fragment$G,
  10389. safe_not_equal,
  10390. {
  10391. class: 0,
  10392. scrollBlockInteractionDist: 21,
  10393. scrollStep: 22,
  10394. scrollFocusMargin: 23,
  10395. scrollDirection: 1,
  10396. scrollAutoCancel: 24,
  10397. elasticity: 25,
  10398. onscroll: 26,
  10399. maskFeatherSize: 20,
  10400. maskFeatherStartOpacity: 18,
  10401. maskFeatherEndOpacity: 19,
  10402. scroll: 27
  10403. },
  10404. [-1, -1]
  10405. );
  10406. }
  10407. }
  10408. function fade$1(node, { delay = 0, duration = 400, easing = identity } = {}) {
  10409. const o = +getComputedStyle(node).opacity;
  10410. return {
  10411. delay,
  10412. duration,
  10413. easing,
  10414. css: t => `opacity: ${t * o}`
  10415. };
  10416. }
  10417. /* src/core/ui/components/StatusMessage.svelte generated by Svelte v3.37.0 */
  10418. function create_fragment$F(ctx) {
  10419. let span;
  10420. let t;
  10421. let span_transition;
  10422. let current;
  10423. let mounted;
  10424. let dispose;
  10425. return {
  10426. c() {
  10427. span = element("span");
  10428. t = text(/*text*/ ctx[0]);
  10429. attr(span, "class", "PinturaStatusMessage");
  10430. },
  10431. m(target, anchor) {
  10432. insert(target, span, anchor);
  10433. append(span, t);
  10434. current = true;
  10435. if (!mounted) {
  10436. dispose = [
  10437. listen(span, "measure", function () {
  10438. if (is_function(/*onmeasure*/ ctx[1])) /*onmeasure*/ ctx[1].apply(this, arguments);
  10439. }),
  10440. action_destroyer(measurable.call(null, span))
  10441. ];
  10442. mounted = true;
  10443. }
  10444. },
  10445. p(new_ctx, [dirty]) {
  10446. ctx = new_ctx;
  10447. if (!current || dirty & /*text*/ 1) set_data(t, /*text*/ ctx[0]);
  10448. },
  10449. i(local) {
  10450. if (current) return;
  10451. add_render_callback(() => {
  10452. if (!span_transition) span_transition = create_bidirectional_transition(span, fade$1, {}, true);
  10453. span_transition.run(1);
  10454. });
  10455. current = true;
  10456. },
  10457. o(local) {
  10458. if (!span_transition) span_transition = create_bidirectional_transition(span, fade$1, {}, false);
  10459. span_transition.run(0);
  10460. current = false;
  10461. },
  10462. d(detaching) {
  10463. if (detaching) detach(span);
  10464. if (detaching && span_transition) span_transition.end();
  10465. mounted = false;
  10466. run_all(dispose);
  10467. }
  10468. };
  10469. }
  10470. function instance$F($$self, $$props, $$invalidate) {
  10471. let { text } = $$props;
  10472. let { onmeasure = noop$1 } = $$props;
  10473. $$self.$$set = $$props => {
  10474. if ("text" in $$props) $$invalidate(0, text = $$props.text);
  10475. if ("onmeasure" in $$props) $$invalidate(1, onmeasure = $$props.onmeasure);
  10476. };
  10477. return [text, onmeasure];
  10478. }
  10479. class StatusMessage extends SvelteComponent {
  10480. constructor(options) {
  10481. super();
  10482. init(this, options, instance$F, create_fragment$F, safe_not_equal, { text: 0, onmeasure: 1 });
  10483. }
  10484. }
  10485. /* src/core/ui/components/ProgressIndicator.svelte generated by Svelte v3.37.0 */
  10486. function create_fragment$E(ctx) {
  10487. let span1;
  10488. let svg;
  10489. let g;
  10490. let circle0;
  10491. let circle1;
  10492. let t0;
  10493. let span0;
  10494. let t1;
  10495. return {
  10496. c() {
  10497. span1 = element("span");
  10498. svg = svg_element("svg");
  10499. g = svg_element("g");
  10500. circle0 = svg_element("circle");
  10501. circle1 = svg_element("circle");
  10502. t0 = space();
  10503. span0 = element("span");
  10504. t1 = text(/*formattedValue*/ ctx[0]);
  10505. attr(circle0, "class", "PinturaProgressIndicatorBar");
  10506. attr(circle0, "r", "8.5");
  10507. attr(circle0, "cx", "10");
  10508. attr(circle0, "cy", "10");
  10509. attr(circle0, "stroke-linecap", "round");
  10510. attr(circle0, "opacity", ".25");
  10511. attr(circle1, "class", "PinturaProgressIndicatorFill");
  10512. attr(circle1, "r", "8.5");
  10513. attr(circle1, "stroke-dasharray", /*circleValue*/ ctx[1]);
  10514. attr(circle1, "cx", "10");
  10515. attr(circle1, "cy", "10");
  10516. attr(circle1, "transform", "rotate(-90) translate(-20)");
  10517. attr(g, "fill", "none");
  10518. attr(g, "stroke", "currentColor");
  10519. attr(g, "stroke-width", "2.5");
  10520. attr(g, "stroke-linecap", "round");
  10521. attr(g, "opacity", /*circleOpacity*/ ctx[2]);
  10522. attr(svg, "width", "20");
  10523. attr(svg, "height", "20");
  10524. attr(svg, "viewBox", "0 0 20 20");
  10525. attr(svg, "xmlns", "http://www.w3.org/2000/svg");
  10526. attr(svg, "aria-hidden", "true");
  10527. attr(svg, "focusable", "false");
  10528. attr(span0, "class", "implicit");
  10529. attr(span1, "class", "PinturaProgressIndicator");
  10530. attr(span1, "data-status", /*status*/ ctx[3]);
  10531. },
  10532. m(target, anchor) {
  10533. insert(target, span1, anchor);
  10534. append(span1, svg);
  10535. append(svg, g);
  10536. append(g, circle0);
  10537. append(g, circle1);
  10538. append(span1, t0);
  10539. append(span1, span0);
  10540. append(span0, t1);
  10541. },
  10542. p(ctx, [dirty]) {
  10543. if (dirty & /*circleValue*/ 2) {
  10544. attr(circle1, "stroke-dasharray", /*circleValue*/ ctx[1]);
  10545. }
  10546. if (dirty & /*circleOpacity*/ 4) {
  10547. attr(g, "opacity", /*circleOpacity*/ ctx[2]);
  10548. }
  10549. if (dirty & /*formattedValue*/ 1) set_data(t1, /*formattedValue*/ ctx[0]);
  10550. if (dirty & /*status*/ 8) {
  10551. attr(span1, "data-status", /*status*/ ctx[3]);
  10552. }
  10553. },
  10554. i: noop,
  10555. o: noop,
  10556. d(detaching) {
  10557. if (detaching) detach(span1);
  10558. }
  10559. };
  10560. }
  10561. function instance$E($$self, $$props, $$invalidate) {
  10562. let formattedValue;
  10563. let circleValue;
  10564. let circleOpacity;
  10565. let status;
  10566. let $animatedProgressClamped;
  10567. const dispatch = createEventDispatcher();
  10568. let { progress } = $$props;
  10569. let { min = 0 } = $$props;
  10570. let { max = 100 } = $$props;
  10571. let { labelBusy = "Busy" } = $$props;
  10572. const animatedValue = spring(0, { precision: 0.01 });
  10573. const animatedProgressClamped = derived([animatedValue], $animatedValue => clamp($animatedValue, min, max));
  10574. component_subscribe($$self, animatedProgressClamped, value => $$invalidate(9, $animatedProgressClamped = value));
  10575. animatedProgressClamped.subscribe(value => {
  10576. if (progress === 1 && Math.round(value) >= 100) dispatch("complete");
  10577. });
  10578. $$self.$$set = $$props => {
  10579. if ("progress" in $$props) $$invalidate(5, progress = $$props.progress);
  10580. if ("min" in $$props) $$invalidate(6, min = $$props.min);
  10581. if ("max" in $$props) $$invalidate(7, max = $$props.max);
  10582. if ("labelBusy" in $$props) $$invalidate(8, labelBusy = $$props.labelBusy);
  10583. };
  10584. $$self.$$.update = () => {
  10585. if ($$self.$$.dirty & /*progress*/ 32) {
  10586. progress && progress !== Infinity && animatedValue.set(progress * 100);
  10587. }
  10588. if ($$self.$$.dirty & /*progress, labelBusy, $animatedProgressClamped*/ 800) {
  10589. $$invalidate(0, formattedValue = progress === Infinity
  10590. ? labelBusy
  10591. : `${Math.round($animatedProgressClamped)}%`);
  10592. }
  10593. if ($$self.$$.dirty & /*progress, $animatedProgressClamped*/ 544) {
  10594. $$invalidate(1, circleValue = progress === Infinity
  10595. ? "26.5 53"
  10596. : `${$animatedProgressClamped / 100 * 53} 53`);
  10597. }
  10598. if ($$self.$$.dirty & /*progress, $animatedProgressClamped*/ 544) {
  10599. $$invalidate(2, circleOpacity = Math.min(1, progress === Infinity
  10600. ? 1
  10601. : $animatedProgressClamped / 10));
  10602. }
  10603. if ($$self.$$.dirty & /*progress*/ 32) {
  10604. $$invalidate(3, status = progress === Infinity ? "busy" : "loading");
  10605. }
  10606. };
  10607. return [
  10608. formattedValue,
  10609. circleValue,
  10610. circleOpacity,
  10611. status,
  10612. animatedProgressClamped,
  10613. progress,
  10614. min,
  10615. max,
  10616. labelBusy,
  10617. $animatedProgressClamped
  10618. ];
  10619. }
  10620. class ProgressIndicator extends SvelteComponent {
  10621. constructor(options) {
  10622. super();
  10623. init(this, options, instance$E, create_fragment$E, safe_not_equal, {
  10624. progress: 5,
  10625. min: 6,
  10626. max: 7,
  10627. labelBusy: 8
  10628. });
  10629. }
  10630. }
  10631. /* src/core/ui/components/StatusAside.svelte generated by Svelte v3.37.0 */
  10632. function create_fragment$D(ctx) {
  10633. let span;
  10634. let span_class_value;
  10635. let current;
  10636. const default_slot_template = /*#slots*/ ctx[5].default;
  10637. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[4], null);
  10638. return {
  10639. c() {
  10640. span = element("span");
  10641. if (default_slot) default_slot.c();
  10642. attr(span, "class", span_class_value = `PinturaStatusAside ${/*klass*/ ctx[0]}`);
  10643. attr(span, "style", /*style*/ ctx[1]);
  10644. },
  10645. m(target, anchor) {
  10646. insert(target, span, anchor);
  10647. if (default_slot) {
  10648. default_slot.m(span, null);
  10649. }
  10650. current = true;
  10651. },
  10652. p(ctx, [dirty]) {
  10653. if (default_slot) {
  10654. if (default_slot.p && dirty & /*$$scope*/ 16) {
  10655. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[4], dirty, null, null);
  10656. }
  10657. }
  10658. if (!current || dirty & /*klass*/ 1 && span_class_value !== (span_class_value = `PinturaStatusAside ${/*klass*/ ctx[0]}`)) {
  10659. attr(span, "class", span_class_value);
  10660. }
  10661. if (!current || dirty & /*style*/ 2) {
  10662. attr(span, "style", /*style*/ ctx[1]);
  10663. }
  10664. },
  10665. i(local) {
  10666. if (current) return;
  10667. transition_in(default_slot, local);
  10668. current = true;
  10669. },
  10670. o(local) {
  10671. transition_out(default_slot, local);
  10672. current = false;
  10673. },
  10674. d(detaching) {
  10675. if (detaching) detach(span);
  10676. if (default_slot) default_slot.d(detaching);
  10677. }
  10678. };
  10679. }
  10680. function instance$D($$self, $$props, $$invalidate) {
  10681. let style;
  10682. let { $$slots: slots = {}, $$scope } = $$props;
  10683. let { offset = 0 } = $$props;
  10684. let { opacity = 0 } = $$props;
  10685. let { class: klass = undefined } = $$props;
  10686. $$self.$$set = $$props => {
  10687. if ("offset" in $$props) $$invalidate(2, offset = $$props.offset);
  10688. if ("opacity" in $$props) $$invalidate(3, opacity = $$props.opacity);
  10689. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  10690. if ("$$scope" in $$props) $$invalidate(4, $$scope = $$props.$$scope);
  10691. };
  10692. $$self.$$.update = () => {
  10693. if ($$self.$$.dirty & /*offset, opacity*/ 12) {
  10694. $$invalidate(1, style = `transform:translateX(${offset}px);opacity:${opacity}`);
  10695. }
  10696. };
  10697. return [klass, style, offset, opacity, $$scope, slots];
  10698. }
  10699. class StatusAside extends SvelteComponent {
  10700. constructor(options) {
  10701. super();
  10702. init(this, options, instance$D, create_fragment$D, safe_not_equal, { offset: 2, opacity: 3, class: 0 });
  10703. }
  10704. }
  10705. /* src/core/ui/components/Tag.svelte generated by Svelte v3.37.0 */
  10706. function create_if_block_2$9(ctx) {
  10707. let label;
  10708. let label_for_value;
  10709. let current;
  10710. const default_slot_template = /*#slots*/ ctx[3].default;
  10711. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[2], null);
  10712. let label_levels = [{ for: label_for_value = "_" }, /*attributes*/ ctx[1]];
  10713. let label_data = {};
  10714. for (let i = 0; i < label_levels.length; i += 1) {
  10715. label_data = assign(label_data, label_levels[i]);
  10716. }
  10717. return {
  10718. c() {
  10719. label = element("label");
  10720. if (default_slot) default_slot.c();
  10721. set_attributes(label, label_data);
  10722. },
  10723. m(target, anchor) {
  10724. insert(target, label, anchor);
  10725. if (default_slot) {
  10726. default_slot.m(label, null);
  10727. }
  10728. current = true;
  10729. },
  10730. p(ctx, dirty) {
  10731. if (default_slot) {
  10732. if (default_slot.p && dirty & /*$$scope*/ 4) {
  10733. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[2], dirty, null, null);
  10734. }
  10735. }
  10736. set_attributes(label, label_data = get_spread_update(label_levels, [
  10737. { for: label_for_value },
  10738. dirty & /*attributes*/ 2 && /*attributes*/ ctx[1]
  10739. ]));
  10740. },
  10741. i(local) {
  10742. if (current) return;
  10743. transition_in(default_slot, local);
  10744. current = true;
  10745. },
  10746. o(local) {
  10747. transition_out(default_slot, local);
  10748. current = false;
  10749. },
  10750. d(detaching) {
  10751. if (detaching) detach(label);
  10752. if (default_slot) default_slot.d(detaching);
  10753. }
  10754. };
  10755. }
  10756. // (12:26)
  10757. function create_if_block_1$c(ctx) {
  10758. let div;
  10759. let current;
  10760. const default_slot_template = /*#slots*/ ctx[3].default;
  10761. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[2], null);
  10762. let div_levels = [/*attributes*/ ctx[1]];
  10763. let div_data = {};
  10764. for (let i = 0; i < div_levels.length; i += 1) {
  10765. div_data = assign(div_data, div_levels[i]);
  10766. }
  10767. return {
  10768. c() {
  10769. div = element("div");
  10770. if (default_slot) default_slot.c();
  10771. set_attributes(div, div_data);
  10772. },
  10773. m(target, anchor) {
  10774. insert(target, div, anchor);
  10775. if (default_slot) {
  10776. default_slot.m(div, null);
  10777. }
  10778. current = true;
  10779. },
  10780. p(ctx, dirty) {
  10781. if (default_slot) {
  10782. if (default_slot.p && dirty & /*$$scope*/ 4) {
  10783. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[2], dirty, null, null);
  10784. }
  10785. }
  10786. set_attributes(div, div_data = get_spread_update(div_levels, [dirty & /*attributes*/ 2 && /*attributes*/ ctx[1]]));
  10787. },
  10788. i(local) {
  10789. if (current) return;
  10790. transition_in(default_slot, local);
  10791. current = true;
  10792. },
  10793. o(local) {
  10794. transition_out(default_slot, local);
  10795. current = false;
  10796. },
  10797. d(detaching) {
  10798. if (detaching) detach(div);
  10799. if (default_slot) default_slot.d(detaching);
  10800. }
  10801. };
  10802. }
  10803. // (8:0) {#if name === 'div'}
  10804. function create_if_block$b(ctx) {
  10805. let div;
  10806. let current;
  10807. const default_slot_template = /*#slots*/ ctx[3].default;
  10808. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[2], null);
  10809. let div_levels = [/*attributes*/ ctx[1]];
  10810. let div_data = {};
  10811. for (let i = 0; i < div_levels.length; i += 1) {
  10812. div_data = assign(div_data, div_levels[i]);
  10813. }
  10814. return {
  10815. c() {
  10816. div = element("div");
  10817. if (default_slot) default_slot.c();
  10818. set_attributes(div, div_data);
  10819. },
  10820. m(target, anchor) {
  10821. insert(target, div, anchor);
  10822. if (default_slot) {
  10823. default_slot.m(div, null);
  10824. }
  10825. current = true;
  10826. },
  10827. p(ctx, dirty) {
  10828. if (default_slot) {
  10829. if (default_slot.p && dirty & /*$$scope*/ 4) {
  10830. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[2], dirty, null, null);
  10831. }
  10832. }
  10833. set_attributes(div, div_data = get_spread_update(div_levels, [dirty & /*attributes*/ 2 && /*attributes*/ ctx[1]]));
  10834. },
  10835. i(local) {
  10836. if (current) return;
  10837. transition_in(default_slot, local);
  10838. current = true;
  10839. },
  10840. o(local) {
  10841. transition_out(default_slot, local);
  10842. current = false;
  10843. },
  10844. d(detaching) {
  10845. if (detaching) detach(div);
  10846. if (default_slot) default_slot.d(detaching);
  10847. }
  10848. };
  10849. }
  10850. function create_fragment$C(ctx) {
  10851. let current_block_type_index;
  10852. let if_block;
  10853. let if_block_anchor;
  10854. let current;
  10855. const if_block_creators = [create_if_block$b, create_if_block_1$c, create_if_block_2$9];
  10856. const if_blocks = [];
  10857. function select_block_type(ctx, dirty) {
  10858. if (/*name*/ ctx[0] === "div") return 0;
  10859. if (/*name*/ ctx[0] === "span") return 1;
  10860. if (/*name*/ ctx[0] === "label") return 2;
  10861. return -1;
  10862. }
  10863. if (~(current_block_type_index = select_block_type(ctx))) {
  10864. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  10865. }
  10866. return {
  10867. c() {
  10868. if (if_block) if_block.c();
  10869. if_block_anchor = empty();
  10870. },
  10871. m(target, anchor) {
  10872. if (~current_block_type_index) {
  10873. if_blocks[current_block_type_index].m(target, anchor);
  10874. }
  10875. insert(target, if_block_anchor, anchor);
  10876. current = true;
  10877. },
  10878. p(ctx, [dirty]) {
  10879. let previous_block_index = current_block_type_index;
  10880. current_block_type_index = select_block_type(ctx);
  10881. if (current_block_type_index === previous_block_index) {
  10882. if (~current_block_type_index) {
  10883. if_blocks[current_block_type_index].p(ctx, dirty);
  10884. }
  10885. } else {
  10886. if (if_block) {
  10887. group_outros();
  10888. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  10889. if_blocks[previous_block_index] = null;
  10890. });
  10891. check_outros();
  10892. }
  10893. if (~current_block_type_index) {
  10894. if_block = if_blocks[current_block_type_index];
  10895. if (!if_block) {
  10896. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  10897. if_block.c();
  10898. } else {
  10899. if_block.p(ctx, dirty);
  10900. }
  10901. transition_in(if_block, 1);
  10902. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  10903. } else {
  10904. if_block = null;
  10905. }
  10906. }
  10907. },
  10908. i(local) {
  10909. if (current) return;
  10910. transition_in(if_block);
  10911. current = true;
  10912. },
  10913. o(local) {
  10914. transition_out(if_block);
  10915. current = false;
  10916. },
  10917. d(detaching) {
  10918. if (~current_block_type_index) {
  10919. if_blocks[current_block_type_index].d(detaching);
  10920. }
  10921. if (detaching) detach(if_block_anchor);
  10922. }
  10923. };
  10924. }
  10925. function instance$C($$self, $$props, $$invalidate) {
  10926. let { $$slots: slots = {}, $$scope } = $$props;
  10927. let { name = "div" } = $$props;
  10928. let { attributes = {} } = $$props;
  10929. $$self.$$set = $$props => {
  10930. if ("name" in $$props) $$invalidate(0, name = $$props.name);
  10931. if ("attributes" in $$props) $$invalidate(1, attributes = $$props.attributes);
  10932. if ("$$scope" in $$props) $$invalidate(2, $$scope = $$props.$$scope);
  10933. };
  10934. return [name, attributes, $$scope, slots];
  10935. }
  10936. class Tag extends SvelteComponent {
  10937. constructor(options) {
  10938. super();
  10939. init(this, options, instance$C, create_fragment$C, safe_not_equal, { name: 0, attributes: 1 });
  10940. }
  10941. }
  10942. var getDevicePixelRatio = () => (isBrowser() && window.devicePixelRatio) || 1;
  10943. // if this is a non retina display snap to pixel
  10944. let fn = null;
  10945. var snapToPixel = (v) => {
  10946. if (fn === null)
  10947. fn = getDevicePixelRatio() === 1 ? (v) => Math.round(v) : (v) => v;
  10948. return fn(v);
  10949. };
  10950. /* src/core/ui/components/Details.svelte generated by Svelte v3.37.0 */
  10951. const get_details_slot_changes = dirty => ({});
  10952. const get_details_slot_context = ctx => ({});
  10953. const get_label_slot_changes = dirty => ({});
  10954. const get_label_slot_context = ctx => ({});
  10955. // (177:0) <Button bind:this={buttonComponent} class={arrayJoin(['PinturaDetailsButton', buttonClass])} onkeydown={handleButtonKeydown} onclick={handleClick} >
  10956. function create_default_slot$g(ctx) {
  10957. let current;
  10958. const label_slot_template = /*#slots*/ ctx[35].label;
  10959. const label_slot = create_slot(label_slot_template, ctx, /*$$scope*/ ctx[39], get_label_slot_context);
  10960. return {
  10961. c() {
  10962. if (label_slot) label_slot.c();
  10963. },
  10964. m(target, anchor) {
  10965. if (label_slot) {
  10966. label_slot.m(target, anchor);
  10967. }
  10968. current = true;
  10969. },
  10970. p(ctx, dirty) {
  10971. if (label_slot) {
  10972. if (label_slot.p && dirty[1] & /*$$scope*/ 256) {
  10973. update_slot(label_slot, label_slot_template, ctx, /*$$scope*/ ctx[39], dirty, get_label_slot_changes, get_label_slot_context);
  10974. }
  10975. }
  10976. },
  10977. i(local) {
  10978. if (current) return;
  10979. transition_in(label_slot, local);
  10980. current = true;
  10981. },
  10982. o(local) {
  10983. transition_out(label_slot, local);
  10984. current = false;
  10985. },
  10986. d(detaching) {
  10987. if (label_slot) label_slot.d(detaching);
  10988. }
  10989. };
  10990. }
  10991. // (186:0) {#if isVisible}
  10992. function create_if_block_1$b(ctx) {
  10993. let div;
  10994. let t;
  10995. let span;
  10996. let div_class_value;
  10997. let current;
  10998. let mounted;
  10999. let dispose;
  11000. const details_slot_template = /*#slots*/ ctx[35].details;
  11001. const details_slot = create_slot(details_slot_template, ctx, /*$$scope*/ ctx[39], get_details_slot_context);
  11002. return {
  11003. c() {
  11004. div = element("div");
  11005. if (details_slot) details_slot.c();
  11006. t = space();
  11007. span = element("span");
  11008. attr(span, "class", "PinturaDetailsPanelTip");
  11009. attr(span, "style", /*tipStyle*/ ctx[7]);
  11010. attr(div, "class", div_class_value = arrayJoin(["PinturaDetailsPanel", /*panelClass*/ ctx[1]]));
  11011. attr(div, "tabindex", "-1");
  11012. attr(div, "style", /*style*/ ctx[6]);
  11013. },
  11014. m(target, anchor) {
  11015. insert(target, div, anchor);
  11016. if (details_slot) {
  11017. details_slot.m(div, null);
  11018. }
  11019. append(div, t);
  11020. append(div, span);
  11021. /*div_binding*/ ctx[37](div);
  11022. current = true;
  11023. if (!mounted) {
  11024. dispose = [
  11025. listen(div, "keydown", /*handlePanelKeydown*/ ctx[17]),
  11026. listen(div, "measure", /*measure_handler*/ ctx[38]),
  11027. action_destroyer(measurable.call(null, div))
  11028. ];
  11029. mounted = true;
  11030. }
  11031. },
  11032. p(ctx, dirty) {
  11033. if (details_slot) {
  11034. if (details_slot.p && dirty[1] & /*$$scope*/ 256) {
  11035. update_slot(details_slot, details_slot_template, ctx, /*$$scope*/ ctx[39], dirty, get_details_slot_changes, get_details_slot_context);
  11036. }
  11037. }
  11038. if (!current || dirty[0] & /*tipStyle*/ 128) {
  11039. attr(span, "style", /*tipStyle*/ ctx[7]);
  11040. }
  11041. if (!current || dirty[0] & /*panelClass*/ 2 && div_class_value !== (div_class_value = arrayJoin(["PinturaDetailsPanel", /*panelClass*/ ctx[1]]))) {
  11042. attr(div, "class", div_class_value);
  11043. }
  11044. if (!current || dirty[0] & /*style*/ 64) {
  11045. attr(div, "style", /*style*/ ctx[6]);
  11046. }
  11047. },
  11048. i(local) {
  11049. if (current) return;
  11050. transition_in(details_slot, local);
  11051. current = true;
  11052. },
  11053. o(local) {
  11054. transition_out(details_slot, local);
  11055. current = false;
  11056. },
  11057. d(detaching) {
  11058. if (detaching) detach(div);
  11059. if (details_slot) details_slot.d(detaching);
  11060. /*div_binding*/ ctx[37](null);
  11061. mounted = false;
  11062. run_all(dispose);
  11063. }
  11064. };
  11065. }
  11066. function create_fragment$B(ctx) {
  11067. let t0;
  11068. let button;
  11069. let t1;
  11070. let t2;
  11071. let if_block1_anchor;
  11072. let current;
  11073. let mounted;
  11074. let dispose;
  11075. let button_props = {
  11076. class: arrayJoin(["PinturaDetailsButton", /*buttonClass*/ ctx[0]]),
  11077. onkeydown: /*handleButtonKeydown*/ ctx[16],
  11078. onclick: /*handleClick*/ ctx[15],
  11079. $$slots: { default: [create_default_slot$g] },
  11080. $$scope: { ctx }
  11081. };
  11082. button = new Button({ props: button_props });
  11083. /*button_binding*/ ctx[36](button);
  11084. let if_block0 = /*isVisible*/ ctx[5] && create_if_block_1$b(ctx);
  11085. let if_block1 = false ;
  11086. return {
  11087. c() {
  11088. t0 = space();
  11089. create_component(button.$$.fragment);
  11090. t1 = space();
  11091. if (if_block0) if_block0.c();
  11092. t2 = space();
  11093. if_block1_anchor = empty();
  11094. },
  11095. m(target, anchor) {
  11096. insert(target, t0, anchor);
  11097. mount_component(button, target, anchor);
  11098. insert(target, t1, anchor);
  11099. if (if_block0) if_block0.m(target, anchor);
  11100. insert(target, t2, anchor);
  11101. insert(target, if_block1_anchor, anchor);
  11102. current = true;
  11103. if (!mounted) {
  11104. dispose = [
  11105. listen(document.body, "pointerdown", function () {
  11106. if (is_function(/*handleDown*/ ctx[8])) /*handleDown*/ ctx[8].apply(this, arguments);
  11107. }),
  11108. listen(document.body, "pointerup", function () {
  11109. if (is_function(/*handleUp*/ ctx[9])) /*handleUp*/ ctx[9].apply(this, arguments);
  11110. })
  11111. ];
  11112. mounted = true;
  11113. }
  11114. },
  11115. p(new_ctx, dirty) {
  11116. ctx = new_ctx;
  11117. const button_changes = {};
  11118. if (dirty[0] & /*buttonClass*/ 1) button_changes.class = arrayJoin(["PinturaDetailsButton", /*buttonClass*/ ctx[0]]);
  11119. if (dirty[1] & /*$$scope*/ 256) {
  11120. button_changes.$$scope = { dirty, ctx };
  11121. }
  11122. button.$set(button_changes);
  11123. if (/*isVisible*/ ctx[5]) {
  11124. if (if_block0) {
  11125. if_block0.p(ctx, dirty);
  11126. if (dirty[0] & /*isVisible*/ 32) {
  11127. transition_in(if_block0, 1);
  11128. }
  11129. } else {
  11130. if_block0 = create_if_block_1$b(ctx);
  11131. if_block0.c();
  11132. transition_in(if_block0, 1);
  11133. if_block0.m(t2.parentNode, t2);
  11134. }
  11135. } else if (if_block0) {
  11136. group_outros();
  11137. transition_out(if_block0, 1, 1, () => {
  11138. if_block0 = null;
  11139. });
  11140. check_outros();
  11141. }
  11142. },
  11143. i(local) {
  11144. if (current) return;
  11145. transition_in(button.$$.fragment, local);
  11146. transition_in(if_block0);
  11147. transition_in(if_block1);
  11148. current = true;
  11149. },
  11150. o(local) {
  11151. transition_out(button.$$.fragment, local);
  11152. transition_out(if_block0);
  11153. transition_out(if_block1);
  11154. current = false;
  11155. },
  11156. d(detaching) {
  11157. if (detaching) detach(t0);
  11158. /*button_binding*/ ctx[36](null);
  11159. destroy_component(button, detaching);
  11160. if (detaching) detach(t1);
  11161. if (if_block0) if_block0.d(detaching);
  11162. if (detaching) detach(t2);
  11163. if (detaching) detach(if_block1_anchor);
  11164. mounted = false;
  11165. run_all(dispose);
  11166. }
  11167. };
  11168. }
  11169. let panelMargin = 12;
  11170. function instance$B($$self, $$props, $$invalidate) {
  11171. let buttonElement;
  11172. let offsetProgress;
  11173. let isVisible;
  11174. let isAnimating;
  11175. let transform;
  11176. let style;
  11177. let tipScale;
  11178. let tipOpacity;
  11179. let tipStyle;
  11180. let handleDown;
  11181. let handleUp;
  11182. let $offset;
  11183. let $portalRootRect;
  11184. let $position;
  11185. let $opacity;
  11186. let $portal;
  11187. let { $$slots: slots = {}, $$scope } = $$props;
  11188. let { buttonClass = undefined } = $$props;
  11189. let { panelClass = undefined } = $$props;
  11190. let { isActive = false } = $$props;
  11191. let { onshow = ({ panel }) => panel.focus() } = $$props;
  11192. const portal = getContext("rootPortal");
  11193. component_subscribe($$self, portal, value => $$invalidate(34, $portal = value));
  11194. const portalRootRect = getContext("rootRect");
  11195. component_subscribe($$self, portalRootRect, value => $$invalidate(27, $portalRootRect = value));
  11196. let panelSize;
  11197. let buttonComponent;
  11198. let buttonRect;
  11199. let dir = vectorCreateEmpty();
  11200. let opacity = spring(0);
  11201. component_subscribe($$self, opacity, value => $$invalidate(29, $opacity = value));
  11202. let shift = vectorCreateEmpty();
  11203. const position = writable({ x: 0, y: 0 });
  11204. component_subscribe($$self, position, value => $$invalidate(28, $position = value));
  11205. const offset = spring(-5, {
  11206. stiffness: 0.1,
  11207. damping: 0.35,
  11208. precision: 0.001
  11209. });
  11210. component_subscribe($$self, offset, value => $$invalidate(26, $offset = value));
  11211. const isTargetSelf = e => isEventTarget(e, $portal) || buttonComponent.isEventTarget(e);
  11212. let downOutsidePanel = false;
  11213. // move detail panel to portal
  11214. let detailPanel;
  11215. let trigger;
  11216. // test keydown press to open
  11217. const handleClick = e => {
  11218. if (!isActive) $$invalidate(20, buttonRect = buttonElement.getBoundingClientRect());
  11219. $$invalidate(24, trigger = e);
  11220. $$invalidate(18, isActive = !isActive);
  11221. };
  11222. const handleButtonKeydown = e => {
  11223. if (!(/down/i).test(e.key)) return;
  11224. $$invalidate(18, isActive = true);
  11225. $$invalidate(24, trigger = e);
  11226. };
  11227. const handlePanelKeydown = e => {
  11228. if (!(/esc/i).test(e.key)) return;
  11229. $$invalidate(18, isActive = false);
  11230. buttonElement.focus();
  11231. };
  11232. // clean up panel if it was appended to a portal
  11233. onDestroy(() => {
  11234. if (!$portal || !detailPanel || detailPanel.parentNode) return;
  11235. $portal.removeChild(detailPanel);
  11236. });
  11237. function button_binding($$value) {
  11238. binding_callbacks[$$value ? "unshift" : "push"](() => {
  11239. buttonComponent = $$value;
  11240. $$invalidate(3, buttonComponent);
  11241. });
  11242. }
  11243. function div_binding($$value) {
  11244. binding_callbacks[$$value ? "unshift" : "push"](() => {
  11245. detailPanel = $$value;
  11246. $$invalidate(4, detailPanel);
  11247. });
  11248. }
  11249. const measure_handler = e => $$invalidate(2, panelSize = sizeCreateFromAny(e.detail));
  11250. $$self.$$set = $$props => {
  11251. if ("buttonClass" in $$props) $$invalidate(0, buttonClass = $$props.buttonClass);
  11252. if ("panelClass" in $$props) $$invalidate(1, panelClass = $$props.panelClass);
  11253. if ("isActive" in $$props) $$invalidate(18, isActive = $$props.isActive);
  11254. if ("onshow" in $$props) $$invalidate(19, onshow = $$props.onshow);
  11255. if ("$$scope" in $$props) $$invalidate(39, $$scope = $$props.$$scope);
  11256. };
  11257. $$self.$$.update = () => {
  11258. if ($$self.$$.dirty[0] & /*buttonComponent*/ 8) {
  11259. buttonElement = buttonComponent && buttonComponent.getElement();
  11260. }
  11261. if ($$self.$$.dirty[0] & /*isActive, downOutsidePanel*/ 8650752) {
  11262. $$invalidate(9, handleUp = isActive
  11263. ? e => {
  11264. if (!downOutsidePanel) return;
  11265. $$invalidate(23, downOutsidePanel = false);
  11266. if (isTargetSelf(e)) return;
  11267. $$invalidate(18, isActive = false);
  11268. }
  11269. : undefined);
  11270. }
  11271. if ($$self.$$.dirty[0] & /*isActive*/ 262144) {
  11272. opacity.set(isActive ? 1 : 0);
  11273. }
  11274. if ($$self.$$.dirty[0] & /*isActive*/ 262144) {
  11275. offset.set(isActive ? 0 : -5);
  11276. }
  11277. if ($$self.$$.dirty[0] & /*$offset*/ 67108864) {
  11278. $$invalidate(25, offsetProgress = 1 - $offset / -5);
  11279. }
  11280. if ($$self.$$.dirty[0] & /*$portalRootRect, panelSize, buttonRect*/ 135266308) {
  11281. if ($portalRootRect && panelSize && buttonRect) {
  11282. // as a starting point we'll align panel to center of button and position below
  11283. let x = buttonRect.x - $portalRootRect.x + buttonRect.width * 0.5 - panelSize.width * 0.5;
  11284. let y = buttonRect.y - $portalRootRect.y + buttonRect.height;
  11285. const parentLeft = panelMargin;
  11286. const parentTop = panelMargin;
  11287. const parentRight = $portalRootRect.width - panelMargin;
  11288. const parentBottom = $portalRootRect.height - panelMargin;
  11289. const panelLeft = x;
  11290. const panelTop = y;
  11291. const panelRight = panelLeft + panelSize.width;
  11292. const panelBottom = panelTop + panelSize.height;
  11293. // move to right
  11294. if (panelLeft < parentLeft) {
  11295. $$invalidate(22, shift.x = panelLeft - parentLeft, shift);
  11296. x = parentLeft;
  11297. }
  11298. // move to left
  11299. if (panelRight > parentRight) {
  11300. $$invalidate(22, shift.x = panelRight - parentRight, shift);
  11301. x = parentRight - panelSize.width;
  11302. }
  11303. if (panelBottom > parentBottom) {
  11304. // doesn't fit vertically, push up
  11305. $$invalidate(21, dir.y = -1, dir);
  11306. const positionedAboveButtonY = y - panelSize.height - buttonRect.height;
  11307. const panelFitsAboveButton = parentTop < positionedAboveButtonY;
  11308. if (panelFitsAboveButton) {
  11309. $$invalidate(22, shift.y = 0, shift);
  11310. y -= panelSize.height + buttonRect.height;
  11311. } else {
  11312. // overlap with button
  11313. $$invalidate(22, shift.y = y - (panelBottom - parentBottom), shift);
  11314. y -= panelBottom - parentBottom;
  11315. }
  11316. } else {
  11317. // all is fine
  11318. $$invalidate(21, dir.y = 1, dir);
  11319. }
  11320. set_store_value(position, $position = vectorApply(vectorCreate(x, y), snapToPixel), $position);
  11321. }
  11322. }
  11323. if ($$self.$$.dirty[0] & /*$opacity*/ 536870912) {
  11324. $$invalidate(5, isVisible = $opacity > 0);
  11325. }
  11326. if ($$self.$$.dirty[0] & /*$opacity*/ 536870912) {
  11327. $$invalidate(30, isAnimating = $opacity < 1);
  11328. }
  11329. if ($$self.$$.dirty[0] & /*$position, dir, $offset*/ 337641472) {
  11330. $$invalidate(31, transform = `translateX(${$position.x + dir.x * panelMargin}px) translateY(${$position.y + dir.y * panelMargin + dir.y * $offset}px)`);
  11331. }
  11332. if ($$self.$$.dirty[0] & /*isAnimating, $opacity*/ 1610612736 | $$self.$$.dirty[1] & /*transform*/ 1) {
  11333. $$invalidate(6, style = isAnimating
  11334. ? `opacity: ${$opacity}; pointer-events: ${$opacity < 1 ? "none" : "all"}; transform: ${transform};`
  11335. : `transform: ${transform}`);
  11336. }
  11337. if ($$self.$$.dirty[0] & /*offsetProgress*/ 33554432) {
  11338. $$invalidate(32, tipScale = 0.5 + offsetProgress * 0.5);
  11339. }
  11340. if ($$self.$$.dirty[0] & /*offsetProgress*/ 33554432) {
  11341. $$invalidate(33, tipOpacity = offsetProgress);
  11342. }
  11343. if ($$self.$$.dirty[0] & /*$position, panelSize, dir, shift*/ 274726916 | $$self.$$.dirty[1] & /*tipOpacity, tipScale*/ 6) {
  11344. $$invalidate(7, tipStyle = $position && panelSize && `opacity:${tipOpacity};transform:scaleX(${tipScale})rotate(45deg);top:${dir.y < 0 ? shift.y + panelSize.height : 0}px;left:${shift.x + panelSize.width * 0.5}px`);
  11345. }
  11346. if ($$self.$$.dirty[0] & /*isActive*/ 262144) {
  11347. $$invalidate(8, handleDown = isActive
  11348. ? e => {
  11349. if (isTargetSelf(e)) return;
  11350. $$invalidate(23, downOutsidePanel = true);
  11351. }
  11352. : undefined);
  11353. }
  11354. if ($$self.$$.dirty[0] & /*isVisible, detailPanel*/ 48 | $$self.$$.dirty[1] & /*$portal*/ 8) {
  11355. if (isVisible && $portal && detailPanel && detailPanel.parentNode !== $portal) $portal.appendChild(detailPanel);
  11356. }
  11357. if ($$self.$$.dirty[0] & /*isActive*/ 262144) {
  11358. if (!isActive) $$invalidate(24, trigger = undefined);
  11359. }
  11360. if ($$self.$$.dirty[0] & /*isVisible, detailPanel, onshow, trigger*/ 17301552) {
  11361. if (isVisible && detailPanel) onshow({ e: trigger, panel: detailPanel });
  11362. }
  11363. };
  11364. return [
  11365. buttonClass,
  11366. panelClass,
  11367. panelSize,
  11368. buttonComponent,
  11369. detailPanel,
  11370. isVisible,
  11371. style,
  11372. tipStyle,
  11373. handleDown,
  11374. handleUp,
  11375. portal,
  11376. portalRootRect,
  11377. opacity,
  11378. position,
  11379. offset,
  11380. handleClick,
  11381. handleButtonKeydown,
  11382. handlePanelKeydown,
  11383. isActive,
  11384. onshow,
  11385. buttonRect,
  11386. dir,
  11387. shift,
  11388. downOutsidePanel,
  11389. trigger,
  11390. offsetProgress,
  11391. $offset,
  11392. $portalRootRect,
  11393. $position,
  11394. $opacity,
  11395. isAnimating,
  11396. transform,
  11397. tipScale,
  11398. tipOpacity,
  11399. $portal,
  11400. slots,
  11401. button_binding,
  11402. div_binding,
  11403. measure_handler,
  11404. $$scope
  11405. ];
  11406. }
  11407. class Details extends SvelteComponent {
  11408. constructor(options) {
  11409. super();
  11410. init(
  11411. this,
  11412. options,
  11413. instance$B,
  11414. create_fragment$B,
  11415. safe_not_equal,
  11416. {
  11417. buttonClass: 0,
  11418. panelClass: 1,
  11419. isActive: 18,
  11420. onshow: 19
  11421. },
  11422. [-1, -1]
  11423. );
  11424. }
  11425. }
  11426. /* src/core/ui/components/RadioItem.svelte generated by Svelte v3.37.0 */
  11427. function create_fragment$A(ctx) {
  11428. let li;
  11429. let input;
  11430. let t;
  11431. let label_1;
  11432. let li_class_value;
  11433. let current;
  11434. let mounted;
  11435. let dispose;
  11436. const default_slot_template = /*#slots*/ ctx[14].default;
  11437. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[13], null);
  11438. return {
  11439. c() {
  11440. li = element("li");
  11441. input = element("input");
  11442. t = space();
  11443. label_1 = element("label");
  11444. if (default_slot) default_slot.c();
  11445. attr(input, "type", "radio");
  11446. attr(input, "class", "implicit");
  11447. attr(input, "id", /*inputId*/ ctx[6]);
  11448. attr(input, "name", /*name*/ ctx[0]);
  11449. input.value = /*value*/ ctx[3];
  11450. input.disabled = /*disabled*/ ctx[5];
  11451. input.checked = /*checked*/ ctx[4];
  11452. attr(label_1, "for", /*inputId*/ ctx[6]);
  11453. attr(label_1, "title", /*label*/ ctx[2]);
  11454. attr(li, "class", li_class_value = arrayJoin(["PinturaRadioGroupOption", /*klass*/ ctx[1]]));
  11455. attr(li, "data-disabled", /*disabled*/ ctx[5]);
  11456. attr(li, "data-selected", /*checked*/ ctx[4]);
  11457. },
  11458. m(target, anchor) {
  11459. insert(target, li, anchor);
  11460. append(li, input);
  11461. append(li, t);
  11462. append(li, label_1);
  11463. if (default_slot) {
  11464. default_slot.m(label_1, null);
  11465. }
  11466. current = true;
  11467. if (!mounted) {
  11468. dispose = [
  11469. listen(input, "change", stop_propagation(/*change_handler*/ ctx[15])),
  11470. listen(input, "keydown", /*handleKeydown*/ ctx[8]),
  11471. listen(input, "click", /*handleClick*/ ctx[9])
  11472. ];
  11473. mounted = true;
  11474. }
  11475. },
  11476. p(ctx, [dirty]) {
  11477. if (!current || dirty & /*inputId*/ 64) {
  11478. attr(input, "id", /*inputId*/ ctx[6]);
  11479. }
  11480. if (!current || dirty & /*name*/ 1) {
  11481. attr(input, "name", /*name*/ ctx[0]);
  11482. }
  11483. if (!current || dirty & /*value*/ 8) {
  11484. input.value = /*value*/ ctx[3];
  11485. }
  11486. if (!current || dirty & /*disabled*/ 32) {
  11487. input.disabled = /*disabled*/ ctx[5];
  11488. }
  11489. if (!current || dirty & /*checked*/ 16) {
  11490. input.checked = /*checked*/ ctx[4];
  11491. }
  11492. if (default_slot) {
  11493. if (default_slot.p && dirty & /*$$scope*/ 8192) {
  11494. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[13], dirty, null, null);
  11495. }
  11496. }
  11497. if (!current || dirty & /*inputId*/ 64) {
  11498. attr(label_1, "for", /*inputId*/ ctx[6]);
  11499. }
  11500. if (!current || dirty & /*label*/ 4) {
  11501. attr(label_1, "title", /*label*/ ctx[2]);
  11502. }
  11503. if (!current || dirty & /*klass*/ 2 && li_class_value !== (li_class_value = arrayJoin(["PinturaRadioGroupOption", /*klass*/ ctx[1]]))) {
  11504. attr(li, "class", li_class_value);
  11505. }
  11506. if (!current || dirty & /*disabled*/ 32) {
  11507. attr(li, "data-disabled", /*disabled*/ ctx[5]);
  11508. }
  11509. if (!current || dirty & /*checked*/ 16) {
  11510. attr(li, "data-selected", /*checked*/ ctx[4]);
  11511. }
  11512. },
  11513. i(local) {
  11514. if (current) return;
  11515. transition_in(default_slot, local);
  11516. current = true;
  11517. },
  11518. o(local) {
  11519. transition_out(default_slot, local);
  11520. current = false;
  11521. },
  11522. d(detaching) {
  11523. if (detaching) detach(li);
  11524. if (default_slot) default_slot.d(detaching);
  11525. mounted = false;
  11526. run_all(dispose);
  11527. }
  11528. };
  11529. }
  11530. function instance$A($$self, $$props, $$invalidate) {
  11531. let inputId;
  11532. let $keysPressedStored;
  11533. let { $$slots: slots = {}, $$scope } = $$props;
  11534. let { name } = $$props;
  11535. let { class: klass = undefined } = $$props;
  11536. let { label } = $$props;
  11537. let { id } = $$props;
  11538. let { value } = $$props;
  11539. let { checked } = $$props;
  11540. let { onkeydown } = $$props;
  11541. let { onclick } = $$props;
  11542. let { disabled = false } = $$props;
  11543. const keysPressedStored = getContext("keysPressed");
  11544. component_subscribe($$self, keysPressedStored, value => $$invalidate(16, $keysPressedStored = value));
  11545. const handleKeydown = e => {
  11546. onkeydown(e);
  11547. };
  11548. const handleClick = e => {
  11549. if ($keysPressedStored.length) return;
  11550. onclick(e);
  11551. };
  11552. function change_handler(event) {
  11553. bubble($$self, event);
  11554. }
  11555. $$self.$$set = $$props => {
  11556. if ("name" in $$props) $$invalidate(0, name = $$props.name);
  11557. if ("class" in $$props) $$invalidate(1, klass = $$props.class);
  11558. if ("label" in $$props) $$invalidate(2, label = $$props.label);
  11559. if ("id" in $$props) $$invalidate(10, id = $$props.id);
  11560. if ("value" in $$props) $$invalidate(3, value = $$props.value);
  11561. if ("checked" in $$props) $$invalidate(4, checked = $$props.checked);
  11562. if ("onkeydown" in $$props) $$invalidate(11, onkeydown = $$props.onkeydown);
  11563. if ("onclick" in $$props) $$invalidate(12, onclick = $$props.onclick);
  11564. if ("disabled" in $$props) $$invalidate(5, disabled = $$props.disabled);
  11565. if ("$$scope" in $$props) $$invalidate(13, $$scope = $$props.$$scope);
  11566. };
  11567. $$self.$$.update = () => {
  11568. if ($$self.$$.dirty & /*name, id*/ 1025) {
  11569. $$invalidate(6, inputId = `${name}-${id}`);
  11570. }
  11571. };
  11572. return [
  11573. name,
  11574. klass,
  11575. label,
  11576. value,
  11577. checked,
  11578. disabled,
  11579. inputId,
  11580. keysPressedStored,
  11581. handleKeydown,
  11582. handleClick,
  11583. id,
  11584. onkeydown,
  11585. onclick,
  11586. $$scope,
  11587. slots,
  11588. change_handler
  11589. ];
  11590. }
  11591. class RadioItem extends SvelteComponent {
  11592. constructor(options) {
  11593. super();
  11594. init(this, options, instance$A, create_fragment$A, safe_not_equal, {
  11595. name: 0,
  11596. class: 1,
  11597. label: 2,
  11598. id: 10,
  11599. value: 3,
  11600. checked: 4,
  11601. onkeydown: 11,
  11602. onclick: 12,
  11603. disabled: 5
  11604. });
  11605. }
  11606. }
  11607. var flattenOptions = (options = []) => options.reduce((prev, current) => {
  11608. const isGroup = isArray(current) ? isArray(current[1]) : !!current.options;
  11609. if (isGroup) {
  11610. return prev.concat(isArray(current) ? current[1] : current.options);
  11611. }
  11612. prev.push(current);
  11613. return prev;
  11614. }, []);
  11615. const mapOption = (option, index, optionMapper) => {
  11616. let mappedOption;
  11617. if (isArray(option)) {
  11618. mappedOption = {
  11619. id: index,
  11620. value: option[0],
  11621. label: option[1],
  11622. ...(option[2] || {}),
  11623. };
  11624. }
  11625. else {
  11626. mappedOption = option;
  11627. mappedOption.id = mappedOption.id != null ? mappedOption.id : index;
  11628. }
  11629. return optionMapper ? optionMapper(mappedOption) : mappedOption;
  11630. };
  11631. var mapOptions = (options = [], optionMapper) => {
  11632. let index = 0;
  11633. return options.map((option) => {
  11634. index++;
  11635. if (isArray(option)) {
  11636. // is either [label, options] or [value, label]
  11637. if (isArray(option[1])) {
  11638. return {
  11639. id: index,
  11640. label: option[0],
  11641. options: option[1].map((option) => mapOption(option, ++index, optionMapper)),
  11642. };
  11643. }
  11644. return mapOption(option, index, optionMapper);
  11645. }
  11646. else {
  11647. // is either { id?, label, options } or { id?, value, label }
  11648. if (option.options) {
  11649. return {
  11650. id: option.id || index,
  11651. label: option.label,
  11652. options: option.options.map((option) => mapOption(option, ++index, optionMapper)),
  11653. };
  11654. }
  11655. return mapOption(option, index, optionMapper);
  11656. }
  11657. });
  11658. };
  11659. var opop = (fn, ...args) => fn && fn(...args);
  11660. var localize = (prop, locale, params) => isFunction(prop) ? prop(locale, params) : prop;
  11661. const localizeOptions = (options, locale) => options.map(([value, label, props]) => {
  11662. if (isArray(label)) {
  11663. return [localize(value, locale), localizeOptions(label, locale)];
  11664. }
  11665. else {
  11666. const res = [value, localize(label, locale)];
  11667. if (props) {
  11668. let obj = { ...props };
  11669. if (props.icon)
  11670. obj.icon = localize(props.icon, locale);
  11671. res.push(obj);
  11672. }
  11673. return res;
  11674. }
  11675. });
  11676. var localizeOptions$1 = (options, locale) => localizeOptions(options, locale);
  11677. var isConfirmKey = (key) => /enter| /i.test(key);
  11678. /* src/core/ui/components/RadioGroup.svelte generated by Svelte v3.37.0 */
  11679. function get_each_context$7(ctx, list, i) {
  11680. const child_ctx = ctx.slice();
  11681. child_ctx[26] = list[i];
  11682. return child_ctx;
  11683. }
  11684. const get_option_slot_changes_1 = dirty => ({ option: dirty & /*mappedOptions*/ 2048 });
  11685. const get_option_slot_context_1 = ctx => ({ option: /*option*/ ctx[26] });
  11686. function get_each_context_1(ctx, list, i) {
  11687. const child_ctx = ctx.slice();
  11688. child_ctx[26] = list[i];
  11689. return child_ctx;
  11690. }
  11691. const get_option_slot_changes = dirty => ({ option: dirty & /*mappedOptions*/ 2048 });
  11692. const get_option_slot_context = ctx => ({ option: /*option*/ ctx[26] });
  11693. const get_group_slot_changes = dirty => ({ option: dirty & /*mappedOptions*/ 2048 });
  11694. const get_group_slot_context = ctx => ({ option: /*option*/ ctx[26] });
  11695. // (71:0) {#if localizedOptions.length}
  11696. function create_if_block_1$a(ctx) {
  11697. let fieldset;
  11698. let t;
  11699. let ul;
  11700. let each_blocks = [];
  11701. let each_1_lookup = new Map();
  11702. let fieldset_class_value;
  11703. let current;
  11704. let if_block = /*label*/ ctx[1] && create_if_block_7$1(ctx);
  11705. let each_value = /*mappedOptions*/ ctx[11];
  11706. const get_key = ctx => /*option*/ ctx[26].id;
  11707. for (let i = 0; i < each_value.length; i += 1) {
  11708. let child_ctx = get_each_context$7(ctx, each_value, i);
  11709. let key = get_key(child_ctx);
  11710. each_1_lookup.set(key, each_blocks[i] = create_each_block$7(key, child_ctx));
  11711. }
  11712. return {
  11713. c() {
  11714. fieldset = element("fieldset");
  11715. if (if_block) if_block.c();
  11716. t = space();
  11717. ul = element("ul");
  11718. for (let i = 0; i < each_blocks.length; i += 1) {
  11719. each_blocks[i].c();
  11720. }
  11721. attr(ul, "class", "PinturaRadioGroupOptions");
  11722. attr(fieldset, "class", fieldset_class_value = arrayJoin(["PinturaRadioGroup", /*klass*/ ctx[3]]));
  11723. attr(fieldset, "data-layout", /*layout*/ ctx[5]);
  11724. attr(fieldset, "title", /*title*/ ctx[7]);
  11725. },
  11726. m(target, anchor) {
  11727. insert(target, fieldset, anchor);
  11728. if (if_block) if_block.m(fieldset, null);
  11729. append(fieldset, t);
  11730. append(fieldset, ul);
  11731. for (let i = 0; i < each_blocks.length; i += 1) {
  11732. each_blocks[i].m(ul, null);
  11733. }
  11734. current = true;
  11735. },
  11736. p(ctx, dirty) {
  11737. if (/*label*/ ctx[1]) {
  11738. if (if_block) {
  11739. if_block.p(ctx, dirty);
  11740. } else {
  11741. if_block = create_if_block_7$1(ctx);
  11742. if_block.c();
  11743. if_block.m(fieldset, t);
  11744. }
  11745. } else if (if_block) {
  11746. if_block.d(1);
  11747. if_block = null;
  11748. }
  11749. if (dirty & /*arrayJoin, optionGroupClass, mappedOptions, name, optionClass, getOptionIndex, selectedIndex, handleRadioKeydown, handleRadioClick, optionLabelClass, $$scope*/ 8420177) {
  11750. each_value = /*mappedOptions*/ ctx[11];
  11751. group_outros();
  11752. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, ul, outro_and_destroy_block, create_each_block$7, null, get_each_context$7);
  11753. check_outros();
  11754. }
  11755. if (!current || dirty & /*klass*/ 8 && fieldset_class_value !== (fieldset_class_value = arrayJoin(["PinturaRadioGroup", /*klass*/ ctx[3]]))) {
  11756. attr(fieldset, "class", fieldset_class_value);
  11757. }
  11758. if (!current || dirty & /*layout*/ 32) {
  11759. attr(fieldset, "data-layout", /*layout*/ ctx[5]);
  11760. }
  11761. if (!current || dirty & /*title*/ 128) {
  11762. attr(fieldset, "title", /*title*/ ctx[7]);
  11763. }
  11764. },
  11765. i(local) {
  11766. if (current) return;
  11767. for (let i = 0; i < each_value.length; i += 1) {
  11768. transition_in(each_blocks[i]);
  11769. }
  11770. current = true;
  11771. },
  11772. o(local) {
  11773. for (let i = 0; i < each_blocks.length; i += 1) {
  11774. transition_out(each_blocks[i]);
  11775. }
  11776. current = false;
  11777. },
  11778. d(detaching) {
  11779. if (detaching) detach(fieldset);
  11780. if (if_block) if_block.d();
  11781. for (let i = 0; i < each_blocks.length; i += 1) {
  11782. each_blocks[i].d();
  11783. }
  11784. }
  11785. };
  11786. }
  11787. // (73:8) {#if label}
  11788. function create_if_block_7$1(ctx) {
  11789. let legend;
  11790. let t;
  11791. let legend_class_value;
  11792. return {
  11793. c() {
  11794. legend = element("legend");
  11795. t = text(/*label*/ ctx[1]);
  11796. attr(legend, "class", legend_class_value = /*hideLabel*/ ctx[2] && "implicit");
  11797. },
  11798. m(target, anchor) {
  11799. insert(target, legend, anchor);
  11800. append(legend, t);
  11801. },
  11802. p(ctx, dirty) {
  11803. if (dirty & /*label*/ 2) set_data(t, /*label*/ ctx[1]);
  11804. if (dirty & /*hideLabel*/ 4 && legend_class_value !== (legend_class_value = /*hideLabel*/ ctx[2] && "implicit")) {
  11805. attr(legend, "class", legend_class_value);
  11806. }
  11807. },
  11808. d(detaching) {
  11809. if (detaching) detach(legend);
  11810. }
  11811. };
  11812. }
  11813. // (108:16) {:else}
  11814. function create_else_block$4(ctx) {
  11815. let radioitem;
  11816. let current;
  11817. radioitem = new RadioItem({
  11818. props: {
  11819. name: /*name*/ ctx[4],
  11820. label: /*option*/ ctx[26].label,
  11821. id: /*option*/ ctx[26].id,
  11822. value: /*option*/ ctx[26].value,
  11823. disabled: /*option*/ ctx[26].disabled,
  11824. class: /*optionClass*/ ctx[8],
  11825. checked: /*getOptionIndex*/ ctx[12](/*option*/ ctx[26]) === /*selectedIndex*/ ctx[0],
  11826. onkeydown: /*handleRadioKeydown*/ ctx[13](/*option*/ ctx[26]),
  11827. onclick: /*handleRadioClick*/ ctx[14](/*option*/ ctx[26]),
  11828. $$slots: { default: [create_default_slot_2$4] },
  11829. $$scope: { ctx }
  11830. }
  11831. });
  11832. return {
  11833. c() {
  11834. create_component(radioitem.$$.fragment);
  11835. },
  11836. m(target, anchor) {
  11837. mount_component(radioitem, target, anchor);
  11838. current = true;
  11839. },
  11840. p(ctx, dirty) {
  11841. const radioitem_changes = {};
  11842. if (dirty & /*name*/ 16) radioitem_changes.name = /*name*/ ctx[4];
  11843. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.label = /*option*/ ctx[26].label;
  11844. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.id = /*option*/ ctx[26].id;
  11845. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.value = /*option*/ ctx[26].value;
  11846. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.disabled = /*option*/ ctx[26].disabled;
  11847. if (dirty & /*optionClass*/ 256) radioitem_changes.class = /*optionClass*/ ctx[8];
  11848. if (dirty & /*mappedOptions, selectedIndex*/ 2049) radioitem_changes.checked = /*getOptionIndex*/ ctx[12](/*option*/ ctx[26]) === /*selectedIndex*/ ctx[0];
  11849. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.onkeydown = /*handleRadioKeydown*/ ctx[13](/*option*/ ctx[26]);
  11850. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.onclick = /*handleRadioClick*/ ctx[14](/*option*/ ctx[26]);
  11851. if (dirty & /*$$scope, optionLabelClass, mappedOptions*/ 8390720) {
  11852. radioitem_changes.$$scope = { dirty, ctx };
  11853. }
  11854. radioitem.$set(radioitem_changes);
  11855. },
  11856. i(local) {
  11857. if (current) return;
  11858. transition_in(radioitem.$$.fragment, local);
  11859. current = true;
  11860. },
  11861. o(local) {
  11862. transition_out(radioitem.$$.fragment, local);
  11863. current = false;
  11864. },
  11865. d(detaching) {
  11866. destroy_component(radioitem, detaching);
  11867. }
  11868. };
  11869. }
  11870. // (78:16) {#if option.options}
  11871. function create_if_block_2$8(ctx) {
  11872. let li;
  11873. let t0;
  11874. let ul;
  11875. let each_blocks = [];
  11876. let each_1_lookup = new Map();
  11877. let t1;
  11878. let li_class_value;
  11879. let current;
  11880. const group_slot_template = /*#slots*/ ctx[22].group;
  11881. const group_slot = create_slot(group_slot_template, ctx, /*$$scope*/ ctx[23], get_group_slot_context);
  11882. const group_slot_or_fallback = group_slot || fallback_block_1(ctx);
  11883. let each_value_1 = /*option*/ ctx[26].options;
  11884. const get_key = ctx => /*option*/ ctx[26].id;
  11885. for (let i = 0; i < each_value_1.length; i += 1) {
  11886. let child_ctx = get_each_context_1(ctx, each_value_1, i);
  11887. let key = get_key(child_ctx);
  11888. each_1_lookup.set(key, each_blocks[i] = create_each_block_1(key, child_ctx));
  11889. }
  11890. return {
  11891. c() {
  11892. li = element("li");
  11893. if (group_slot_or_fallback) group_slot_or_fallback.c();
  11894. t0 = space();
  11895. ul = element("ul");
  11896. for (let i = 0; i < each_blocks.length; i += 1) {
  11897. each_blocks[i].c();
  11898. }
  11899. t1 = space();
  11900. attr(ul, "class", "PinturaRadioGroupOptions");
  11901. attr(li, "class", li_class_value = arrayJoin(["PinturaRadioGroupOptionGroup", /*optionGroupClass*/ ctx[9]]));
  11902. },
  11903. m(target, anchor) {
  11904. insert(target, li, anchor);
  11905. if (group_slot_or_fallback) {
  11906. group_slot_or_fallback.m(li, null);
  11907. }
  11908. append(li, t0);
  11909. append(li, ul);
  11910. for (let i = 0; i < each_blocks.length; i += 1) {
  11911. each_blocks[i].m(ul, null);
  11912. }
  11913. append(li, t1);
  11914. current = true;
  11915. },
  11916. p(ctx, dirty) {
  11917. if (group_slot) {
  11918. if (group_slot.p && dirty & /*$$scope, mappedOptions*/ 8390656) {
  11919. update_slot(group_slot, group_slot_template, ctx, /*$$scope*/ ctx[23], dirty, get_group_slot_changes, get_group_slot_context);
  11920. }
  11921. } else {
  11922. if (group_slot_or_fallback && group_slot_or_fallback.p && dirty & /*mappedOptions*/ 2048) {
  11923. group_slot_or_fallback.p(ctx, dirty);
  11924. }
  11925. }
  11926. if (dirty & /*name, mappedOptions, optionClass, getOptionIndex, selectedIndex, handleRadioKeydown, handleRadioClick, optionLabelClass, $$scope*/ 8419665) {
  11927. each_value_1 = /*option*/ ctx[26].options;
  11928. group_outros();
  11929. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value_1, each_1_lookup, ul, outro_and_destroy_block, create_each_block_1, null, get_each_context_1);
  11930. check_outros();
  11931. }
  11932. if (!current || dirty & /*optionGroupClass*/ 512 && li_class_value !== (li_class_value = arrayJoin(["PinturaRadioGroupOptionGroup", /*optionGroupClass*/ ctx[9]]))) {
  11933. attr(li, "class", li_class_value);
  11934. }
  11935. },
  11936. i(local) {
  11937. if (current) return;
  11938. transition_in(group_slot_or_fallback, local);
  11939. for (let i = 0; i < each_value_1.length; i += 1) {
  11940. transition_in(each_blocks[i]);
  11941. }
  11942. current = true;
  11943. },
  11944. o(local) {
  11945. transition_out(group_slot_or_fallback, local);
  11946. for (let i = 0; i < each_blocks.length; i += 1) {
  11947. transition_out(each_blocks[i]);
  11948. }
  11949. current = false;
  11950. },
  11951. d(detaching) {
  11952. if (detaching) detach(li);
  11953. if (group_slot_or_fallback) group_slot_or_fallback.d(detaching);
  11954. for (let i = 0; i < each_blocks.length; i += 1) {
  11955. each_blocks[i].d();
  11956. }
  11957. }
  11958. };
  11959. }
  11960. // (120:28) {#if option.icon}
  11961. function create_if_block_6$2(ctx) {
  11962. let icon;
  11963. let current;
  11964. icon = new Icon({
  11965. props: {
  11966. $$slots: { default: [create_default_slot_3$2] },
  11967. $$scope: { ctx }
  11968. }
  11969. });
  11970. return {
  11971. c() {
  11972. create_component(icon.$$.fragment);
  11973. },
  11974. m(target, anchor) {
  11975. mount_component(icon, target, anchor);
  11976. current = true;
  11977. },
  11978. p(ctx, dirty) {
  11979. const icon_changes = {};
  11980. if (dirty & /*$$scope, mappedOptions*/ 8390656) {
  11981. icon_changes.$$scope = { dirty, ctx };
  11982. }
  11983. icon.$set(icon_changes);
  11984. },
  11985. i(local) {
  11986. if (current) return;
  11987. transition_in(icon.$$.fragment, local);
  11988. current = true;
  11989. },
  11990. o(local) {
  11991. transition_out(icon.$$.fragment, local);
  11992. current = false;
  11993. },
  11994. d(detaching) {
  11995. destroy_component(icon, detaching);
  11996. }
  11997. };
  11998. }
  11999. // (121:32) <Icon>
  12000. function create_default_slot_3$2(ctx) {
  12001. let g;
  12002. let raw_value = /*option*/ ctx[26].icon + "";
  12003. return {
  12004. c() {
  12005. g = svg_element("g");
  12006. },
  12007. m(target, anchor) {
  12008. insert(target, g, anchor);
  12009. g.innerHTML = raw_value;
  12010. },
  12011. p(ctx, dirty) {
  12012. if (dirty & /*mappedOptions*/ 2048 && raw_value !== (raw_value = /*option*/ ctx[26].icon + "")) g.innerHTML = raw_value; },
  12013. d(detaching) {
  12014. if (detaching) detach(g);
  12015. }
  12016. };
  12017. }
  12018. // (123:28) {#if !option.hideLabel}
  12019. function create_if_block_5$4(ctx) {
  12020. let span;
  12021. let t_value = /*option*/ ctx[26].label + "";
  12022. let t;
  12023. return {
  12024. c() {
  12025. span = element("span");
  12026. t = text(t_value);
  12027. attr(span, "class", /*optionLabelClass*/ ctx[6]);
  12028. },
  12029. m(target, anchor) {
  12030. insert(target, span, anchor);
  12031. append(span, t);
  12032. },
  12033. p(ctx, dirty) {
  12034. if (dirty & /*mappedOptions*/ 2048 && t_value !== (t_value = /*option*/ ctx[26].label + "")) set_data(t, t_value);
  12035. if (dirty & /*optionLabelClass*/ 64) {
  12036. attr(span, "class", /*optionLabelClass*/ ctx[6]);
  12037. }
  12038. },
  12039. d(detaching) {
  12040. if (detaching) detach(span);
  12041. }
  12042. };
  12043. }
  12044. // (119:54)
  12045. function fallback_block_2(ctx) {
  12046. let t0;
  12047. let t1;
  12048. let current;
  12049. let if_block0 = /*option*/ ctx[26].icon && create_if_block_6$2(ctx);
  12050. let if_block1 = !/*option*/ ctx[26].hideLabel && create_if_block_5$4(ctx);
  12051. return {
  12052. c() {
  12053. if (if_block0) if_block0.c();
  12054. t0 = space();
  12055. if (if_block1) if_block1.c();
  12056. t1 = space();
  12057. },
  12058. m(target, anchor) {
  12059. if (if_block0) if_block0.m(target, anchor);
  12060. insert(target, t0, anchor);
  12061. if (if_block1) if_block1.m(target, anchor);
  12062. insert(target, t1, anchor);
  12063. current = true;
  12064. },
  12065. p(ctx, dirty) {
  12066. if (/*option*/ ctx[26].icon) {
  12067. if (if_block0) {
  12068. if_block0.p(ctx, dirty);
  12069. if (dirty & /*mappedOptions*/ 2048) {
  12070. transition_in(if_block0, 1);
  12071. }
  12072. } else {
  12073. if_block0 = create_if_block_6$2(ctx);
  12074. if_block0.c();
  12075. transition_in(if_block0, 1);
  12076. if_block0.m(t0.parentNode, t0);
  12077. }
  12078. } else if (if_block0) {
  12079. group_outros();
  12080. transition_out(if_block0, 1, 1, () => {
  12081. if_block0 = null;
  12082. });
  12083. check_outros();
  12084. }
  12085. if (!/*option*/ ctx[26].hideLabel) {
  12086. if (if_block1) {
  12087. if_block1.p(ctx, dirty);
  12088. } else {
  12089. if_block1 = create_if_block_5$4(ctx);
  12090. if_block1.c();
  12091. if_block1.m(t1.parentNode, t1);
  12092. }
  12093. } else if (if_block1) {
  12094. if_block1.d(1);
  12095. if_block1 = null;
  12096. }
  12097. },
  12098. i(local) {
  12099. if (current) return;
  12100. transition_in(if_block0);
  12101. current = true;
  12102. },
  12103. o(local) {
  12104. transition_out(if_block0);
  12105. current = false;
  12106. },
  12107. d(detaching) {
  12108. if (if_block0) if_block0.d(detaching);
  12109. if (detaching) detach(t0);
  12110. if (if_block1) if_block1.d(detaching);
  12111. if (detaching) detach(t1);
  12112. }
  12113. };
  12114. }
  12115. // (109:20) <RadioItem {name} label={option.label} id={option.id} value={option.value} disabled={option.disabled} class={optionClass} checked={getOptionIndex(option) === selectedIndex} onkeydown={handleRadioKeydown(option)} onclick={handleRadioClick(option)} >
  12116. function create_default_slot_2$4(ctx) {
  12117. let current;
  12118. const option_slot_template = /*#slots*/ ctx[22].option;
  12119. const option_slot = create_slot(option_slot_template, ctx, /*$$scope*/ ctx[23], get_option_slot_context_1);
  12120. const option_slot_or_fallback = option_slot || fallback_block_2(ctx);
  12121. return {
  12122. c() {
  12123. if (option_slot_or_fallback) option_slot_or_fallback.c();
  12124. },
  12125. m(target, anchor) {
  12126. if (option_slot_or_fallback) {
  12127. option_slot_or_fallback.m(target, anchor);
  12128. }
  12129. current = true;
  12130. },
  12131. p(ctx, dirty) {
  12132. if (option_slot) {
  12133. if (option_slot.p && dirty & /*$$scope, mappedOptions*/ 8390656) {
  12134. update_slot(option_slot, option_slot_template, ctx, /*$$scope*/ ctx[23], dirty, get_option_slot_changes_1, get_option_slot_context_1);
  12135. }
  12136. } else {
  12137. if (option_slot_or_fallback && option_slot_or_fallback.p && dirty & /*optionLabelClass, mappedOptions*/ 2112) {
  12138. option_slot_or_fallback.p(ctx, dirty);
  12139. }
  12140. }
  12141. },
  12142. i(local) {
  12143. if (current) return;
  12144. transition_in(option_slot_or_fallback, local);
  12145. current = true;
  12146. },
  12147. o(local) {
  12148. transition_out(option_slot_or_fallback, local);
  12149. current = false;
  12150. },
  12151. d(detaching) {
  12152. if (option_slot_or_fallback) option_slot_or_fallback.d(detaching);
  12153. }
  12154. };
  12155. }
  12156. // (81:29) <span class="PinturaRadioGroupOptionGroupLabel">
  12157. function fallback_block_1(ctx) {
  12158. let span;
  12159. let t_value = /*option*/ ctx[26].label + "";
  12160. let t;
  12161. return {
  12162. c() {
  12163. span = element("span");
  12164. t = text(t_value);
  12165. attr(span, "class", "PinturaRadioGroupOptionGroupLabel");
  12166. },
  12167. m(target, anchor) {
  12168. insert(target, span, anchor);
  12169. append(span, t);
  12170. },
  12171. p(ctx, dirty) {
  12172. if (dirty & /*mappedOptions*/ 2048 && t_value !== (t_value = /*option*/ ctx[26].label + "")) set_data(t, t_value);
  12173. },
  12174. d(detaching) {
  12175. if (detaching) detach(span);
  12176. }
  12177. };
  12178. }
  12179. // (97:40) {#if option.icon}
  12180. function create_if_block_4$5(ctx) {
  12181. let icon;
  12182. let current;
  12183. icon = new Icon({
  12184. props: {
  12185. $$slots: { default: [create_default_slot_1$7] },
  12186. $$scope: { ctx }
  12187. }
  12188. });
  12189. return {
  12190. c() {
  12191. create_component(icon.$$.fragment);
  12192. },
  12193. m(target, anchor) {
  12194. mount_component(icon, target, anchor);
  12195. current = true;
  12196. },
  12197. p(ctx, dirty) {
  12198. const icon_changes = {};
  12199. if (dirty & /*$$scope, mappedOptions*/ 8390656) {
  12200. icon_changes.$$scope = { dirty, ctx };
  12201. }
  12202. icon.$set(icon_changes);
  12203. },
  12204. i(local) {
  12205. if (current) return;
  12206. transition_in(icon.$$.fragment, local);
  12207. current = true;
  12208. },
  12209. o(local) {
  12210. transition_out(icon.$$.fragment, local);
  12211. current = false;
  12212. },
  12213. d(detaching) {
  12214. destroy_component(icon, detaching);
  12215. }
  12216. };
  12217. }
  12218. // (98:44) <Icon>
  12219. function create_default_slot_1$7(ctx) {
  12220. let g;
  12221. let raw_value = /*option*/ ctx[26].icon + "";
  12222. return {
  12223. c() {
  12224. g = svg_element("g");
  12225. },
  12226. m(target, anchor) {
  12227. insert(target, g, anchor);
  12228. g.innerHTML = raw_value;
  12229. },
  12230. p(ctx, dirty) {
  12231. if (dirty & /*mappedOptions*/ 2048 && raw_value !== (raw_value = /*option*/ ctx[26].icon + "")) g.innerHTML = raw_value; },
  12232. d(detaching) {
  12233. if (detaching) detach(g);
  12234. }
  12235. };
  12236. }
  12237. // (100:40) {#if !option.hideLabel}
  12238. function create_if_block_3$6(ctx) {
  12239. let span;
  12240. let t_value = /*option*/ ctx[26].label + "";
  12241. let t;
  12242. return {
  12243. c() {
  12244. span = element("span");
  12245. t = text(t_value);
  12246. attr(span, "class", /*optionLabelClass*/ ctx[6]);
  12247. },
  12248. m(target, anchor) {
  12249. insert(target, span, anchor);
  12250. append(span, t);
  12251. },
  12252. p(ctx, dirty) {
  12253. if (dirty & /*mappedOptions*/ 2048 && t_value !== (t_value = /*option*/ ctx[26].label + "")) set_data(t, t_value);
  12254. if (dirty & /*optionLabelClass*/ 64) {
  12255. attr(span, "class", /*optionLabelClass*/ ctx[6]);
  12256. }
  12257. },
  12258. d(detaching) {
  12259. if (detaching) detach(span);
  12260. }
  12261. };
  12262. }
  12263. // (96:66)
  12264. function fallback_block$1(ctx) {
  12265. let t0;
  12266. let t1;
  12267. let current;
  12268. let if_block0 = /*option*/ ctx[26].icon && create_if_block_4$5(ctx);
  12269. let if_block1 = !/*option*/ ctx[26].hideLabel && create_if_block_3$6(ctx);
  12270. return {
  12271. c() {
  12272. if (if_block0) if_block0.c();
  12273. t0 = space();
  12274. if (if_block1) if_block1.c();
  12275. t1 = space();
  12276. },
  12277. m(target, anchor) {
  12278. if (if_block0) if_block0.m(target, anchor);
  12279. insert(target, t0, anchor);
  12280. if (if_block1) if_block1.m(target, anchor);
  12281. insert(target, t1, anchor);
  12282. current = true;
  12283. },
  12284. p(ctx, dirty) {
  12285. if (/*option*/ ctx[26].icon) {
  12286. if (if_block0) {
  12287. if_block0.p(ctx, dirty);
  12288. if (dirty & /*mappedOptions*/ 2048) {
  12289. transition_in(if_block0, 1);
  12290. }
  12291. } else {
  12292. if_block0 = create_if_block_4$5(ctx);
  12293. if_block0.c();
  12294. transition_in(if_block0, 1);
  12295. if_block0.m(t0.parentNode, t0);
  12296. }
  12297. } else if (if_block0) {
  12298. group_outros();
  12299. transition_out(if_block0, 1, 1, () => {
  12300. if_block0 = null;
  12301. });
  12302. check_outros();
  12303. }
  12304. if (!/*option*/ ctx[26].hideLabel) {
  12305. if (if_block1) {
  12306. if_block1.p(ctx, dirty);
  12307. } else {
  12308. if_block1 = create_if_block_3$6(ctx);
  12309. if_block1.c();
  12310. if_block1.m(t1.parentNode, t1);
  12311. }
  12312. } else if (if_block1) {
  12313. if_block1.d(1);
  12314. if_block1 = null;
  12315. }
  12316. },
  12317. i(local) {
  12318. if (current) return;
  12319. transition_in(if_block0);
  12320. current = true;
  12321. },
  12322. o(local) {
  12323. transition_out(if_block0);
  12324. current = false;
  12325. },
  12326. d(detaching) {
  12327. if (if_block0) if_block0.d(detaching);
  12328. if (detaching) detach(t0);
  12329. if (if_block1) if_block1.d(detaching);
  12330. if (detaching) detach(t1);
  12331. }
  12332. };
  12333. }
  12334. // (86:32) <RadioItem {name} label={option.label} id={option.id} value={option.value} disabled={option.disabled} class={optionClass} checked={getOptionIndex(option) === selectedIndex} onkeydown={handleRadioKeydown(option)} onclick={handleRadioClick(option)} >
  12335. function create_default_slot$f(ctx) {
  12336. let current;
  12337. const option_slot_template = /*#slots*/ ctx[22].option;
  12338. const option_slot = create_slot(option_slot_template, ctx, /*$$scope*/ ctx[23], get_option_slot_context);
  12339. const option_slot_or_fallback = option_slot || fallback_block$1(ctx);
  12340. return {
  12341. c() {
  12342. if (option_slot_or_fallback) option_slot_or_fallback.c();
  12343. },
  12344. m(target, anchor) {
  12345. if (option_slot_or_fallback) {
  12346. option_slot_or_fallback.m(target, anchor);
  12347. }
  12348. current = true;
  12349. },
  12350. p(ctx, dirty) {
  12351. if (option_slot) {
  12352. if (option_slot.p && dirty & /*$$scope, mappedOptions*/ 8390656) {
  12353. update_slot(option_slot, option_slot_template, ctx, /*$$scope*/ ctx[23], dirty, get_option_slot_changes, get_option_slot_context);
  12354. }
  12355. } else {
  12356. if (option_slot_or_fallback && option_slot_or_fallback.p && dirty & /*optionLabelClass, mappedOptions*/ 2112) {
  12357. option_slot_or_fallback.p(ctx, dirty);
  12358. }
  12359. }
  12360. },
  12361. i(local) {
  12362. if (current) return;
  12363. transition_in(option_slot_or_fallback, local);
  12364. current = true;
  12365. },
  12366. o(local) {
  12367. transition_out(option_slot_or_fallback, local);
  12368. current = false;
  12369. },
  12370. d(detaching) {
  12371. if (option_slot_or_fallback) option_slot_or_fallback.d(detaching);
  12372. }
  12373. };
  12374. }
  12375. // (85:28) {#each option.options as option (option.id)}
  12376. function create_each_block_1(key_1, ctx) {
  12377. let first;
  12378. let radioitem;
  12379. let current;
  12380. radioitem = new RadioItem({
  12381. props: {
  12382. name: /*name*/ ctx[4],
  12383. label: /*option*/ ctx[26].label,
  12384. id: /*option*/ ctx[26].id,
  12385. value: /*option*/ ctx[26].value,
  12386. disabled: /*option*/ ctx[26].disabled,
  12387. class: /*optionClass*/ ctx[8],
  12388. checked: /*getOptionIndex*/ ctx[12](/*option*/ ctx[26]) === /*selectedIndex*/ ctx[0],
  12389. onkeydown: /*handleRadioKeydown*/ ctx[13](/*option*/ ctx[26]),
  12390. onclick: /*handleRadioClick*/ ctx[14](/*option*/ ctx[26]),
  12391. $$slots: { default: [create_default_slot$f] },
  12392. $$scope: { ctx }
  12393. }
  12394. });
  12395. return {
  12396. key: key_1,
  12397. first: null,
  12398. c() {
  12399. first = empty();
  12400. create_component(radioitem.$$.fragment);
  12401. this.first = first;
  12402. },
  12403. m(target, anchor) {
  12404. insert(target, first, anchor);
  12405. mount_component(radioitem, target, anchor);
  12406. current = true;
  12407. },
  12408. p(new_ctx, dirty) {
  12409. ctx = new_ctx;
  12410. const radioitem_changes = {};
  12411. if (dirty & /*name*/ 16) radioitem_changes.name = /*name*/ ctx[4];
  12412. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.label = /*option*/ ctx[26].label;
  12413. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.id = /*option*/ ctx[26].id;
  12414. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.value = /*option*/ ctx[26].value;
  12415. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.disabled = /*option*/ ctx[26].disabled;
  12416. if (dirty & /*optionClass*/ 256) radioitem_changes.class = /*optionClass*/ ctx[8];
  12417. if (dirty & /*mappedOptions, selectedIndex*/ 2049) radioitem_changes.checked = /*getOptionIndex*/ ctx[12](/*option*/ ctx[26]) === /*selectedIndex*/ ctx[0];
  12418. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.onkeydown = /*handleRadioKeydown*/ ctx[13](/*option*/ ctx[26]);
  12419. if (dirty & /*mappedOptions*/ 2048) radioitem_changes.onclick = /*handleRadioClick*/ ctx[14](/*option*/ ctx[26]);
  12420. if (dirty & /*$$scope, optionLabelClass, mappedOptions*/ 8390720) {
  12421. radioitem_changes.$$scope = { dirty, ctx };
  12422. }
  12423. radioitem.$set(radioitem_changes);
  12424. },
  12425. i(local) {
  12426. if (current) return;
  12427. transition_in(radioitem.$$.fragment, local);
  12428. current = true;
  12429. },
  12430. o(local) {
  12431. transition_out(radioitem.$$.fragment, local);
  12432. current = false;
  12433. },
  12434. d(detaching) {
  12435. if (detaching) detach(first);
  12436. destroy_component(radioitem, detaching);
  12437. }
  12438. };
  12439. }
  12440. // (77:12) {#each mappedOptions as option (option.id)}
  12441. function create_each_block$7(key_1, ctx) {
  12442. let first;
  12443. let current_block_type_index;
  12444. let if_block;
  12445. let if_block_anchor;
  12446. let current;
  12447. const if_block_creators = [create_if_block_2$8, create_else_block$4];
  12448. const if_blocks = [];
  12449. function select_block_type(ctx, dirty) {
  12450. if (/*option*/ ctx[26].options) return 0;
  12451. return 1;
  12452. }
  12453. current_block_type_index = select_block_type(ctx);
  12454. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  12455. return {
  12456. key: key_1,
  12457. first: null,
  12458. c() {
  12459. first = empty();
  12460. if_block.c();
  12461. if_block_anchor = empty();
  12462. this.first = first;
  12463. },
  12464. m(target, anchor) {
  12465. insert(target, first, anchor);
  12466. if_blocks[current_block_type_index].m(target, anchor);
  12467. insert(target, if_block_anchor, anchor);
  12468. current = true;
  12469. },
  12470. p(new_ctx, dirty) {
  12471. ctx = new_ctx;
  12472. let previous_block_index = current_block_type_index;
  12473. current_block_type_index = select_block_type(ctx);
  12474. if (current_block_type_index === previous_block_index) {
  12475. if_blocks[current_block_type_index].p(ctx, dirty);
  12476. } else {
  12477. group_outros();
  12478. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  12479. if_blocks[previous_block_index] = null;
  12480. });
  12481. check_outros();
  12482. if_block = if_blocks[current_block_type_index];
  12483. if (!if_block) {
  12484. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  12485. if_block.c();
  12486. } else {
  12487. if_block.p(ctx, dirty);
  12488. }
  12489. transition_in(if_block, 1);
  12490. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  12491. }
  12492. },
  12493. i(local) {
  12494. if (current) return;
  12495. transition_in(if_block);
  12496. current = true;
  12497. },
  12498. o(local) {
  12499. transition_out(if_block);
  12500. current = false;
  12501. },
  12502. d(detaching) {
  12503. if (detaching) detach(first);
  12504. if_blocks[current_block_type_index].d(detaching);
  12505. if (detaching) detach(if_block_anchor);
  12506. }
  12507. };
  12508. }
  12509. function create_fragment$z(ctx) {
  12510. let t;
  12511. let if_block1_anchor;
  12512. let current;
  12513. let if_block0 = /*localizedOptions*/ ctx[10].length && create_if_block_1$a(ctx);
  12514. let if_block1 = false ;
  12515. return {
  12516. c() {
  12517. if (if_block0) if_block0.c();
  12518. t = space();
  12519. if_block1_anchor = empty();
  12520. },
  12521. m(target, anchor) {
  12522. if (if_block0) if_block0.m(target, anchor);
  12523. insert(target, t, anchor);
  12524. insert(target, if_block1_anchor, anchor);
  12525. current = true;
  12526. },
  12527. p(ctx, [dirty]) {
  12528. if (/*localizedOptions*/ ctx[10].length) {
  12529. if (if_block0) {
  12530. if_block0.p(ctx, dirty);
  12531. if (dirty & /*localizedOptions*/ 1024) {
  12532. transition_in(if_block0, 1);
  12533. }
  12534. } else {
  12535. if_block0 = create_if_block_1$a(ctx);
  12536. if_block0.c();
  12537. transition_in(if_block0, 1);
  12538. if_block0.m(t.parentNode, t);
  12539. }
  12540. } else if (if_block0) {
  12541. group_outros();
  12542. transition_out(if_block0, 1, 1, () => {
  12543. if_block0 = null;
  12544. });
  12545. check_outros();
  12546. }
  12547. },
  12548. i(local) {
  12549. if (current) return;
  12550. transition_in(if_block0);
  12551. transition_in(if_block1);
  12552. current = true;
  12553. },
  12554. o(local) {
  12555. transition_out(if_block0);
  12556. transition_out(if_block1);
  12557. current = false;
  12558. },
  12559. d(detaching) {
  12560. if (if_block0) if_block0.d(detaching);
  12561. if (detaching) detach(t);
  12562. if (detaching) detach(if_block1_anchor);
  12563. }
  12564. };
  12565. }
  12566. function instance$z($$self, $$props, $$invalidate) {
  12567. let localizedOptions;
  12568. let mappedOptions;
  12569. let flattenedOptions;
  12570. let { $$slots: slots = {}, $$scope } = $$props;
  12571. const dispatch = createEventDispatcher();
  12572. let { label = undefined } = $$props;
  12573. let { hideLabel = true } = $$props;
  12574. let { class: klass = undefined } = $$props;
  12575. let { name = `radio-group-${getUniqueId()}` } = $$props;
  12576. let { selectedIndex = -1 } = $$props;
  12577. let { options = [] } = $$props;
  12578. let { onchange = undefined } = $$props;
  12579. let { layout = undefined } = $$props;
  12580. let { optionMapper = undefined } = $$props;
  12581. let { optionFilter = undefined } = $$props;
  12582. let { value = undefined } = $$props;
  12583. let { optionLabelClass = undefined } = $$props;
  12584. let { title = undefined } = $$props;
  12585. let { locale = undefined } = $$props;
  12586. let { optionClass = undefined } = $$props;
  12587. let { optionGroupClass = undefined } = $$props;
  12588. const getOptionIndex = option => flattenedOptions.findIndex(flattenedOption => flattenedOption.id === option.id);
  12589. const changeSelection = (option, e) => {
  12590. $$invalidate(0, selectedIndex = getOptionIndex(option));
  12591. const payload = { index: selectedIndex, ...option };
  12592. opop(onchange, payload, e);
  12593. dispatch("change", payload);
  12594. };
  12595. const handleRadioKeydown = option => e => {
  12596. // is confirm key ([enter] or [space])
  12597. if (!isConfirmKey(e.key)) return;
  12598. changeSelection(option, e);
  12599. };
  12600. const handleRadioClick = option => e => {
  12601. changeSelection(option, e);
  12602. };
  12603. $$self.$$set = $$props => {
  12604. if ("label" in $$props) $$invalidate(1, label = $$props.label);
  12605. if ("hideLabel" in $$props) $$invalidate(2, hideLabel = $$props.hideLabel);
  12606. if ("class" in $$props) $$invalidate(3, klass = $$props.class);
  12607. if ("name" in $$props) $$invalidate(4, name = $$props.name);
  12608. if ("selectedIndex" in $$props) $$invalidate(0, selectedIndex = $$props.selectedIndex);
  12609. if ("options" in $$props) $$invalidate(15, options = $$props.options);
  12610. if ("onchange" in $$props) $$invalidate(16, onchange = $$props.onchange);
  12611. if ("layout" in $$props) $$invalidate(5, layout = $$props.layout);
  12612. if ("optionMapper" in $$props) $$invalidate(17, optionMapper = $$props.optionMapper);
  12613. if ("optionFilter" in $$props) $$invalidate(18, optionFilter = $$props.optionFilter);
  12614. if ("value" in $$props) $$invalidate(19, value = $$props.value);
  12615. if ("optionLabelClass" in $$props) $$invalidate(6, optionLabelClass = $$props.optionLabelClass);
  12616. if ("title" in $$props) $$invalidate(7, title = $$props.title);
  12617. if ("locale" in $$props) $$invalidate(20, locale = $$props.locale);
  12618. if ("optionClass" in $$props) $$invalidate(8, optionClass = $$props.optionClass);
  12619. if ("optionGroupClass" in $$props) $$invalidate(9, optionGroupClass = $$props.optionGroupClass);
  12620. if ("$$scope" in $$props) $$invalidate(23, $$scope = $$props.$$scope);
  12621. };
  12622. $$self.$$.update = () => {
  12623. if ($$self.$$.dirty & /*optionFilter, options, locale*/ 1343488) {
  12624. $$invalidate(10, localizedOptions = localizeOptions$1(optionFilter ? options.filter(optionFilter) : options, locale));
  12625. }
  12626. if ($$self.$$.dirty & /*localizedOptions, optionMapper*/ 132096) {
  12627. $$invalidate(11, mappedOptions = mapOptions(localizedOptions, optionMapper));
  12628. }
  12629. if ($$self.$$.dirty & /*mappedOptions*/ 2048) {
  12630. $$invalidate(21, flattenedOptions = flattenOptions(mappedOptions));
  12631. }
  12632. if ($$self.$$.dirty & /*value, selectedIndex, flattenedOptions*/ 2621441) {
  12633. // can optionally pass value to have radio button group try to auto-select the right option
  12634. if (value && selectedIndex < 0) {
  12635. $$invalidate(0, selectedIndex = flattenedOptions.findIndex(option => option.value === value));
  12636. }
  12637. }
  12638. };
  12639. return [
  12640. selectedIndex,
  12641. label,
  12642. hideLabel,
  12643. klass,
  12644. name,
  12645. layout,
  12646. optionLabelClass,
  12647. title,
  12648. optionClass,
  12649. optionGroupClass,
  12650. localizedOptions,
  12651. mappedOptions,
  12652. getOptionIndex,
  12653. handleRadioKeydown,
  12654. handleRadioClick,
  12655. options,
  12656. onchange,
  12657. optionMapper,
  12658. optionFilter,
  12659. value,
  12660. locale,
  12661. flattenedOptions,
  12662. slots,
  12663. $$scope
  12664. ];
  12665. }
  12666. class RadioGroup extends SvelteComponent {
  12667. constructor(options) {
  12668. super();
  12669. init(this, options, instance$z, create_fragment$z, safe_not_equal, {
  12670. label: 1,
  12671. hideLabel: 2,
  12672. class: 3,
  12673. name: 4,
  12674. selectedIndex: 0,
  12675. options: 15,
  12676. onchange: 16,
  12677. layout: 5,
  12678. optionMapper: 17,
  12679. optionFilter: 18,
  12680. value: 19,
  12681. optionLabelClass: 6,
  12682. title: 7,
  12683. locale: 20,
  12684. optionClass: 8,
  12685. optionGroupClass: 9
  12686. });
  12687. }
  12688. }
  12689. var isDeepEqual = (a, b) => {
  12690. if (Array.isArray(a) && Array.isArray(b))
  12691. return arrayEqual(a, b);
  12692. return a === b;
  12693. };
  12694. /* src/core/ui/components/Dropdown.svelte generated by Svelte v3.37.0 */
  12695. function create_if_block_1$9(ctx) {
  12696. let icon_1;
  12697. let current;
  12698. icon_1 = new Icon({
  12699. props: {
  12700. class: "PinturaButtonIcon",
  12701. $$slots: { default: [create_default_slot_1$6] },
  12702. $$scope: { ctx }
  12703. }
  12704. });
  12705. return {
  12706. c() {
  12707. create_component(icon_1.$$.fragment);
  12708. },
  12709. m(target, anchor) {
  12710. mount_component(icon_1, target, anchor);
  12711. current = true;
  12712. },
  12713. p(ctx, dirty) {
  12714. const icon_1_changes = {};
  12715. if (dirty & /*$$scope, icon*/ 536870976) {
  12716. icon_1_changes.$$scope = { dirty, ctx };
  12717. }
  12718. icon_1.$set(icon_1_changes);
  12719. },
  12720. i(local) {
  12721. if (current) return;
  12722. transition_in(icon_1.$$.fragment, local);
  12723. current = true;
  12724. },
  12725. o(local) {
  12726. transition_out(icon_1.$$.fragment, local);
  12727. current = false;
  12728. },
  12729. d(detaching) {
  12730. destroy_component(icon_1, detaching);
  12731. }
  12732. };
  12733. }
  12734. // (95:12) <Icon class="PinturaButtonIcon">
  12735. function create_default_slot_1$6(ctx) {
  12736. let g;
  12737. return {
  12738. c() {
  12739. g = svg_element("g");
  12740. },
  12741. m(target, anchor) {
  12742. insert(target, g, anchor);
  12743. g.innerHTML = /*icon*/ ctx[6];
  12744. },
  12745. p(ctx, dirty) {
  12746. if (dirty & /*icon*/ 64) g.innerHTML = /*icon*/ ctx[6]; },
  12747. d(detaching) {
  12748. if (detaching) detach(g);
  12749. }
  12750. };
  12751. }
  12752. // (89:4)
  12753. function create_label_slot$2(ctx) {
  12754. let span1;
  12755. let t0;
  12756. let span0;
  12757. let t1_value = (/*label*/ ctx[2] || /*selectedLabel*/ ctx[18]) + "";
  12758. let t1;
  12759. let span0_class_value;
  12760. let span1_title_value;
  12761. let span1_class_value;
  12762. let current;
  12763. let if_block = /*icon*/ ctx[6] && create_if_block_1$9(ctx);
  12764. return {
  12765. c() {
  12766. span1 = element("span");
  12767. if (if_block) if_block.c();
  12768. t0 = space();
  12769. span0 = element("span");
  12770. t1 = text(t1_value);
  12771. attr(span0, "class", span0_class_value = arrayJoin([
  12772. "PinturaButtonLabel",
  12773. /*labelClass*/ ctx[3],
  12774. /*hideLabel*/ ctx[5] && "implicit"
  12775. ]));
  12776. attr(span1, "slot", "label");
  12777. attr(span1, "title", span1_title_value = localize(/*title*/ ctx[1], /*locale*/ ctx[15]));
  12778. attr(span1, "class", span1_class_value = arrayJoin(["PinturaButtonInner", /*innerClass*/ ctx[4]]));
  12779. },
  12780. m(target, anchor) {
  12781. insert(target, span1, anchor);
  12782. if (if_block) if_block.m(span1, null);
  12783. append(span1, t0);
  12784. append(span1, span0);
  12785. append(span0, t1);
  12786. current = true;
  12787. },
  12788. p(ctx, dirty) {
  12789. if (/*icon*/ ctx[6]) {
  12790. if (if_block) {
  12791. if_block.p(ctx, dirty);
  12792. if (dirty & /*icon*/ 64) {
  12793. transition_in(if_block, 1);
  12794. }
  12795. } else {
  12796. if_block = create_if_block_1$9(ctx);
  12797. if_block.c();
  12798. transition_in(if_block, 1);
  12799. if_block.m(span1, t0);
  12800. }
  12801. } else if (if_block) {
  12802. group_outros();
  12803. transition_out(if_block, 1, 1, () => {
  12804. if_block = null;
  12805. });
  12806. check_outros();
  12807. }
  12808. if ((!current || dirty & /*label, selectedLabel*/ 262148) && t1_value !== (t1_value = (/*label*/ ctx[2] || /*selectedLabel*/ ctx[18]) + "")) set_data(t1, t1_value);
  12809. if (!current || dirty & /*labelClass, hideLabel*/ 40 && span0_class_value !== (span0_class_value = arrayJoin([
  12810. "PinturaButtonLabel",
  12811. /*labelClass*/ ctx[3],
  12812. /*hideLabel*/ ctx[5] && "implicit"
  12813. ]))) {
  12814. attr(span0, "class", span0_class_value);
  12815. }
  12816. if (!current || dirty & /*title, locale*/ 32770 && span1_title_value !== (span1_title_value = localize(/*title*/ ctx[1], /*locale*/ ctx[15]))) {
  12817. attr(span1, "title", span1_title_value);
  12818. }
  12819. if (!current || dirty & /*innerClass*/ 16 && span1_class_value !== (span1_class_value = arrayJoin(["PinturaButtonInner", /*innerClass*/ ctx[4]]))) {
  12820. attr(span1, "class", span1_class_value);
  12821. }
  12822. },
  12823. i(local) {
  12824. if (current) return;
  12825. transition_in(if_block);
  12826. current = true;
  12827. },
  12828. o(local) {
  12829. transition_out(if_block);
  12830. current = false;
  12831. },
  12832. d(detaching) {
  12833. if (detaching) detach(span1);
  12834. if (if_block) if_block.d();
  12835. }
  12836. };
  12837. }
  12838. // (116:12)
  12839. function create_group_slot$1(ctx) {
  12840. let span;
  12841. let t_value = /*option*/ ctx[28].label + "";
  12842. let t;
  12843. return {
  12844. c() {
  12845. span = element("span");
  12846. t = text(t_value);
  12847. attr(span, "slot", "group");
  12848. },
  12849. m(target, anchor) {
  12850. insert(target, span, anchor);
  12851. append(span, t);
  12852. },
  12853. p(ctx, dirty) {
  12854. if (dirty & /*option*/ 268435456 && t_value !== (t_value = /*option*/ ctx[28].label + "")) set_data(t, t_value);
  12855. },
  12856. d(detaching) {
  12857. if (detaching) detach(span);
  12858. }
  12859. };
  12860. }
  12861. // (118:16) {#if option.icon}
  12862. function create_if_block$a(ctx) {
  12863. let icon_1;
  12864. let current;
  12865. icon_1 = new Icon({
  12866. props: {
  12867. style: isFunction(/*optionIconStyle*/ ctx[13])
  12868. ? /*optionIconStyle*/ ctx[13](/*option*/ ctx[28].value)
  12869. : /*optionIconStyle*/ ctx[13],
  12870. $$slots: { default: [create_default_slot$e] },
  12871. $$scope: { ctx }
  12872. }
  12873. });
  12874. return {
  12875. c() {
  12876. create_component(icon_1.$$.fragment);
  12877. },
  12878. m(target, anchor) {
  12879. mount_component(icon_1, target, anchor);
  12880. current = true;
  12881. },
  12882. p(ctx, dirty) {
  12883. const icon_1_changes = {};
  12884. if (dirty & /*optionIconStyle, option*/ 268443648) icon_1_changes.style = isFunction(/*optionIconStyle*/ ctx[13])
  12885. ? /*optionIconStyle*/ ctx[13](/*option*/ ctx[28].value)
  12886. : /*optionIconStyle*/ ctx[13];
  12887. if (dirty & /*$$scope, option*/ 805306368) {
  12888. icon_1_changes.$$scope = { dirty, ctx };
  12889. }
  12890. icon_1.$set(icon_1_changes);
  12891. },
  12892. i(local) {
  12893. if (current) return;
  12894. transition_in(icon_1.$$.fragment, local);
  12895. current = true;
  12896. },
  12897. o(local) {
  12898. transition_out(icon_1.$$.fragment, local);
  12899. current = false;
  12900. },
  12901. d(detaching) {
  12902. destroy_component(icon_1, detaching);
  12903. }
  12904. };
  12905. }
  12906. // (119:20) <Icon style={isFunction(optionIconStyle) ? optionIconStyle(option.value) : optionIconStyle}>
  12907. function create_default_slot$e(ctx) {
  12908. let g;
  12909. let raw_value = /*option*/ ctx[28].icon + "";
  12910. return {
  12911. c() {
  12912. g = svg_element("g");
  12913. },
  12914. m(target, anchor) {
  12915. insert(target, g, anchor);
  12916. g.innerHTML = raw_value;
  12917. },
  12918. p(ctx, dirty) {
  12919. if (dirty & /*option*/ 268435456 && raw_value !== (raw_value = /*option*/ ctx[28].icon + "")) g.innerHTML = raw_value; },
  12920. d(detaching) {
  12921. if (detaching) detach(g);
  12922. }
  12923. };
  12924. }
  12925. // (117:12)
  12926. function create_option_slot$4(ctx) {
  12927. let span1;
  12928. let t0;
  12929. let span0;
  12930. let t1_value = /*option*/ ctx[28].label + "";
  12931. let t1;
  12932. let span0_style_value;
  12933. let span0_class_value;
  12934. let current;
  12935. let if_block = /*option*/ ctx[28].icon && create_if_block$a(ctx);
  12936. return {
  12937. c() {
  12938. span1 = element("span");
  12939. if (if_block) if_block.c();
  12940. t0 = space();
  12941. span0 = element("span");
  12942. t1 = text(t1_value);
  12943. attr(span0, "style", span0_style_value = isFunction(/*optionLabelStyle*/ ctx[14])
  12944. ? /*optionLabelStyle*/ ctx[14](/*option*/ ctx[28].value)
  12945. : /*optionLabelStyle*/ ctx[14]);
  12946. attr(span0, "class", span0_class_value = arrayJoin(["PinturaDropdownOptionLabel", /*optionLabelClass*/ ctx[10]]));
  12947. attr(span1, "slot", "option");
  12948. },
  12949. m(target, anchor) {
  12950. insert(target, span1, anchor);
  12951. if (if_block) if_block.m(span1, null);
  12952. append(span1, t0);
  12953. append(span1, span0);
  12954. append(span0, t1);
  12955. current = true;
  12956. },
  12957. p(ctx, dirty) {
  12958. if (/*option*/ ctx[28].icon) {
  12959. if (if_block) {
  12960. if_block.p(ctx, dirty);
  12961. if (dirty & /*option*/ 268435456) {
  12962. transition_in(if_block, 1);
  12963. }
  12964. } else {
  12965. if_block = create_if_block$a(ctx);
  12966. if_block.c();
  12967. transition_in(if_block, 1);
  12968. if_block.m(span1, t0);
  12969. }
  12970. } else if (if_block) {
  12971. group_outros();
  12972. transition_out(if_block, 1, 1, () => {
  12973. if_block = null;
  12974. });
  12975. check_outros();
  12976. }
  12977. if ((!current || dirty & /*option*/ 268435456) && t1_value !== (t1_value = /*option*/ ctx[28].label + "")) set_data(t1, t1_value);
  12978. if (!current || dirty & /*optionLabelStyle, option*/ 268451840 && span0_style_value !== (span0_style_value = isFunction(/*optionLabelStyle*/ ctx[14])
  12979. ? /*optionLabelStyle*/ ctx[14](/*option*/ ctx[28].value)
  12980. : /*optionLabelStyle*/ ctx[14])) {
  12981. attr(span0, "style", span0_style_value);
  12982. }
  12983. if (!current || dirty & /*optionLabelClass*/ 1024 && span0_class_value !== (span0_class_value = arrayJoin(["PinturaDropdownOptionLabel", /*optionLabelClass*/ ctx[10]]))) {
  12984. attr(span0, "class", span0_class_value);
  12985. }
  12986. },
  12987. i(local) {
  12988. if (current) return;
  12989. transition_in(if_block);
  12990. current = true;
  12991. },
  12992. o(local) {
  12993. transition_out(if_block);
  12994. current = false;
  12995. },
  12996. d(detaching) {
  12997. if (detaching) detach(span1);
  12998. if (if_block) if_block.d();
  12999. }
  13000. };
  13001. }
  13002. // (102:4)
  13003. function create_details_slot$2(ctx) {
  13004. let div;
  13005. let radiogroup;
  13006. let current;
  13007. let mounted;
  13008. let dispose;
  13009. radiogroup = new RadioGroup({
  13010. props: {
  13011. name: /*name*/ ctx[7],
  13012. value: /*value*/ ctx[9],
  13013. selectedIndex: /*selectedIndex*/ ctx[8],
  13014. optionFilter: /*optionFilter*/ ctx[11],
  13015. optionMapper: /*optionMapper*/ ctx[12],
  13016. optionLabelClass: arrayJoin(["PinturaDropdownOptionLabel", /*optionLabelClass*/ ctx[10]]),
  13017. optionGroupClass: "PinturaDropdownOptionGroup",
  13018. optionClass: "PinturaDropdownOption",
  13019. options: /*localizedOptions*/ ctx[16],
  13020. onchange: /*handleSelect*/ ctx[19],
  13021. $$slots: {
  13022. option: [
  13023. create_option_slot$4,
  13024. ({ option }) => ({ 28: option }),
  13025. ({ option }) => option ? 268435456 : 0
  13026. ],
  13027. group: [
  13028. create_group_slot$1,
  13029. ({ option }) => ({ 28: option }),
  13030. ({ option }) => option ? 268435456 : 0
  13031. ]
  13032. },
  13033. $$scope: { ctx }
  13034. }
  13035. });
  13036. return {
  13037. c() {
  13038. div = element("div");
  13039. create_component(radiogroup.$$.fragment);
  13040. attr(div, "class", "PinturaDropdownPanel");
  13041. attr(div, "slot", "details");
  13042. },
  13043. m(target, anchor) {
  13044. insert(target, div, anchor);
  13045. mount_component(radiogroup, div, null);
  13046. current = true;
  13047. if (!mounted) {
  13048. dispose = listen(div, "keydown", /*handleKeydown*/ ctx[21]);
  13049. mounted = true;
  13050. }
  13051. },
  13052. p(ctx, dirty) {
  13053. const radiogroup_changes = {};
  13054. if (dirty & /*name*/ 128) radiogroup_changes.name = /*name*/ ctx[7];
  13055. if (dirty & /*value*/ 512) radiogroup_changes.value = /*value*/ ctx[9];
  13056. if (dirty & /*selectedIndex*/ 256) radiogroup_changes.selectedIndex = /*selectedIndex*/ ctx[8];
  13057. if (dirty & /*optionFilter*/ 2048) radiogroup_changes.optionFilter = /*optionFilter*/ ctx[11];
  13058. if (dirty & /*optionMapper*/ 4096) radiogroup_changes.optionMapper = /*optionMapper*/ ctx[12];
  13059. if (dirty & /*optionLabelClass*/ 1024) radiogroup_changes.optionLabelClass = arrayJoin(["PinturaDropdownOptionLabel", /*optionLabelClass*/ ctx[10]]);
  13060. if (dirty & /*localizedOptions*/ 65536) radiogroup_changes.options = /*localizedOptions*/ ctx[16];
  13061. if (dirty & /*$$scope, optionLabelStyle, option, optionLabelClass, optionIconStyle*/ 805331968) {
  13062. radiogroup_changes.$$scope = { dirty, ctx };
  13063. }
  13064. radiogroup.$set(radiogroup_changes);
  13065. },
  13066. i(local) {
  13067. if (current) return;
  13068. transition_in(radiogroup.$$.fragment, local);
  13069. current = true;
  13070. },
  13071. o(local) {
  13072. transition_out(radiogroup.$$.fragment, local);
  13073. current = false;
  13074. },
  13075. d(detaching) {
  13076. if (detaching) detach(div);
  13077. destroy_component(radiogroup);
  13078. mounted = false;
  13079. dispose();
  13080. }
  13081. };
  13082. }
  13083. function create_fragment$y(ctx) {
  13084. let details;
  13085. let updating_isActive;
  13086. let current;
  13087. function details_isActive_binding(value) {
  13088. /*details_isActive_binding*/ ctx[26](value);
  13089. }
  13090. let details_props = {
  13091. onshow: /*handleShowPanel*/ ctx[20],
  13092. buttonClass: arrayJoin([
  13093. "PinturaDropdownButton",
  13094. /*klass*/ ctx[0],
  13095. /*hideLabel*/ ctx[5] && "PinturaDropdownIconOnly"
  13096. ]),
  13097. $$slots: {
  13098. details: [create_details_slot$2],
  13099. label: [create_label_slot$2]
  13100. },
  13101. $$scope: { ctx }
  13102. };
  13103. if (/*dropdownVisible*/ ctx[17] !== void 0) {
  13104. details_props.isActive = /*dropdownVisible*/ ctx[17];
  13105. }
  13106. details = new Details({ props: details_props });
  13107. binding_callbacks.push(() => bind(details, "isActive", details_isActive_binding));
  13108. return {
  13109. c() {
  13110. create_component(details.$$.fragment);
  13111. },
  13112. m(target, anchor) {
  13113. mount_component(details, target, anchor);
  13114. current = true;
  13115. },
  13116. p(ctx, [dirty]) {
  13117. const details_changes = {};
  13118. if (dirty & /*klass, hideLabel*/ 33) details_changes.buttonClass = arrayJoin([
  13119. "PinturaDropdownButton",
  13120. /*klass*/ ctx[0],
  13121. /*hideLabel*/ ctx[5] && "PinturaDropdownIconOnly"
  13122. ]);
  13123. if (dirty & /*$$scope, name, value, selectedIndex, optionFilter, optionMapper, optionLabelClass, localizedOptions, optionLabelStyle, optionIconStyle, title, locale, innerClass, labelClass, hideLabel, label, selectedLabel, icon*/ 537264126) {
  13124. details_changes.$$scope = { dirty, ctx };
  13125. }
  13126. if (!updating_isActive && dirty & /*dropdownVisible*/ 131072) {
  13127. updating_isActive = true;
  13128. details_changes.isActive = /*dropdownVisible*/ ctx[17];
  13129. add_flush_callback(() => updating_isActive = false);
  13130. }
  13131. details.$set(details_changes);
  13132. },
  13133. i(local) {
  13134. if (current) return;
  13135. transition_in(details.$$.fragment, local);
  13136. current = true;
  13137. },
  13138. o(local) {
  13139. transition_out(details.$$.fragment, local);
  13140. current = false;
  13141. },
  13142. d(detaching) {
  13143. destroy_component(details, detaching);
  13144. }
  13145. };
  13146. }
  13147. function instance$y($$self, $$props, $$invalidate) {
  13148. let localizedOptions;
  13149. let selectedLabel;
  13150. let { class: klass = undefined } = $$props;
  13151. let { title = undefined } = $$props;
  13152. let { label = undefined } = $$props;
  13153. let { labelClass = undefined } = $$props;
  13154. let { innerClass = undefined } = $$props;
  13155. let { hideLabel = false } = $$props;
  13156. let { icon = undefined } = $$props;
  13157. let { name = undefined } = $$props;
  13158. let { options = [] } = $$props;
  13159. let { selectedIndex = -1 } = $$props;
  13160. let { value = undefined } = $$props;
  13161. let { optionLabelClass = undefined } = $$props;
  13162. let { optionFilter = undefined } = $$props;
  13163. let { optionMapper = undefined } = $$props;
  13164. let { optionIconStyle = undefined } = $$props;
  13165. let { optionLabelStyle = undefined } = $$props;
  13166. let { locale = undefined } = $$props;
  13167. let { onchange = noop$1 } = $$props;
  13168. let { onload = noop$1 } = $$props;
  13169. let { ondestroy = noop$1 } = $$props;
  13170. const getUndefinedOptionLabel = options => {
  13171. const option = options.find(option => option[0] === undefined);
  13172. if (!option) return undefined;
  13173. return option[1];
  13174. };
  13175. let dropdownVisible;
  13176. const handleSelect = detail => {
  13177. // triggers label update
  13178. $$invalidate(18, selectedLabel = detail.value);
  13179. // update value
  13180. onchange(detail);
  13181. // hide details
  13182. $$invalidate(17, dropdownVisible = false);
  13183. };
  13184. const handleShowPanel = ({ e, panel }) => {
  13185. if (e && e.key && (/up|down/i).test(e.key)) return panel.querySelector("input:not([disabled])").focus();
  13186. panel.querySelector("fieldset").focus();
  13187. };
  13188. const handleKeydown = e => {
  13189. // don't allow tabbing ([tab] is also blocked in normal <select>)
  13190. if ((/tab/i).test(e.key)) e.preventDefault();
  13191. };
  13192. onMount(() => onload({ options }));
  13193. onDestroy(() => ondestroy({ options }));
  13194. function details_isActive_binding(value) {
  13195. dropdownVisible = value;
  13196. $$invalidate(17, dropdownVisible);
  13197. }
  13198. $$self.$$set = $$props => {
  13199. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  13200. if ("title" in $$props) $$invalidate(1, title = $$props.title);
  13201. if ("label" in $$props) $$invalidate(2, label = $$props.label);
  13202. if ("labelClass" in $$props) $$invalidate(3, labelClass = $$props.labelClass);
  13203. if ("innerClass" in $$props) $$invalidate(4, innerClass = $$props.innerClass);
  13204. if ("hideLabel" in $$props) $$invalidate(5, hideLabel = $$props.hideLabel);
  13205. if ("icon" in $$props) $$invalidate(6, icon = $$props.icon);
  13206. if ("name" in $$props) $$invalidate(7, name = $$props.name);
  13207. if ("options" in $$props) $$invalidate(22, options = $$props.options);
  13208. if ("selectedIndex" in $$props) $$invalidate(8, selectedIndex = $$props.selectedIndex);
  13209. if ("value" in $$props) $$invalidate(9, value = $$props.value);
  13210. if ("optionLabelClass" in $$props) $$invalidate(10, optionLabelClass = $$props.optionLabelClass);
  13211. if ("optionFilter" in $$props) $$invalidate(11, optionFilter = $$props.optionFilter);
  13212. if ("optionMapper" in $$props) $$invalidate(12, optionMapper = $$props.optionMapper);
  13213. if ("optionIconStyle" in $$props) $$invalidate(13, optionIconStyle = $$props.optionIconStyle);
  13214. if ("optionLabelStyle" in $$props) $$invalidate(14, optionLabelStyle = $$props.optionLabelStyle);
  13215. if ("locale" in $$props) $$invalidate(15, locale = $$props.locale);
  13216. if ("onchange" in $$props) $$invalidate(23, onchange = $$props.onchange);
  13217. if ("onload" in $$props) $$invalidate(24, onload = $$props.onload);
  13218. if ("ondestroy" in $$props) $$invalidate(25, ondestroy = $$props.ondestroy);
  13219. };
  13220. $$self.$$.update = () => {
  13221. if ($$self.$$.dirty & /*locale, options*/ 4227072) {
  13222. $$invalidate(16, localizedOptions = locale ? localizeOptions$1(options, locale) : options);
  13223. }
  13224. if ($$self.$$.dirty & /*localizedOptions, value*/ 66048) {
  13225. $$invalidate(18, selectedLabel = localizedOptions.reduce(
  13226. (prev, curr) => {
  13227. if (prev) return prev;
  13228. const item = Array.isArray(curr) ? curr : [curr, curr];
  13229. const [optionValue, optionLabel] = item;
  13230. if (isDeepEqual(optionValue, value)) return optionLabel;
  13231. },
  13232. undefined
  13233. ) || getUndefinedOptionLabel(localizedOptions));
  13234. }
  13235. };
  13236. return [
  13237. klass,
  13238. title,
  13239. label,
  13240. labelClass,
  13241. innerClass,
  13242. hideLabel,
  13243. icon,
  13244. name,
  13245. selectedIndex,
  13246. value,
  13247. optionLabelClass,
  13248. optionFilter,
  13249. optionMapper,
  13250. optionIconStyle,
  13251. optionLabelStyle,
  13252. locale,
  13253. localizedOptions,
  13254. dropdownVisible,
  13255. selectedLabel,
  13256. handleSelect,
  13257. handleShowPanel,
  13258. handleKeydown,
  13259. options,
  13260. onchange,
  13261. onload,
  13262. ondestroy,
  13263. details_isActive_binding
  13264. ];
  13265. }
  13266. class Dropdown extends SvelteComponent {
  13267. constructor(options) {
  13268. super();
  13269. init(this, options, instance$y, create_fragment$y, safe_not_equal, {
  13270. class: 0,
  13271. title: 1,
  13272. label: 2,
  13273. labelClass: 3,
  13274. innerClass: 4,
  13275. hideLabel: 5,
  13276. icon: 6,
  13277. name: 7,
  13278. options: 22,
  13279. selectedIndex: 8,
  13280. value: 9,
  13281. optionLabelClass: 10,
  13282. optionFilter: 11,
  13283. optionMapper: 12,
  13284. optionIconStyle: 13,
  13285. optionLabelStyle: 14,
  13286. locale: 15,
  13287. onchange: 23,
  13288. onload: 24,
  13289. ondestroy: 25
  13290. });
  13291. }
  13292. }
  13293. var numberRoundTo = (value, fraction) => {
  13294. fraction = 1 / fraction;
  13295. return Math.round(value * fraction) / fraction;
  13296. };
  13297. var toFraction = (value, min, max) => (value - min) / (max - min);
  13298. /* src/core/ui/components/Slider.svelte generated by Svelte v3.37.0 */
  13299. function create_default_slot_1$5(ctx) {
  13300. let path;
  13301. return {
  13302. c() {
  13303. path = svg_element("path");
  13304. attr(path, "d", "M8 12 h8 M12 8 v8");
  13305. },
  13306. m(target, anchor) {
  13307. insert(target, path, anchor);
  13308. },
  13309. d(detaching) {
  13310. if (detaching) detach(path);
  13311. }
  13312. };
  13313. }
  13314. // (153:8) <Icon>
  13315. function create_default_slot$d(ctx) {
  13316. let path;
  13317. return {
  13318. c() {
  13319. path = svg_element("path");
  13320. attr(path, "d", "M9 12 h6");
  13321. },
  13322. m(target, anchor) {
  13323. insert(target, path, anchor);
  13324. },
  13325. d(detaching) {
  13326. if (detaching) detach(path);
  13327. }
  13328. };
  13329. }
  13330. function create_fragment$x(ctx) {
  13331. let div4;
  13332. let div3;
  13333. let input_1;
  13334. let t0;
  13335. let div0;
  13336. let t1;
  13337. let div2;
  13338. let div1;
  13339. let t2;
  13340. let button0;
  13341. let icon0;
  13342. let t3;
  13343. let button1;
  13344. let icon1;
  13345. let div4_class_value;
  13346. let current;
  13347. let mounted;
  13348. let dispose;
  13349. icon0 = new Icon({
  13350. props: {
  13351. $$slots: { default: [create_default_slot_1$5] },
  13352. $$scope: { ctx }
  13353. }
  13354. });
  13355. icon1 = new Icon({
  13356. props: {
  13357. $$slots: { default: [create_default_slot$d] },
  13358. $$scope: { ctx }
  13359. }
  13360. });
  13361. return {
  13362. c() {
  13363. div4 = element("div");
  13364. div3 = element("div");
  13365. input_1 = element("input");
  13366. t0 = space();
  13367. div0 = element("div");
  13368. t1 = space();
  13369. div2 = element("div");
  13370. div1 = element("div");
  13371. t2 = space();
  13372. button0 = element("button");
  13373. create_component(icon0.$$.fragment);
  13374. t3 = space();
  13375. button1 = element("button");
  13376. create_component(icon1.$$.fragment);
  13377. attr(input_1, "type", "range");
  13378. attr(input_1, "id", /*id*/ ctx[3]);
  13379. attr(input_1, "min", /*min*/ ctx[0]);
  13380. attr(input_1, "max", /*max*/ ctx[1]);
  13381. attr(input_1, "step", /*step*/ ctx[2]);
  13382. input_1.value = /*numberValue*/ ctx[8];
  13383. attr(div0, "class", "PinturaSliderTrack");
  13384. attr(div0, "style", /*trackStyle*/ ctx[4]);
  13385. attr(div1, "class", "PinturaSliderKnob");
  13386. attr(div1, "style", /*knobStyle*/ ctx[5]);
  13387. attr(div2, "class", "PinturaSliderKnobController");
  13388. attr(div2, "style", /*knobControllerStyle*/ ctx[10]);
  13389. attr(div3, "class", "PinturaSliderControl");
  13390. attr(button0, "type", "button");
  13391. attr(button0, "aria-label", "Increase");
  13392. attr(button1, "type", "button");
  13393. attr(button1, "aria-label", "Decrease");
  13394. attr(div4, "class", div4_class_value = arrayJoin(["PinturaSlider", /*klass*/ ctx[7]]));
  13395. attr(div4, "data-direction", /*direction*/ ctx[6]);
  13396. },
  13397. m(target, anchor) {
  13398. insert(target, div4, anchor);
  13399. append(div4, div3);
  13400. append(div3, input_1);
  13401. /*input_1_binding*/ ctx[22](input_1);
  13402. append(div3, t0);
  13403. append(div3, div0);
  13404. append(div3, t1);
  13405. append(div3, div2);
  13406. append(div2, div1);
  13407. append(div4, t2);
  13408. append(div4, button0);
  13409. mount_component(icon0, button0, null);
  13410. append(div4, t3);
  13411. append(div4, button1);
  13412. mount_component(icon1, button1, null);
  13413. current = true;
  13414. if (!mounted) {
  13415. dispose = [
  13416. listen(input_1, "pointerdown", /*handlePointerDown*/ ctx[13]),
  13417. listen(input_1, "input", /*handleInput*/ ctx[11]),
  13418. listen(input_1, "nudge", /*handleNudge*/ ctx[12]),
  13419. action_destroyer(nudgeable.call(null, input_1)),
  13420. listen(button0, "pointerdown", /*handleUpdaterDown*/ ctx[14](1)),
  13421. listen(button1, "pointerdown", /*handleUpdaterDown*/ ctx[14](-1))
  13422. ];
  13423. mounted = true;
  13424. }
  13425. },
  13426. p(ctx, dirty) {
  13427. if (!current || dirty[0] & /*id*/ 8) {
  13428. attr(input_1, "id", /*id*/ ctx[3]);
  13429. }
  13430. if (!current || dirty[0] & /*min*/ 1) {
  13431. attr(input_1, "min", /*min*/ ctx[0]);
  13432. }
  13433. if (!current || dirty[0] & /*max*/ 2) {
  13434. attr(input_1, "max", /*max*/ ctx[1]);
  13435. }
  13436. if (!current || dirty[0] & /*step*/ 4) {
  13437. attr(input_1, "step", /*step*/ ctx[2]);
  13438. }
  13439. if (!current || dirty[0] & /*numberValue*/ 256) {
  13440. input_1.value = /*numberValue*/ ctx[8];
  13441. }
  13442. if (!current || dirty[0] & /*trackStyle*/ 16) {
  13443. attr(div0, "style", /*trackStyle*/ ctx[4]);
  13444. }
  13445. if (!current || dirty[0] & /*knobStyle*/ 32) {
  13446. attr(div1, "style", /*knobStyle*/ ctx[5]);
  13447. }
  13448. if (!current || dirty[0] & /*knobControllerStyle*/ 1024) {
  13449. attr(div2, "style", /*knobControllerStyle*/ ctx[10]);
  13450. }
  13451. const icon0_changes = {};
  13452. if (dirty[1] & /*$$scope*/ 512) {
  13453. icon0_changes.$$scope = { dirty, ctx };
  13454. }
  13455. icon0.$set(icon0_changes);
  13456. const icon1_changes = {};
  13457. if (dirty[1] & /*$$scope*/ 512) {
  13458. icon1_changes.$$scope = { dirty, ctx };
  13459. }
  13460. icon1.$set(icon1_changes);
  13461. if (!current || dirty[0] & /*klass*/ 128 && div4_class_value !== (div4_class_value = arrayJoin(["PinturaSlider", /*klass*/ ctx[7]]))) {
  13462. attr(div4, "class", div4_class_value);
  13463. }
  13464. if (!current || dirty[0] & /*direction*/ 64) {
  13465. attr(div4, "data-direction", /*direction*/ ctx[6]);
  13466. }
  13467. },
  13468. i(local) {
  13469. if (current) return;
  13470. transition_in(icon0.$$.fragment, local);
  13471. transition_in(icon1.$$.fragment, local);
  13472. current = true;
  13473. },
  13474. o(local) {
  13475. transition_out(icon0.$$.fragment, local);
  13476. transition_out(icon1.$$.fragment, local);
  13477. current = false;
  13478. },
  13479. d(detaching) {
  13480. if (detaching) detach(div4);
  13481. /*input_1_binding*/ ctx[22](null);
  13482. destroy_component(icon0);
  13483. destroy_component(icon1);
  13484. mounted = false;
  13485. run_all(dispose);
  13486. }
  13487. };
  13488. }
  13489. function instance$x($$self, $$props, $$invalidate) {
  13490. let numberValue;
  13491. let range;
  13492. let position;
  13493. let axis;
  13494. let dimension;
  13495. let offsetSizeProp;
  13496. let offsetAxisProp;
  13497. let pageAxisProp;
  13498. let knobControllerStyle;
  13499. let { min = 0 } = $$props;
  13500. let { max = 100 } = $$props;
  13501. let { step = 1 } = $$props;
  13502. let { id = undefined } = $$props;
  13503. let { value = 0 } = $$props;
  13504. let { trackStyle = undefined } = $$props;
  13505. let { knobStyle = undefined } = $$props;
  13506. let { onchange = undefined } = $$props;
  13507. let { direction = "x" } = $$props;
  13508. let { getValue = passthrough } = $$props;
  13509. let { setValue = passthrough } = $$props;
  13510. let { class: klass = undefined } = $$props;
  13511. let input;
  13512. let inputSize;
  13513. let inputOffset;
  13514. let pageOffset;
  13515. let valuePrev;
  13516. const formatValue = value => setValue(numberRoundTo(clamp(value, min, max), step));
  13517. const setValueByOffset = (offset, size) => {
  13518. $$invalidate(15, value = formatValue(min + offset / size * range));
  13519. if (value === valuePrev) return;
  13520. valuePrev = value;
  13521. onchange(value);
  13522. };
  13523. const handleInput = e => {
  13524. // already handled by pointer events
  13525. if (inputSize) return;
  13526. $$invalidate(15, value = setValue(parseFloat(e.target.value)));
  13527. if (value === valuePrev) return;
  13528. valuePrev = value;
  13529. onchange(value);
  13530. };
  13531. const handleNudge = e => {
  13532. const size = input[offsetSizeProp];
  13533. const offset = numberValue / range * size;
  13534. setValueByOffset(offset + e.detail[direction], size);
  13535. };
  13536. const handlePointerDown = e => {
  13537. e.stopPropagation();
  13538. inputSize = input[offsetSizeProp];
  13539. inputOffset = e[offsetAxisProp];
  13540. pageOffset = e[pageAxisProp];
  13541. setValueByOffset(inputOffset, inputSize);
  13542. document.documentElement.addEventListener("pointermove", handlePointerMove);
  13543. document.documentElement.addEventListener("pointerup", handlePointerUp);
  13544. };
  13545. const handlePointerMove = e => {
  13546. const d = e[pageAxisProp] - pageOffset;
  13547. setValueByOffset(inputOffset + d, inputSize);
  13548. };
  13549. const handlePointerUp = e => {
  13550. inputSize = undefined;
  13551. document.documentElement.removeEventListener("pointermove", handlePointerMove);
  13552. document.documentElement.removeEventListener("pointerup", handlePointerUp);
  13553. onchange(value);
  13554. };
  13555. const update = () => {
  13556. $$invalidate(15, value = formatValue(numberValue + updateDir * step));
  13557. onchange(value);
  13558. };
  13559. let updateTimer;
  13560. let updateDir = 1;
  13561. let didUpdate = false;
  13562. const handleUpdaterDown = dir => e => {
  13563. updateDir = dir;
  13564. didUpdate = false;
  13565. updateTimer = setInterval(
  13566. () => {
  13567. didUpdate = true;
  13568. update();
  13569. },
  13570. 100
  13571. );
  13572. document.addEventListener("pointercancel", handleUpdaterUp);
  13573. document.addEventListener("pointerup", handleUpdaterUp);
  13574. };
  13575. const handleUpdaterUp = e => {
  13576. clearTimeout(updateTimer);
  13577. if (!didUpdate) update();
  13578. document.removeEventListener("pointerup", handleUpdaterUp);
  13579. };
  13580. function input_1_binding($$value) {
  13581. binding_callbacks[$$value ? "unshift" : "push"](() => {
  13582. input = $$value;
  13583. $$invalidate(9, input);
  13584. });
  13585. }
  13586. $$self.$$set = $$props => {
  13587. if ("min" in $$props) $$invalidate(0, min = $$props.min);
  13588. if ("max" in $$props) $$invalidate(1, max = $$props.max);
  13589. if ("step" in $$props) $$invalidate(2, step = $$props.step);
  13590. if ("id" in $$props) $$invalidate(3, id = $$props.id);
  13591. if ("value" in $$props) $$invalidate(15, value = $$props.value);
  13592. if ("trackStyle" in $$props) $$invalidate(4, trackStyle = $$props.trackStyle);
  13593. if ("knobStyle" in $$props) $$invalidate(5, knobStyle = $$props.knobStyle);
  13594. if ("onchange" in $$props) $$invalidate(16, onchange = $$props.onchange);
  13595. if ("direction" in $$props) $$invalidate(6, direction = $$props.direction);
  13596. if ("getValue" in $$props) $$invalidate(17, getValue = $$props.getValue);
  13597. if ("setValue" in $$props) $$invalidate(18, setValue = $$props.setValue);
  13598. if ("class" in $$props) $$invalidate(7, klass = $$props.class);
  13599. };
  13600. $$self.$$.update = () => {
  13601. if ($$self.$$.dirty[0] & /*value, getValue*/ 163840) {
  13602. $$invalidate(8, numberValue = value !== undefined ? getValue(value) : 0);
  13603. }
  13604. if ($$self.$$.dirty[0] & /*max, min*/ 3) {
  13605. range = max - min;
  13606. }
  13607. if ($$self.$$.dirty[0] & /*numberValue, min, max*/ 259) {
  13608. $$invalidate(19, position = toFraction(numberValue, min, max) * 100);
  13609. }
  13610. if ($$self.$$.dirty[0] & /*direction*/ 64) {
  13611. $$invalidate(20, axis = direction.toUpperCase());
  13612. }
  13613. if ($$self.$$.dirty[0] & /*direction*/ 64) {
  13614. $$invalidate(21, dimension = direction === "x" ? "Width" : "Height");
  13615. }
  13616. if ($$self.$$.dirty[0] & /*dimension*/ 2097152) {
  13617. offsetSizeProp = `offset${dimension}`;
  13618. }
  13619. if ($$self.$$.dirty[0] & /*axis*/ 1048576) {
  13620. offsetAxisProp = `offset${axis}`;
  13621. }
  13622. if ($$self.$$.dirty[0] & /*axis*/ 1048576) {
  13623. pageAxisProp = `page${axis}`;
  13624. }
  13625. if ($$self.$$.dirty[0] & /*axis, position*/ 1572864) {
  13626. $$invalidate(10, knobControllerStyle = `transform: translate${axis}(${position}%)`);
  13627. }
  13628. };
  13629. return [
  13630. min,
  13631. max,
  13632. step,
  13633. id,
  13634. trackStyle,
  13635. knobStyle,
  13636. direction,
  13637. klass,
  13638. numberValue,
  13639. input,
  13640. knobControllerStyle,
  13641. handleInput,
  13642. handleNudge,
  13643. handlePointerDown,
  13644. handleUpdaterDown,
  13645. value,
  13646. onchange,
  13647. getValue,
  13648. setValue,
  13649. position,
  13650. axis,
  13651. dimension,
  13652. input_1_binding
  13653. ];
  13654. }
  13655. class Slider extends SvelteComponent {
  13656. constructor(options) {
  13657. super();
  13658. init(
  13659. this,
  13660. options,
  13661. instance$x,
  13662. create_fragment$x,
  13663. safe_not_equal,
  13664. {
  13665. min: 0,
  13666. max: 1,
  13667. step: 2,
  13668. id: 3,
  13669. value: 15,
  13670. trackStyle: 4,
  13671. knobStyle: 5,
  13672. onchange: 16,
  13673. direction: 6,
  13674. getValue: 17,
  13675. setValue: 18,
  13676. class: 7
  13677. },
  13678. [-1, -1]
  13679. );
  13680. }
  13681. }
  13682. /* src/core/ui/components/ToggleSlider.svelte generated by Svelte v3.37.0 */
  13683. function create_if_block$9(ctx) {
  13684. let icon_1;
  13685. let current;
  13686. icon_1 = new Icon({
  13687. props: {
  13688. class: "PinturaButtonIcon",
  13689. $$slots: { default: [create_default_slot$c] },
  13690. $$scope: { ctx }
  13691. }
  13692. });
  13693. return {
  13694. c() {
  13695. create_component(icon_1.$$.fragment);
  13696. },
  13697. m(target, anchor) {
  13698. mount_component(icon_1, target, anchor);
  13699. current = true;
  13700. },
  13701. p(ctx, dirty) {
  13702. const icon_1_changes = {};
  13703. if (dirty & /*$$scope, icon*/ 262148) {
  13704. icon_1_changes.$$scope = { dirty, ctx };
  13705. }
  13706. icon_1.$set(icon_1_changes);
  13707. },
  13708. i(local) {
  13709. if (current) return;
  13710. transition_in(icon_1.$$.fragment, local);
  13711. current = true;
  13712. },
  13713. o(local) {
  13714. transition_out(icon_1.$$.fragment, local);
  13715. current = false;
  13716. },
  13717. d(detaching) {
  13718. destroy_component(icon_1, detaching);
  13719. }
  13720. };
  13721. }
  13722. // (51:12) <Icon class="PinturaButtonIcon">
  13723. function create_default_slot$c(ctx) {
  13724. let g;
  13725. return {
  13726. c() {
  13727. g = svg_element("g");
  13728. },
  13729. m(target, anchor) {
  13730. insert(target, g, anchor);
  13731. g.innerHTML = /*icon*/ ctx[2];
  13732. },
  13733. p(ctx, dirty) {
  13734. if (dirty & /*icon*/ 4) g.innerHTML = /*icon*/ ctx[2]; },
  13735. d(detaching) {
  13736. if (detaching) detach(g);
  13737. }
  13738. };
  13739. }
  13740. // (45:4)
  13741. function create_label_slot$1(ctx) {
  13742. let span1;
  13743. let t0;
  13744. let span0;
  13745. let t1;
  13746. let span0_class_value;
  13747. let span1_title_value;
  13748. let span1_class_value;
  13749. let current;
  13750. let if_block = /*icon*/ ctx[2] && create_if_block$9(ctx);
  13751. return {
  13752. c() {
  13753. span1 = element("span");
  13754. if (if_block) if_block.c();
  13755. t0 = space();
  13756. span0 = element("span");
  13757. t1 = text(/*currentLabel*/ ctx[8]);
  13758. attr(span0, "class", span0_class_value = arrayJoin([
  13759. "PinturaButtonLabel",
  13760. /*labelClass*/ ctx[3],
  13761. /*hideLabel*/ ctx[5] && "implicit"
  13762. ]));
  13763. attr(span1, "slot", "label");
  13764. attr(span1, "title", span1_title_value = localize(/*title*/ ctx[1], /*locale*/ ctx[6]));
  13765. attr(span1, "class", span1_class_value = arrayJoin(["PinturaButtonInner", /*innerClass*/ ctx[4]]));
  13766. },
  13767. m(target, anchor) {
  13768. insert(target, span1, anchor);
  13769. if (if_block) if_block.m(span1, null);
  13770. append(span1, t0);
  13771. append(span1, span0);
  13772. append(span0, t1);
  13773. current = true;
  13774. },
  13775. p(ctx, dirty) {
  13776. if (/*icon*/ ctx[2]) {
  13777. if (if_block) {
  13778. if_block.p(ctx, dirty);
  13779. if (dirty & /*icon*/ 4) {
  13780. transition_in(if_block, 1);
  13781. }
  13782. } else {
  13783. if_block = create_if_block$9(ctx);
  13784. if_block.c();
  13785. transition_in(if_block, 1);
  13786. if_block.m(span1, t0);
  13787. }
  13788. } else if (if_block) {
  13789. group_outros();
  13790. transition_out(if_block, 1, 1, () => {
  13791. if_block = null;
  13792. });
  13793. check_outros();
  13794. }
  13795. if (!current || dirty & /*currentLabel*/ 256) set_data(t1, /*currentLabel*/ ctx[8]);
  13796. if (!current || dirty & /*labelClass, hideLabel*/ 40 && span0_class_value !== (span0_class_value = arrayJoin([
  13797. "PinturaButtonLabel",
  13798. /*labelClass*/ ctx[3],
  13799. /*hideLabel*/ ctx[5] && "implicit"
  13800. ]))) {
  13801. attr(span0, "class", span0_class_value);
  13802. }
  13803. if (!current || dirty & /*title, locale*/ 66 && span1_title_value !== (span1_title_value = localize(/*title*/ ctx[1], /*locale*/ ctx[6]))) {
  13804. attr(span1, "title", span1_title_value);
  13805. }
  13806. if (!current || dirty & /*innerClass*/ 16 && span1_class_value !== (span1_class_value = arrayJoin(["PinturaButtonInner", /*innerClass*/ ctx[4]]))) {
  13807. attr(span1, "class", span1_class_value);
  13808. }
  13809. },
  13810. i(local) {
  13811. if (current) return;
  13812. transition_in(if_block);
  13813. current = true;
  13814. },
  13815. o(local) {
  13816. transition_out(if_block);
  13817. current = false;
  13818. },
  13819. d(detaching) {
  13820. if (detaching) detach(span1);
  13821. if (if_block) if_block.d();
  13822. }
  13823. };
  13824. }
  13825. // (58:4)
  13826. function create_details_slot$1(ctx) {
  13827. let div;
  13828. let slider;
  13829. let current;
  13830. let mounted;
  13831. let dispose;
  13832. const slider_spread_levels = [
  13833. /*$$restProps*/ ctx[11],
  13834. { value: /*value*/ ctx[7] },
  13835. { onchange: /*handleChangeValue*/ ctx[10] }
  13836. ];
  13837. let slider_props = {};
  13838. for (let i = 0; i < slider_spread_levels.length; i += 1) {
  13839. slider_props = assign(slider_props, slider_spread_levels[i]);
  13840. }
  13841. slider = new Slider({ props: slider_props });
  13842. return {
  13843. c() {
  13844. div = element("div");
  13845. create_component(slider.$$.fragment);
  13846. attr(div, "slot", "details");
  13847. },
  13848. m(target, anchor) {
  13849. insert(target, div, anchor);
  13850. mount_component(slider, div, null);
  13851. current = true;
  13852. if (!mounted) {
  13853. dispose = listen(div, "keydown", /*handleKeydown*/ ctx[9]);
  13854. mounted = true;
  13855. }
  13856. },
  13857. p(ctx, dirty) {
  13858. const slider_changes = (dirty & /*$$restProps, value, handleChangeValue*/ 3200)
  13859. ? get_spread_update(slider_spread_levels, [
  13860. dirty & /*$$restProps*/ 2048 && get_spread_object(/*$$restProps*/ ctx[11]),
  13861. dirty & /*value*/ 128 && { value: /*value*/ ctx[7] },
  13862. dirty & /*handleChangeValue*/ 1024 && { onchange: /*handleChangeValue*/ ctx[10] }
  13863. ])
  13864. : {};
  13865. slider.$set(slider_changes);
  13866. },
  13867. i(local) {
  13868. if (current) return;
  13869. transition_in(slider.$$.fragment, local);
  13870. current = true;
  13871. },
  13872. o(local) {
  13873. transition_out(slider.$$.fragment, local);
  13874. current = false;
  13875. },
  13876. d(detaching) {
  13877. if (detaching) detach(div);
  13878. destroy_component(slider);
  13879. mounted = false;
  13880. dispose();
  13881. }
  13882. };
  13883. }
  13884. function create_fragment$w(ctx) {
  13885. let details;
  13886. let current;
  13887. details = new Details({
  13888. props: {
  13889. panelClass: "PinturaSliderPanel",
  13890. buttonClass: arrayJoin([
  13891. "PinturaSliderButton",
  13892. /*klass*/ ctx[0],
  13893. /*hideLabel*/ ctx[5] && "PinturaSliderIconOnly"
  13894. ]),
  13895. $$slots: {
  13896. details: [create_details_slot$1],
  13897. label: [create_label_slot$1]
  13898. },
  13899. $$scope: { ctx }
  13900. }
  13901. });
  13902. return {
  13903. c() {
  13904. create_component(details.$$.fragment);
  13905. },
  13906. m(target, anchor) {
  13907. mount_component(details, target, anchor);
  13908. current = true;
  13909. },
  13910. p(ctx, [dirty]) {
  13911. const details_changes = {};
  13912. if (dirty & /*klass, hideLabel*/ 33) details_changes.buttonClass = arrayJoin([
  13913. "PinturaSliderButton",
  13914. /*klass*/ ctx[0],
  13915. /*hideLabel*/ ctx[5] && "PinturaSliderIconOnly"
  13916. ]);
  13917. if (dirty & /*$$scope, $$restProps, value, title, locale, innerClass, labelClass, hideLabel, currentLabel, icon*/ 264702) {
  13918. details_changes.$$scope = { dirty, ctx };
  13919. }
  13920. details.$set(details_changes);
  13921. },
  13922. i(local) {
  13923. if (current) return;
  13924. transition_in(details.$$.fragment, local);
  13925. current = true;
  13926. },
  13927. o(local) {
  13928. transition_out(details.$$.fragment, local);
  13929. current = false;
  13930. },
  13931. d(detaching) {
  13932. destroy_component(details, detaching);
  13933. }
  13934. };
  13935. }
  13936. function instance$w($$self, $$props, $$invalidate) {
  13937. const omit_props_names = [
  13938. "class","title","label","icon","labelClass","innerClass","hideLabel","locale","value","onchange"
  13939. ];
  13940. let $$restProps = compute_rest_props($$props, omit_props_names);
  13941. let { class: klass = undefined } = $$props;
  13942. let { title = undefined } = $$props;
  13943. let { label = value => Math.round(value) } = $$props;
  13944. let { icon = undefined } = $$props;
  13945. let { labelClass = undefined } = $$props;
  13946. let { innerClass = undefined } = $$props;
  13947. let { hideLabel = false } = $$props;
  13948. let { locale = undefined } = $$props;
  13949. let { value = undefined } = $$props;
  13950. let { onchange = noop$1 } = $$props;
  13951. const { min, max, getValue = passthrough } = $$restProps;
  13952. const handleKeydown = e => {
  13953. // don't allow tabbing ([tab] is also blocked in normal <select>)
  13954. if ((/tab/i).test(e.key)) e.preventDefault();
  13955. };
  13956. const getLabel = value => isFunction(label)
  13957. ? label(getValue(value), min, max)
  13958. : label;
  13959. let currentLabel = getLabel(value);
  13960. const handleChangeValue = value => {
  13961. $$invalidate(8, currentLabel = getLabel(value));
  13962. onchange(value);
  13963. };
  13964. $$self.$$set = $$new_props => {
  13965. $$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
  13966. $$invalidate(11, $$restProps = compute_rest_props($$props, omit_props_names));
  13967. if ("class" in $$new_props) $$invalidate(0, klass = $$new_props.class);
  13968. if ("title" in $$new_props) $$invalidate(1, title = $$new_props.title);
  13969. if ("label" in $$new_props) $$invalidate(12, label = $$new_props.label);
  13970. if ("icon" in $$new_props) $$invalidate(2, icon = $$new_props.icon);
  13971. if ("labelClass" in $$new_props) $$invalidate(3, labelClass = $$new_props.labelClass);
  13972. if ("innerClass" in $$new_props) $$invalidate(4, innerClass = $$new_props.innerClass);
  13973. if ("hideLabel" in $$new_props) $$invalidate(5, hideLabel = $$new_props.hideLabel);
  13974. if ("locale" in $$new_props) $$invalidate(6, locale = $$new_props.locale);
  13975. if ("value" in $$new_props) $$invalidate(7, value = $$new_props.value);
  13976. if ("onchange" in $$new_props) $$invalidate(13, onchange = $$new_props.onchange);
  13977. };
  13978. return [
  13979. klass,
  13980. title,
  13981. icon,
  13982. labelClass,
  13983. innerClass,
  13984. hideLabel,
  13985. locale,
  13986. value,
  13987. currentLabel,
  13988. handleKeydown,
  13989. handleChangeValue,
  13990. $$restProps,
  13991. label,
  13992. onchange
  13993. ];
  13994. }
  13995. class ToggleSlider extends SvelteComponent {
  13996. constructor(options) {
  13997. super();
  13998. init(this, options, instance$w, create_fragment$w, safe_not_equal, {
  13999. class: 0,
  14000. title: 1,
  14001. label: 12,
  14002. icon: 2,
  14003. labelClass: 3,
  14004. innerClass: 4,
  14005. hideLabel: 5,
  14006. locale: 6,
  14007. value: 7,
  14008. onchange: 13
  14009. });
  14010. }
  14011. }
  14012. /* src/core/ui/components/DynamicComponentTree.svelte generated by Svelte v3.37.0 */
  14013. function get_each_context$6(ctx, list, i) {
  14014. const child_ctx = ctx.slice();
  14015. child_ctx[7] = list[i][0];
  14016. child_ctx[8] = list[i][1];
  14017. child_ctx[9] = list[i][2];
  14018. child_ctx[0] = list[i][3];
  14019. return child_ctx;
  14020. }
  14021. // (54:4) {:else}
  14022. function create_else_block$3(ctx) {
  14023. let switch_instance;
  14024. let switch_instance_anchor;
  14025. let current;
  14026. const switch_instance_spread_levels = [/*props*/ ctx[9]];
  14027. var switch_value = /*ComponentMap*/ ctx[1][/*node*/ ctx[7]] || /*node*/ ctx[7];
  14028. function switch_props(ctx) {
  14029. let switch_instance_props = {};
  14030. for (let i = 0; i < switch_instance_spread_levels.length; i += 1) {
  14031. switch_instance_props = assign(switch_instance_props, switch_instance_spread_levels[i]);
  14032. }
  14033. return { props: switch_instance_props };
  14034. }
  14035. if (switch_value) {
  14036. switch_instance = new switch_value(switch_props());
  14037. }
  14038. return {
  14039. c() {
  14040. if (switch_instance) create_component(switch_instance.$$.fragment);
  14041. switch_instance_anchor = empty();
  14042. },
  14043. m(target, anchor) {
  14044. if (switch_instance) {
  14045. mount_component(switch_instance, target, anchor);
  14046. }
  14047. insert(target, switch_instance_anchor, anchor);
  14048. current = true;
  14049. },
  14050. p(ctx, dirty) {
  14051. const switch_instance_changes = (dirty & /*children*/ 1)
  14052. ? get_spread_update(switch_instance_spread_levels, [get_spread_object(/*props*/ ctx[9])])
  14053. : {};
  14054. if (switch_value !== (switch_value = /*ComponentMap*/ ctx[1][/*node*/ ctx[7]] || /*node*/ ctx[7])) {
  14055. if (switch_instance) {
  14056. group_outros();
  14057. const old_component = switch_instance;
  14058. transition_out(old_component.$$.fragment, 1, 0, () => {
  14059. destroy_component(old_component, 1);
  14060. });
  14061. check_outros();
  14062. }
  14063. if (switch_value) {
  14064. switch_instance = new switch_value(switch_props());
  14065. create_component(switch_instance.$$.fragment);
  14066. transition_in(switch_instance.$$.fragment, 1);
  14067. mount_component(switch_instance, switch_instance_anchor.parentNode, switch_instance_anchor);
  14068. } else {
  14069. switch_instance = null;
  14070. }
  14071. } else if (switch_value) {
  14072. switch_instance.$set(switch_instance_changes);
  14073. }
  14074. },
  14075. i(local) {
  14076. if (current) return;
  14077. if (switch_instance) transition_in(switch_instance.$$.fragment, local);
  14078. current = true;
  14079. },
  14080. o(local) {
  14081. if (switch_instance) transition_out(switch_instance.$$.fragment, local);
  14082. current = false;
  14083. },
  14084. d(detaching) {
  14085. if (detaching) detach(switch_instance_anchor);
  14086. if (switch_instance) destroy_component(switch_instance, detaching);
  14087. }
  14088. };
  14089. }
  14090. // (44:4) {#if !isComponent(node)}
  14091. function create_if_block$8(ctx) {
  14092. let tag;
  14093. let current;
  14094. tag = new Tag({
  14095. props: {
  14096. name: /*node*/ ctx[7],
  14097. attributes: /*getElementAttributes*/ ctx[2](/*props*/ ctx[9]),
  14098. $$slots: { default: [create_default_slot$b] },
  14099. $$scope: { ctx }
  14100. }
  14101. });
  14102. return {
  14103. c() {
  14104. create_component(tag.$$.fragment);
  14105. },
  14106. m(target, anchor) {
  14107. mount_component(tag, target, anchor);
  14108. current = true;
  14109. },
  14110. p(ctx, dirty) {
  14111. const tag_changes = {};
  14112. if (dirty & /*children*/ 1) tag_changes.name = /*node*/ ctx[7];
  14113. if (dirty & /*children*/ 1) tag_changes.attributes = /*getElementAttributes*/ ctx[2](/*props*/ ctx[9]);
  14114. if (dirty & /*$$scope, children*/ 4097) {
  14115. tag_changes.$$scope = { dirty, ctx };
  14116. }
  14117. tag.$set(tag_changes);
  14118. },
  14119. i(local) {
  14120. if (current) return;
  14121. transition_in(tag.$$.fragment, local);
  14122. current = true;
  14123. },
  14124. o(local) {
  14125. transition_out(tag.$$.fragment, local);
  14126. current = false;
  14127. },
  14128. d(detaching) {
  14129. destroy_component(tag, detaching);
  14130. }
  14131. };
  14132. }
  14133. // (50:38)
  14134. function create_if_block_3$5(ctx) {
  14135. let html_tag;
  14136. let raw_value = /*props*/ ctx[9].innerHTML + "";
  14137. let html_anchor;
  14138. return {
  14139. c() {
  14140. html_anchor = empty();
  14141. html_tag = new HtmlTag(html_anchor);
  14142. },
  14143. m(target, anchor) {
  14144. html_tag.m(raw_value, target, anchor);
  14145. insert(target, html_anchor, anchor);
  14146. },
  14147. p(ctx, dirty) {
  14148. if (dirty & /*children*/ 1 && raw_value !== (raw_value = /*props*/ ctx[9].innerHTML + "")) html_tag.p(raw_value);
  14149. },
  14150. i: noop,
  14151. o: noop,
  14152. d(detaching) {
  14153. if (detaching) detach(html_anchor);
  14154. if (detaching) html_tag.d();
  14155. }
  14156. };
  14157. }
  14158. // (48:40)
  14159. function create_if_block_2$7(ctx) {
  14160. let t_value = /*props*/ ctx[9].textContent + "";
  14161. let t;
  14162. return {
  14163. c() {
  14164. t = text(t_value);
  14165. },
  14166. m(target, anchor) {
  14167. insert(target, t, anchor);
  14168. },
  14169. p(ctx, dirty) {
  14170. if (dirty & /*children*/ 1 && t_value !== (t_value = /*props*/ ctx[9].textContent + "")) set_data(t, t_value);
  14171. },
  14172. i: noop,
  14173. o: noop,
  14174. d(detaching) {
  14175. if (detaching) detach(t);
  14176. }
  14177. };
  14178. }
  14179. // (46:12) {#if children && children.length}
  14180. function create_if_block_1$8(ctx) {
  14181. let dynamiccomponenttree;
  14182. let current;
  14183. dynamiccomponenttree = new DynamicComponentTree_1({
  14184. props: {
  14185. items: /*children*/ ctx[0],
  14186. discardEmptyItems: true
  14187. }
  14188. });
  14189. return {
  14190. c() {
  14191. create_component(dynamiccomponenttree.$$.fragment);
  14192. },
  14193. m(target, anchor) {
  14194. mount_component(dynamiccomponenttree, target, anchor);
  14195. current = true;
  14196. },
  14197. p(ctx, dirty) {
  14198. const dynamiccomponenttree_changes = {};
  14199. if (dirty & /*children*/ 1) dynamiccomponenttree_changes.items = /*children*/ ctx[0];
  14200. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  14201. },
  14202. i(local) {
  14203. if (current) return;
  14204. transition_in(dynamiccomponenttree.$$.fragment, local);
  14205. current = true;
  14206. },
  14207. o(local) {
  14208. transition_out(dynamiccomponenttree.$$.fragment, local);
  14209. current = false;
  14210. },
  14211. d(detaching) {
  14212. destroy_component(dynamiccomponenttree, detaching);
  14213. }
  14214. };
  14215. }
  14216. // (45:8) <Tag name={node} attributes={getElementAttributes(props)}>
  14217. function create_default_slot$b(ctx) {
  14218. let current_block_type_index;
  14219. let if_block;
  14220. let t;
  14221. let current;
  14222. const if_block_creators = [create_if_block_1$8, create_if_block_2$7, create_if_block_3$5];
  14223. const if_blocks = [];
  14224. function select_block_type_1(ctx, dirty) {
  14225. if (/*children*/ ctx[0] && /*children*/ ctx[0].length) return 0;
  14226. if (/*props*/ ctx[9].textContent) return 1;
  14227. if (/*props*/ ctx[9].innerHTML) return 2;
  14228. return -1;
  14229. }
  14230. if (~(current_block_type_index = select_block_type_1(ctx))) {
  14231. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  14232. }
  14233. return {
  14234. c() {
  14235. if (if_block) if_block.c();
  14236. t = space();
  14237. },
  14238. m(target, anchor) {
  14239. if (~current_block_type_index) {
  14240. if_blocks[current_block_type_index].m(target, anchor);
  14241. }
  14242. insert(target, t, anchor);
  14243. current = true;
  14244. },
  14245. p(ctx, dirty) {
  14246. let previous_block_index = current_block_type_index;
  14247. current_block_type_index = select_block_type_1(ctx);
  14248. if (current_block_type_index === previous_block_index) {
  14249. if (~current_block_type_index) {
  14250. if_blocks[current_block_type_index].p(ctx, dirty);
  14251. }
  14252. } else {
  14253. if (if_block) {
  14254. group_outros();
  14255. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  14256. if_blocks[previous_block_index] = null;
  14257. });
  14258. check_outros();
  14259. }
  14260. if (~current_block_type_index) {
  14261. if_block = if_blocks[current_block_type_index];
  14262. if (!if_block) {
  14263. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  14264. if_block.c();
  14265. } else {
  14266. if_block.p(ctx, dirty);
  14267. }
  14268. transition_in(if_block, 1);
  14269. if_block.m(t.parentNode, t);
  14270. } else {
  14271. if_block = null;
  14272. }
  14273. }
  14274. },
  14275. i(local) {
  14276. if (current) return;
  14277. transition_in(if_block);
  14278. current = true;
  14279. },
  14280. o(local) {
  14281. transition_out(if_block);
  14282. current = false;
  14283. },
  14284. d(detaching) {
  14285. if (~current_block_type_index) {
  14286. if_blocks[current_block_type_index].d(detaching);
  14287. }
  14288. if (detaching) detach(t);
  14289. }
  14290. };
  14291. }
  14292. // (43:0) {#each children as [node, key, props, children] (key)}
  14293. function create_each_block$6(key_1, ctx) {
  14294. let first;
  14295. let show_if;
  14296. let current_block_type_index;
  14297. let if_block;
  14298. let if_block_anchor;
  14299. let current;
  14300. const if_block_creators = [create_if_block$8, create_else_block$3];
  14301. const if_blocks = [];
  14302. function select_block_type(ctx, dirty) {
  14303. if (dirty & /*children*/ 1) show_if = !!!/*isComponent*/ ctx[3](/*node*/ ctx[7]);
  14304. if (show_if) return 0;
  14305. return 1;
  14306. }
  14307. current_block_type_index = select_block_type(ctx, -1);
  14308. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  14309. return {
  14310. key: key_1,
  14311. first: null,
  14312. c() {
  14313. first = empty();
  14314. if_block.c();
  14315. if_block_anchor = empty();
  14316. this.first = first;
  14317. },
  14318. m(target, anchor) {
  14319. insert(target, first, anchor);
  14320. if_blocks[current_block_type_index].m(target, anchor);
  14321. insert(target, if_block_anchor, anchor);
  14322. current = true;
  14323. },
  14324. p(new_ctx, dirty) {
  14325. ctx = new_ctx;
  14326. let previous_block_index = current_block_type_index;
  14327. current_block_type_index = select_block_type(ctx, dirty);
  14328. if (current_block_type_index === previous_block_index) {
  14329. if_blocks[current_block_type_index].p(ctx, dirty);
  14330. } else {
  14331. group_outros();
  14332. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  14333. if_blocks[previous_block_index] = null;
  14334. });
  14335. check_outros();
  14336. if_block = if_blocks[current_block_type_index];
  14337. if (!if_block) {
  14338. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  14339. if_block.c();
  14340. } else {
  14341. if_block.p(ctx, dirty);
  14342. }
  14343. transition_in(if_block, 1);
  14344. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  14345. }
  14346. },
  14347. i(local) {
  14348. if (current) return;
  14349. transition_in(if_block);
  14350. current = true;
  14351. },
  14352. o(local) {
  14353. transition_out(if_block);
  14354. current = false;
  14355. },
  14356. d(detaching) {
  14357. if (detaching) detach(first);
  14358. if_blocks[current_block_type_index].d(detaching);
  14359. if (detaching) detach(if_block_anchor);
  14360. }
  14361. };
  14362. }
  14363. function create_fragment$v(ctx) {
  14364. let each_blocks = [];
  14365. let each_1_lookup = new Map();
  14366. let each_1_anchor;
  14367. let current;
  14368. let each_value = /*children*/ ctx[0];
  14369. const get_key = ctx => /*key*/ ctx[8];
  14370. for (let i = 0; i < each_value.length; i += 1) {
  14371. let child_ctx = get_each_context$6(ctx, each_value, i);
  14372. let key = get_key(child_ctx);
  14373. each_1_lookup.set(key, each_blocks[i] = create_each_block$6(key, child_ctx));
  14374. }
  14375. return {
  14376. c() {
  14377. for (let i = 0; i < each_blocks.length; i += 1) {
  14378. each_blocks[i].c();
  14379. }
  14380. each_1_anchor = empty();
  14381. },
  14382. m(target, anchor) {
  14383. for (let i = 0; i < each_blocks.length; i += 1) {
  14384. each_blocks[i].m(target, anchor);
  14385. }
  14386. insert(target, each_1_anchor, anchor);
  14387. current = true;
  14388. },
  14389. p(ctx, [dirty]) {
  14390. if (dirty & /*children, getElementAttributes, isComponent, ComponentMap*/ 15) {
  14391. each_value = /*children*/ ctx[0];
  14392. group_outros();
  14393. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, outro_and_destroy_block, create_each_block$6, each_1_anchor, get_each_context$6);
  14394. check_outros();
  14395. }
  14396. },
  14397. i(local) {
  14398. if (current) return;
  14399. for (let i = 0; i < each_value.length; i += 1) {
  14400. transition_in(each_blocks[i]);
  14401. }
  14402. current = true;
  14403. },
  14404. o(local) {
  14405. for (let i = 0; i < each_blocks.length; i += 1) {
  14406. transition_out(each_blocks[i]);
  14407. }
  14408. current = false;
  14409. },
  14410. d(detaching) {
  14411. for (let i = 0; i < each_blocks.length; i += 1) {
  14412. each_blocks[i].d(detaching);
  14413. }
  14414. if (detaching) detach(each_1_anchor);
  14415. }
  14416. };
  14417. }
  14418. function instance$v($$self, $$props, $$invalidate) {
  14419. let children;
  14420. let { items } = $$props;
  14421. let { discardEmptyItems = true } = $$props;
  14422. const ComponentMap = { Button, Dropdown, Slider: ToggleSlider };
  14423. const getElementAttributes = (props = {}) => {
  14424. const { textContent, innerHTML, ...attributes } = props;
  14425. return attributes;
  14426. };
  14427. const isComponent = node => !isString(node) || !!ComponentMap[node];
  14428. const shouldRenderItem = item => {
  14429. // don't render falsy items
  14430. if (!item) return false;
  14431. // get relevant props
  14432. const [node, ,props, children = []] = item;
  14433. // if item is component, we always render it
  14434. if (isComponent(node)) return true;
  14435. // item is tag, we have to check if it has content
  14436. return children.some(shouldRenderItem) || props.textContent || props.innerHTML;
  14437. };
  14438. $$self.$$set = $$props => {
  14439. if ("items" in $$props) $$invalidate(4, items = $$props.items);
  14440. if ("discardEmptyItems" in $$props) $$invalidate(5, discardEmptyItems = $$props.discardEmptyItems);
  14441. };
  14442. $$self.$$.update = () => {
  14443. if ($$self.$$.dirty & /*items, discardEmptyItems*/ 48) {
  14444. $$invalidate(0, children = (items && discardEmptyItems
  14445. ? items.filter(shouldRenderItem)
  14446. : items) || []);
  14447. }
  14448. };
  14449. return [
  14450. children,
  14451. ComponentMap,
  14452. getElementAttributes,
  14453. isComponent,
  14454. items,
  14455. discardEmptyItems
  14456. ];
  14457. }
  14458. class DynamicComponentTree_1 extends SvelteComponent {
  14459. constructor(options) {
  14460. super();
  14461. init(this, options, instance$v, create_fragment$v, safe_not_equal, { items: 4, discardEmptyItems: 5 });
  14462. }
  14463. }
  14464. var smoothstep = (min, max, value, ease = (x) => x * x * (3 - 2 * x)) => ease(Math.max(0, Math.min(1, (value - min) / (max - min))));
  14465. var canvasClone = (canvas) => {
  14466. const clone = h('canvas', { width: canvas.width, height: canvas.height });
  14467. clone.getContext('2d').drawImage(canvas, 0, 0);
  14468. return clone;
  14469. };
  14470. const ImageStoreProps = [
  14471. 'file',
  14472. 'size',
  14473. 'loadState',
  14474. 'processState',
  14475. 'cropAspectRatio',
  14476. 'cropLimitToImage',
  14477. 'crop',
  14478. 'cropMinSize',
  14479. 'cropMaxSize',
  14480. 'cropRange',
  14481. 'cropOrigin',
  14482. 'cropRectAspectRatio',
  14483. 'rotation',
  14484. 'rotationRange',
  14485. 'targetSize',
  14486. 'flipX',
  14487. 'flipY',
  14488. 'perspectiveX',
  14489. 'perspectiveY',
  14490. 'perspective',
  14491. 'colorMatrix',
  14492. 'convolutionMatrix',
  14493. 'gamma',
  14494. 'vignette',
  14495. 'noise',
  14496. 'redaction',
  14497. 'decoration',
  14498. 'annotation',
  14499. 'frame',
  14500. 'backgroundColor',
  14501. 'state',
  14502. ];
  14503. const proxy = function (get, set, update) {
  14504. let subscribers = [];
  14505. return {
  14506. set,
  14507. update,
  14508. publish: (value) => {
  14509. subscribers.forEach((cb) => cb(value));
  14510. },
  14511. subscribe: (cb) => {
  14512. subscribers.push(cb);
  14513. get(cb);
  14514. return () => {
  14515. subscribers = subscribers.filter((item) => item !== cb);
  14516. };
  14517. },
  14518. };
  14519. };
  14520. var createImageProxy = () => {
  14521. let unsubs;
  14522. let image;
  14523. const proxyStores = ImageStoreProps.reduce((prev, curr) => {
  14524. prev[curr] = proxy(
  14525. // getter
  14526. (cb) => {
  14527. // subscribe
  14528. if (!image)
  14529. return cb();
  14530. const unsub = image.stores[curr].subscribe(cb);
  14531. unsub();
  14532. },
  14533. // setter
  14534. (value) => {
  14535. // set value on actual store if is defined
  14536. if (!image)
  14537. return;
  14538. image.stores[curr].set(value);
  14539. },
  14540. // updater
  14541. (cb) => {
  14542. if (!image)
  14543. return;
  14544. image.stores[curr].update(cb);
  14545. });
  14546. return prev;
  14547. }, {});
  14548. const update = (newImage) => {
  14549. image = newImage;
  14550. if (unsubs) {
  14551. // remove subscribers
  14552. unsubs.forEach((unsub) => unsub());
  14553. unsubs = undefined;
  14554. }
  14555. if (!newImage) {
  14556. // need to reset load state
  14557. proxyStores['file'].publish(undefined);
  14558. proxyStores['loadState'].publish(undefined);
  14559. return;
  14560. }
  14561. unsubs = ImageStoreProps.map((prop) => newImage.stores[prop].subscribe((value) => {
  14562. proxyStores[prop].publish(value);
  14563. }));
  14564. };
  14565. return {
  14566. update,
  14567. stores: proxyStores,
  14568. };
  14569. };
  14570. var createPingRouter = (route, cancel = true) => (e) => {
  14571. if (e.type !== 'ping')
  14572. return;
  14573. if (cancel)
  14574. e.stopPropagation();
  14575. route(e.detail.type, e.detail.data);
  14576. };
  14577. var createPing = (type, data) => new CustomEvent('ping', {
  14578. detail: {
  14579. type,
  14580. data,
  14581. },
  14582. cancelable: true,
  14583. bubbles: true,
  14584. });
  14585. var isTextarea = (element) => /textarea/i.test(element.nodeName);
  14586. var isTextInput = (node) => /date|email|number|search|text|url/.test(node.type);
  14587. var isTextField = (node) => isTextarea(node) || isTextInput(node);
  14588. var toKebabCase = (str, abbr) => {
  14589. return (abbr ? stringReplace(str, abbr) : str)
  14590. .replace(/([a-z])([A-Z])/g, '$1-$2')
  14591. .replace(/\s+/g, '-')
  14592. .toLowerCase();
  14593. };
  14594. var matchMedia$1 = (query, cb) => {
  14595. const mql = matchMedia(query);
  14596. mql.addListener(cb);
  14597. cb(mql);
  14598. return {
  14599. get matches() { return mql.matches; },
  14600. destroy: () => mql.removeListener(cb)
  14601. };
  14602. };
  14603. var mediaQueryStore = (query, formatValue = passthrough) => {
  14604. const { subscribe, set } = writable(undefined);
  14605. const mm = matchMedia$1(query, ({ matches }) => set(formatValue(matches)));
  14606. return {
  14607. subscribe,
  14608. unsubscribe: mm.destroy
  14609. };
  14610. };
  14611. var canPreventNavSwipe = () => {
  14612. // if not iOS we can't prevent swipe because it probably isn't a thing
  14613. if (!isIOS())
  14614. return false;
  14615. // extract version number
  14616. const matches = navigator.userAgent.match(/OS (\d+)_(\d+)_?(\d+)?/i) || [];
  14617. const [, major, minor] = matches.map((v) => parseInt(v, 10) || 0);
  14618. // is atleast version 13.4+
  14619. return major > 13 || (major === 13 && minor >= 4);
  14620. };
  14621. var calculateImageTransforms = (stageRect, rootRect, imageSize, cropRect, imageSelectionRect, imageScale, imagePerspectiveX, imagePerspectiveY, imageRotation, imageFlipX, imageFlipY) => {
  14622. if (!stageRect || !rootRect || !imageSize || !cropRect || !imageScale)
  14623. return undefined;
  14624. const viewRect = rectNormalizeOffset(rectClone(rootRect));
  14625. const viewCenter = rectCenter(viewRect);
  14626. const stageCenter = rectCenter(stageRect);
  14627. const imageRect = rectCreateFromSize(imageSize);
  14628. const imageCenter = rectCenter(imageRect);
  14629. const imagePerspective = vectorCreate(imagePerspectiveX, imagePerspectiveY);
  14630. // get base crop rect so we can correctly apply transforms
  14631. const cropRectBase = getBaseCropRect(imageSize, cropRect, imageRotation);
  14632. const cropRectBaseCenter = rectCenter(cropRectBase);
  14633. const imageTranslation = vectorSubtract(vectorClone(imageCenter), cropRectBaseCenter);
  14634. // calculate stage center offset from view center
  14635. const imageOffset = vectorSubtract(vectorClone(stageCenter), viewCenter);
  14636. // correct for stage offset
  14637. imageTranslation.x += imageOffset.x;
  14638. imageTranslation.y += imageOffset.y;
  14639. // set origin of translation (so rotates around center of selection)
  14640. const imageOrigin = vectorInvert(vectorClone(imageTranslation));
  14641. // correct for stage offset
  14642. imageOrigin.x += imageOffset.x;
  14643. imageOrigin.y += imageOffset.y;
  14644. // correct for image selection offset relative to view
  14645. const imageSelectionCenter = rectCenter(rectTranslate(rectClone(imageSelectionRect), stageRect));
  14646. const imageSelectionOffset = vectorSubtract(imageSelectionCenter, stageCenter);
  14647. vectorAdd(imageTranslation, imageSelectionOffset);
  14648. return {
  14649. // offset: imageOffset,
  14650. origin: imageOrigin,
  14651. translation: imageTranslation,
  14652. rotation: {
  14653. x: imageFlipY ? Math.PI : 0,
  14654. y: imageFlipX ? Math.PI : 0,
  14655. z: imageRotation,
  14656. },
  14657. perspective: imagePerspective,
  14658. scale: imageScale,
  14659. };
  14660. };
  14661. // @ts-ignore
  14662. var historyCreate = (getState, setState) => {
  14663. // set up pub/sub for history object
  14664. const { sub, pub } = pubsub();
  14665. // current history state
  14666. //let baseState;//
  14667. const entries = [];
  14668. const index = writable(0);
  14669. const subs = [];
  14670. const updateSubs = () => subs.forEach((cb) => cb({ index: get_store_value(index), length: entries.length }));
  14671. const history = {
  14672. get index() {
  14673. return get_store_value(index);
  14674. },
  14675. set index(i) {
  14676. // validate new index
  14677. i = Number.isInteger(i) ? i : 0;
  14678. i = clamp(i, 0, entries.length - 1);
  14679. // remember
  14680. index.set(i);
  14681. setState(entries[history.index]); // || baseState);
  14682. // update subs
  14683. updateSubs();
  14684. },
  14685. get state() {
  14686. return entries[entries.length - 1]; // || baseState;
  14687. },
  14688. length() {
  14689. return entries.length;
  14690. },
  14691. undo() {
  14692. const newIndex = history.index--;
  14693. pub('undo', newIndex);
  14694. return newIndex;
  14695. },
  14696. redo() {
  14697. const newIndex = history.index++;
  14698. pub('redo', history.index);
  14699. return newIndex;
  14700. },
  14701. revert() {
  14702. entries.length = 1; // retain first state
  14703. history.index = 0;
  14704. pub('revert');
  14705. },
  14706. write(state) {
  14707. // write history entry
  14708. if (state) {
  14709. setState({
  14710. ...getState(),
  14711. ...state,
  14712. });
  14713. }
  14714. const newState = getState();
  14715. const lastState = entries[entries.length - 1];
  14716. // don't update if new state isn't different
  14717. if (JSON.stringify(newState) === JSON.stringify(lastState))
  14718. return;
  14719. // reset length to current index
  14720. entries.length = history.index + 1;
  14721. // add new entry
  14722. entries.push(newState);
  14723. // move pointer to last added index
  14724. index.set(entries.length - 1);
  14725. updateSubs();
  14726. },
  14727. set(state = {}) {
  14728. // set clears all entries
  14729. entries.length = 0;
  14730. history.index = 0;
  14731. // set new entries
  14732. const newStateEntries = !Array.isArray(state) ? [state] : state;
  14733. // add new entries
  14734. entries.push(...newStateEntries);
  14735. // move pointer to last added index
  14736. history.index = entries.length - 1;
  14737. },
  14738. get() {
  14739. return [...entries];
  14740. },
  14741. subscribe(cb) {
  14742. subs.push(cb);
  14743. cb({ index: history.index, length: entries.length });
  14744. return () => subs.splice(subs.indexOf(cb), 1);
  14745. },
  14746. on: sub,
  14747. };
  14748. return history;
  14749. };
  14750. var isChrome = () => isBrowser() && !!window['chrome'];
  14751. var imageBitmapToImageData = async (imageBitmap) => canvasToImageData(await imageDataToCanvas(imageBitmap));
  14752. var blobToImageBitmap = (file, ImageOrienter, canvasMemoryLimit) => new Promise((resolve, reject) => {
  14753. (async () => {
  14754. // get orientation of image, should return 1 for normal orientation
  14755. const orientation = await ImageOrienter.read(file);
  14756. // helper method to apply orientation fix if needed
  14757. const toImageData = (file) => blobToImageData(file, canvasMemoryLimit)
  14758. .then((imageData) => ImageOrienter.apply(imageData, orientation))
  14759. .then(resolve)
  14760. .catch(reject);
  14761. // if cannot create image bitmaps in worker
  14762. // Safari 15 cannot correctly apply orientation, also it will choke on very big images when trying to createImageBitmap in thread, so lets just do it on the main thread
  14763. // we'll ignore safari for now
  14764. if (isSVGFile(file) || !canCreateImageBitmap() || isSafari$1())
  14765. return toImageData(file);
  14766. // create image bitmap in thread
  14767. let imageBitmap;
  14768. try {
  14769. imageBitmap = await thread((file, done) => createImageBitmap(file)
  14770. .then((bitmap) => done(null, bitmap))
  14771. .catch(done), [file]);
  14772. }
  14773. catch (err) {
  14774. // fails silently on purpose, we'll try to turn the blob into image data in the main thread
  14775. // console.error(err);
  14776. }
  14777. // no bitmap returned, something went wrong in `createImageBitmap` logic
  14778. if (!imageBitmap || !imageBitmap.width)
  14779. return toImageData(file);
  14780. // if the browser can't orient images, we need to correct the orientation now
  14781. if (!(await canOrientImages()))
  14782. return resolve(ImageOrienter.apply(imageBitmap, orientation));
  14783. // need to convert so oriented image can be used as WebGL texture
  14784. // converting ImageBitmap to <canvas> (and then optionally to image data) fixes a Chrome render bug where the
  14785. // ImageBitmap when used in WebGL doesn't render in the correct orientation
  14786. // https://bugs.chromium.org/p/chromium/issues/detail?id=1082451&q=orientation%20imagebitmap&can=2
  14787. if (isChrome() && orientation > 1)
  14788. return resolve(await imageBitmapToImageData(imageBitmap));
  14789. // yay we got our bitmap
  14790. resolve(imageBitmap);
  14791. })();
  14792. });
  14793. var imageDataContain = (imageData, size) => new Promise(async (resolve) => {
  14794. if (imageData.width < size.width && imageData.height < size.height)
  14795. return resolve(imageData);
  14796. const scalar = Math.min(size.width / imageData.width, size.height / imageData.height);
  14797. // scale
  14798. const targetWidth = scalar * imageData.width;
  14799. const targetHeight = scalar * imageData.height;
  14800. const canvas = h('canvas', {
  14801. width: targetWidth,
  14802. height: targetHeight,
  14803. });
  14804. const ctx = canvas.getContext('2d');
  14805. const data = isImageData(imageData)
  14806. ? (await imageDataToCanvas(imageData))
  14807. : imageData;
  14808. ctx.drawImage(data, 0, 0, targetWidth, targetHeight);
  14809. resolve(canvasToImageData(canvas));
  14810. });
  14811. var hexToRGB = (str) => {
  14812. const [, q, w, e] = str.split('');
  14813. str = str.length === 4 ? `#${q}${q}${w}${w}${e}${e}` : str;
  14814. const [, r, g, b] = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(str);
  14815. return [r, g, b].map((v) => parseInt(v, 16) / 255);
  14816. };
  14817. var colorStringToColorArray = (color) => {
  14818. color = color.trim();
  14819. // if rgba(128, 128, 128, .5)
  14820. if (/^rgba/.test(color)) {
  14821. return color
  14822. .substr(5)
  14823. .split(',')
  14824. .map(parseFloat)
  14825. .map((v, i) => v / (i === 3 ? 1 : 255));
  14826. }
  14827. // if rgb(128, 128, 128)
  14828. if (/^rgb/.test(color)) {
  14829. return color
  14830. .substr(4)
  14831. .split(',')
  14832. .map(parseFloat)
  14833. .map((v) => v / 255);
  14834. }
  14835. // if #777
  14836. if (/^#/.test(color)) {
  14837. return hexToRGB(color);
  14838. }
  14839. // is possibly 255, 0, 0
  14840. if (/[0-9]{1,3}\s?,\s?[0-9]{1,3}\s?,\s?[0-9]{1,3}/.test(color)) {
  14841. return color
  14842. .split(',')
  14843. .map((v) => parseInt(v, 10))
  14844. .map((v) => v / 255);
  14845. }
  14846. };
  14847. let result$4 = null;
  14848. var supportsWebGL = () => {
  14849. if (result$4 === null) {
  14850. const canvas = h('canvas');
  14851. result$4 = !!getWebGLContext(canvas);
  14852. releaseCanvas(canvas);
  14853. }
  14854. return result$4;
  14855. };
  14856. var isBitmap = (file) => /^image/.test(file.type) && !/svg/.test(file.type);
  14857. // @ts-ignore
  14858. const COLOR_MATRIX_IDENTITY = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
  14859. const SPRING_PROPS = { precision: 0.0001 };
  14860. const SPRING_PROPS_FRACTION = { precision: SPRING_PROPS.precision * 0.01 };
  14861. var createImage = (data, size, options = {}) => {
  14862. const { resize: resizeInitial = 1, opacity: opacityInitial = 0 } = options;
  14863. const stores = {
  14864. // interface
  14865. opacity: [spring(opacityInitial, { ...SPRING_PROPS, stiffness: 0.1 }), passthrough],
  14866. resize: [spring(resizeInitial, { ...SPRING_PROPS, stiffness: 0.1 }), passthrough],
  14867. // transforms
  14868. translation: [spring(undefined, SPRING_PROPS), passthrough],
  14869. rotation: [spring(undefined, SPRING_PROPS_FRACTION), passthrough],
  14870. origin: [spring(undefined, SPRING_PROPS), passthrough],
  14871. scale: [spring(undefined, SPRING_PROPS_FRACTION), passthrough],
  14872. gamma: [spring(undefined, SPRING_PROPS_FRACTION), (v) => v || 1],
  14873. vignette: [spring(undefined, SPRING_PROPS_FRACTION), (v) => v || 0],
  14874. colorMatrix: [
  14875. spring([...COLOR_MATRIX_IDENTITY], SPRING_PROPS),
  14876. (v) => v || [...COLOR_MATRIX_IDENTITY],
  14877. ],
  14878. convolutionMatrix: [writable(undefined), (v) => (v && v.clarity) || undefined],
  14879. backgroundColor: [spring(undefined, SPRING_PROPS), passthrough],
  14880. };
  14881. // shortcut to quickly get all stores from the stores object
  14882. const storeEntries = Object.entries(stores).map(([key, value]) => [key, value[0]]);
  14883. const storeArray = storeEntries.map(([, store]) => store);
  14884. // create quick accessors to store value setter functions, best to do ones on creation instead of on each update
  14885. const storeSetters = Object.entries(stores).reduce((prev, [key, value]) => {
  14886. const [store, getValue] = value;
  14887. prev[key] = (value, opts) => store.set(getValue(value), opts);
  14888. return prev;
  14889. }, {});
  14890. // holds current derived state so can be easily read from from the outside
  14891. let stateCache;
  14892. //
  14893. const state = derived(storeArray, (storeValues) => {
  14894. // get new state
  14895. stateCache = storeValues.reduce((calculatedState, value, index) => {
  14896. const key = storeEntries[index][0];
  14897. calculatedState[key] = value;
  14898. return calculatedState;
  14899. }, {});
  14900. // set base image props
  14901. stateCache.data = data;
  14902. stateCache.size = size;
  14903. // apply resize modifier (is at index 1 of storeValues)
  14904. stateCache.scale *= storeValues[1];
  14905. return stateCache;
  14906. });
  14907. state.get = () => stateCache;
  14908. state.set = (props, animate) => {
  14909. const opts = { hard: !animate };
  14910. Object.entries(props).forEach(([key, value]) => {
  14911. if (!storeSetters[key])
  14912. return;
  14913. storeSetters[key](value, opts);
  14914. });
  14915. };
  14916. return state;
  14917. };
  14918. var storeList = () => {
  14919. const stores = [];
  14920. const subscribers = [];
  14921. const state = [];
  14922. const storeDidUpdate = (store, value) => {
  14923. const index = stores.indexOf(store);
  14924. if (index < 0)
  14925. return;
  14926. state[index] = value;
  14927. triggerUpdate();
  14928. };
  14929. const triggerUpdate = () => {
  14930. subscribers.forEach((fn) => fn(state));
  14931. };
  14932. const addStore = (store) => {
  14933. store.unsub = store.subscribe((value) => storeDidUpdate(store, value));
  14934. triggerUpdate();
  14935. };
  14936. const unshift = (store) => {
  14937. stores.unshift(store);
  14938. addStore(store);
  14939. };
  14940. const push = (store) => {
  14941. stores.push(store);
  14942. addStore(store);
  14943. };
  14944. const clear = () => {
  14945. stores.forEach((store) => store.unsub());
  14946. stores.length = 0;
  14947. state.length = 0;
  14948. };
  14949. const remove = (store) => {
  14950. store.unsub();
  14951. const index = stores.indexOf(store);
  14952. stores.splice(index, 1);
  14953. state.splice(index, 1);
  14954. };
  14955. const subscribe = (fn) => {
  14956. subscribers.push(fn);
  14957. return () => {
  14958. subscribers.splice(subscribers.indexOf(fn), 1);
  14959. };
  14960. };
  14961. const forEach = (fn) => stores.forEach(fn);
  14962. const filter = (fn) => stores.filter(fn);
  14963. const get = (index) => stores[index];
  14964. return {
  14965. get length() {
  14966. return stores.length;
  14967. },
  14968. clear,
  14969. unshift,
  14970. get,
  14971. push,
  14972. remove,
  14973. forEach,
  14974. filter,
  14975. subscribe,
  14976. };
  14977. };
  14978. var isDarkColor = (color) => {
  14979. return color[0] < 0.25 && color[1] < 0.25 && color[2] < 0.25;
  14980. };
  14981. /* src/core/ui/index.svelte generated by Svelte v3.37.0 */
  14982. const { window: window_1$1 } = globals;
  14983. function create_if_block_1$7(ctx) {
  14984. let t;
  14985. let if_block1_anchor;
  14986. let current;
  14987. let if_block0 = /*isStatusVisible*/ ctx[25] && create_if_block_6$1(ctx);
  14988. let if_block1 = /*isReady*/ ctx[26] && create_if_block_2$6(ctx);
  14989. return {
  14990. c() {
  14991. if (if_block0) if_block0.c();
  14992. t = space();
  14993. if (if_block1) if_block1.c();
  14994. if_block1_anchor = empty();
  14995. },
  14996. m(target, anchor) {
  14997. if (if_block0) if_block0.m(target, anchor);
  14998. insert(target, t, anchor);
  14999. if (if_block1) if_block1.m(target, anchor);
  15000. insert(target, if_block1_anchor, anchor);
  15001. current = true;
  15002. },
  15003. p(ctx, dirty) {
  15004. if (/*isStatusVisible*/ ctx[25]) {
  15005. if (if_block0) {
  15006. if_block0.p(ctx, dirty);
  15007. if (dirty[0] & /*isStatusVisible*/ 33554432) {
  15008. transition_in(if_block0, 1);
  15009. }
  15010. } else {
  15011. if_block0 = create_if_block_6$1(ctx);
  15012. if_block0.c();
  15013. transition_in(if_block0, 1);
  15014. if_block0.m(t.parentNode, t);
  15015. }
  15016. } else if (if_block0) {
  15017. group_outros();
  15018. transition_out(if_block0, 1, 1, () => {
  15019. if_block0 = null;
  15020. });
  15021. check_outros();
  15022. }
  15023. if (/*isReady*/ ctx[26]) {
  15024. if (if_block1) {
  15025. if_block1.p(ctx, dirty);
  15026. if (dirty[0] & /*isReady*/ 67108864) {
  15027. transition_in(if_block1, 1);
  15028. }
  15029. } else {
  15030. if_block1 = create_if_block_2$6(ctx);
  15031. if_block1.c();
  15032. transition_in(if_block1, 1);
  15033. if_block1.m(if_block1_anchor.parentNode, if_block1_anchor);
  15034. }
  15035. } else if (if_block1) {
  15036. group_outros();
  15037. transition_out(if_block1, 1, 1, () => {
  15038. if_block1 = null;
  15039. });
  15040. check_outros();
  15041. }
  15042. },
  15043. i(local) {
  15044. if (current) return;
  15045. transition_in(if_block0);
  15046. transition_in(if_block1);
  15047. current = true;
  15048. },
  15049. o(local) {
  15050. transition_out(if_block0);
  15051. transition_out(if_block1);
  15052. current = false;
  15053. },
  15054. d(detaching) {
  15055. if (if_block0) if_block0.d(detaching);
  15056. if (detaching) detach(t);
  15057. if (if_block1) if_block1.d(detaching);
  15058. if (detaching) detach(if_block1_anchor);
  15059. }
  15060. };
  15061. }
  15062. // (2463:8) {#if isStatusVisible}
  15063. function create_if_block_6$1(ctx) {
  15064. let div;
  15065. let p;
  15066. let current_block_type_index;
  15067. let if_block;
  15068. let div_style_value;
  15069. let current;
  15070. const if_block_creators = [create_if_block_7, create_if_block_8];
  15071. const if_blocks = [];
  15072. function select_block_type(ctx, dirty) {
  15073. if (/*isSupportsError*/ ctx[23]) return 0;
  15074. if (/*statusState*/ ctx[13]) return 1;
  15075. return -1;
  15076. }
  15077. if (~(current_block_type_index = select_block_type(ctx))) {
  15078. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  15079. }
  15080. return {
  15081. c() {
  15082. div = element("div");
  15083. p = element("p");
  15084. if (if_block) if_block.c();
  15085. attr(p, "style", /*statusTransform*/ ctx[38]);
  15086. attr(div, "class", "PinturaStatus");
  15087. attr(div, "style", div_style_value = `opacity: ${/*$statusOpacity*/ ctx[24]}`);
  15088. },
  15089. m(target, anchor) {
  15090. insert(target, div, anchor);
  15091. append(div, p);
  15092. if (~current_block_type_index) {
  15093. if_blocks[current_block_type_index].m(p, null);
  15094. }
  15095. current = true;
  15096. },
  15097. p(ctx, dirty) {
  15098. let previous_block_index = current_block_type_index;
  15099. current_block_type_index = select_block_type(ctx);
  15100. if (current_block_type_index === previous_block_index) {
  15101. if (~current_block_type_index) {
  15102. if_blocks[current_block_type_index].p(ctx, dirty);
  15103. }
  15104. } else {
  15105. if (if_block) {
  15106. group_outros();
  15107. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  15108. if_blocks[previous_block_index] = null;
  15109. });
  15110. check_outros();
  15111. }
  15112. if (~current_block_type_index) {
  15113. if_block = if_blocks[current_block_type_index];
  15114. if (!if_block) {
  15115. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  15116. if_block.c();
  15117. } else {
  15118. if_block.p(ctx, dirty);
  15119. }
  15120. transition_in(if_block, 1);
  15121. if_block.m(p, null);
  15122. } else {
  15123. if_block = null;
  15124. }
  15125. }
  15126. if (!current || dirty[1] & /*statusTransform*/ 128) {
  15127. attr(p, "style", /*statusTransform*/ ctx[38]);
  15128. }
  15129. if (!current || dirty[0] & /*$statusOpacity*/ 16777216 && div_style_value !== (div_style_value = `opacity: ${/*$statusOpacity*/ ctx[24]}`)) {
  15130. attr(div, "style", div_style_value);
  15131. }
  15132. },
  15133. i(local) {
  15134. if (current) return;
  15135. transition_in(if_block);
  15136. current = true;
  15137. },
  15138. o(local) {
  15139. transition_out(if_block);
  15140. current = false;
  15141. },
  15142. d(detaching) {
  15143. if (detaching) detach(div);
  15144. if (~current_block_type_index) {
  15145. if_blocks[current_block_type_index].d();
  15146. }
  15147. }
  15148. };
  15149. }
  15150. // (2476:42)
  15151. function create_if_block_8(ctx) {
  15152. let statusmessage;
  15153. let t;
  15154. let if_block_anchor;
  15155. let current;
  15156. statusmessage = new StatusMessage({
  15157. props: {
  15158. text: /*statusState*/ ctx[13].text || "",
  15159. onmeasure: /*offsetAside*/ ctx[126]
  15160. }
  15161. });
  15162. let if_block = /*statusState*/ ctx[13].aside && create_if_block_9(ctx);
  15163. return {
  15164. c() {
  15165. create_component(statusmessage.$$.fragment);
  15166. t = space();
  15167. if (if_block) if_block.c();
  15168. if_block_anchor = empty();
  15169. },
  15170. m(target, anchor) {
  15171. mount_component(statusmessage, target, anchor);
  15172. insert(target, t, anchor);
  15173. if (if_block) if_block.m(target, anchor);
  15174. insert(target, if_block_anchor, anchor);
  15175. current = true;
  15176. },
  15177. p(ctx, dirty) {
  15178. const statusmessage_changes = {};
  15179. if (dirty[0] & /*statusState*/ 8192) statusmessage_changes.text = /*statusState*/ ctx[13].text || "";
  15180. statusmessage.$set(statusmessage_changes);
  15181. if (/*statusState*/ ctx[13].aside) {
  15182. if (if_block) {
  15183. if_block.p(ctx, dirty);
  15184. if (dirty[0] & /*statusState*/ 8192) {
  15185. transition_in(if_block, 1);
  15186. }
  15187. } else {
  15188. if_block = create_if_block_9(ctx);
  15189. if_block.c();
  15190. transition_in(if_block, 1);
  15191. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  15192. }
  15193. } else if (if_block) {
  15194. group_outros();
  15195. transition_out(if_block, 1, 1, () => {
  15196. if_block = null;
  15197. });
  15198. check_outros();
  15199. }
  15200. },
  15201. i(local) {
  15202. if (current) return;
  15203. transition_in(statusmessage.$$.fragment, local);
  15204. transition_in(if_block);
  15205. current = true;
  15206. },
  15207. o(local) {
  15208. transition_out(statusmessage.$$.fragment, local);
  15209. transition_out(if_block);
  15210. current = false;
  15211. },
  15212. d(detaching) {
  15213. destroy_component(statusmessage, detaching);
  15214. if (detaching) detach(t);
  15215. if (if_block) if_block.d(detaching);
  15216. if (detaching) detach(if_block_anchor);
  15217. }
  15218. };
  15219. }
  15220. // (2466:20) {#if isSupportsError}
  15221. function create_if_block_7(ctx) {
  15222. let statusmessage;
  15223. let t;
  15224. let statusaside;
  15225. let current;
  15226. statusmessage = new StatusMessage({
  15227. props: {
  15228. text: /*isSupportsError*/ ctx[23],
  15229. onmeasure: /*offsetAside*/ ctx[126]
  15230. }
  15231. });
  15232. statusaside = new StatusAside({
  15233. props: {
  15234. class: "PinturaStatusIcon",
  15235. offset: /*$asideOffset*/ ctx[42],
  15236. opacity: /*$asideOpacity*/ ctx[43],
  15237. $$slots: { default: [create_default_slot_4$1] },
  15238. $$scope: { ctx }
  15239. }
  15240. });
  15241. return {
  15242. c() {
  15243. create_component(statusmessage.$$.fragment);
  15244. t = space();
  15245. create_component(statusaside.$$.fragment);
  15246. },
  15247. m(target, anchor) {
  15248. mount_component(statusmessage, target, anchor);
  15249. insert(target, t, anchor);
  15250. mount_component(statusaside, target, anchor);
  15251. current = true;
  15252. },
  15253. p(ctx, dirty) {
  15254. const statusmessage_changes = {};
  15255. if (dirty[0] & /*isSupportsError*/ 8388608) statusmessage_changes.text = /*isSupportsError*/ ctx[23];
  15256. statusmessage.$set(statusmessage_changes);
  15257. const statusaside_changes = {};
  15258. if (dirty[1] & /*$asideOffset*/ 2048) statusaside_changes.offset = /*$asideOffset*/ ctx[42];
  15259. if (dirty[1] & /*$asideOpacity*/ 4096) statusaside_changes.opacity = /*$asideOpacity*/ ctx[43];
  15260. if (dirty[0] & /*locale*/ 4 | dirty[11] & /*$$scope*/ 134217728) {
  15261. statusaside_changes.$$scope = { dirty, ctx };
  15262. }
  15263. statusaside.$set(statusaside_changes);
  15264. },
  15265. i(local) {
  15266. if (current) return;
  15267. transition_in(statusmessage.$$.fragment, local);
  15268. transition_in(statusaside.$$.fragment, local);
  15269. current = true;
  15270. },
  15271. o(local) {
  15272. transition_out(statusmessage.$$.fragment, local);
  15273. transition_out(statusaside.$$.fragment, local);
  15274. current = false;
  15275. },
  15276. d(detaching) {
  15277. destroy_component(statusmessage, detaching);
  15278. if (detaching) detach(t);
  15279. destroy_component(statusaside, detaching);
  15280. }
  15281. };
  15282. }
  15283. // (2479:24) {#if statusState.aside}
  15284. function create_if_block_9(ctx) {
  15285. let statusaside;
  15286. let current;
  15287. statusaside = new StatusAside({
  15288. props: {
  15289. class: "PinturaStatusButton",
  15290. offset: /*$asideOffset*/ ctx[42],
  15291. opacity: /*$asideOpacity*/ ctx[43],
  15292. $$slots: { default: [create_default_slot_6] },
  15293. $$scope: { ctx }
  15294. }
  15295. });
  15296. return {
  15297. c() {
  15298. create_component(statusaside.$$.fragment);
  15299. },
  15300. m(target, anchor) {
  15301. mount_component(statusaside, target, anchor);
  15302. current = true;
  15303. },
  15304. p(ctx, dirty) {
  15305. const statusaside_changes = {};
  15306. if (dirty[1] & /*$asideOffset*/ 2048) statusaside_changes.offset = /*$asideOffset*/ ctx[42];
  15307. if (dirty[1] & /*$asideOpacity*/ 4096) statusaside_changes.opacity = /*$asideOpacity*/ ctx[43];
  15308. if (dirty[0] & /*statusState*/ 8192 | dirty[11] & /*$$scope*/ 134217728) {
  15309. statusaside_changes.$$scope = { dirty, ctx };
  15310. }
  15311. statusaside.$set(statusaside_changes);
  15312. },
  15313. i(local) {
  15314. if (current) return;
  15315. transition_in(statusaside.$$.fragment, local);
  15316. current = true;
  15317. },
  15318. o(local) {
  15319. transition_out(statusaside.$$.fragment, local);
  15320. current = false;
  15321. },
  15322. d(detaching) {
  15323. destroy_component(statusaside, detaching);
  15324. }
  15325. };
  15326. }
  15327. // (2485:32) {#if statusState.progressIndicator.visible}
  15328. function create_if_block_11(ctx) {
  15329. let progressindicator;
  15330. let current;
  15331. progressindicator = new ProgressIndicator({
  15332. props: {
  15333. progress: /*statusState*/ ctx[13].progressIndicator.progress
  15334. }
  15335. });
  15336. return {
  15337. c() {
  15338. create_component(progressindicator.$$.fragment);
  15339. },
  15340. m(target, anchor) {
  15341. mount_component(progressindicator, target, anchor);
  15342. current = true;
  15343. },
  15344. p(ctx, dirty) {
  15345. const progressindicator_changes = {};
  15346. if (dirty[0] & /*statusState*/ 8192) progressindicator_changes.progress = /*statusState*/ ctx[13].progressIndicator.progress;
  15347. progressindicator.$set(progressindicator_changes);
  15348. },
  15349. i(local) {
  15350. if (current) return;
  15351. transition_in(progressindicator.$$.fragment, local);
  15352. current = true;
  15353. },
  15354. o(local) {
  15355. transition_out(progressindicator.$$.fragment, local);
  15356. current = false;
  15357. },
  15358. d(detaching) {
  15359. destroy_component(progressindicator, detaching);
  15360. }
  15361. };
  15362. }
  15363. // (2491:32) {#if statusState.closeButton && statusState.text}
  15364. function create_if_block_10(ctx) {
  15365. let button;
  15366. let current;
  15367. const button_spread_levels = [/*statusState*/ ctx[13].closeButton, { hideLabel: true }];
  15368. let button_props = {};
  15369. for (let i = 0; i < button_spread_levels.length; i += 1) {
  15370. button_props = assign(button_props, button_spread_levels[i]);
  15371. }
  15372. button = new Button({ props: button_props });
  15373. return {
  15374. c() {
  15375. create_component(button.$$.fragment);
  15376. },
  15377. m(target, anchor) {
  15378. mount_component(button, target, anchor);
  15379. current = true;
  15380. },
  15381. p(ctx, dirty) {
  15382. const button_changes = (dirty[0] & /*statusState*/ 8192)
  15383. ? get_spread_update(button_spread_levels, [
  15384. get_spread_object(/*statusState*/ ctx[13].closeButton),
  15385. button_spread_levels[1]
  15386. ])
  15387. : {};
  15388. button.$set(button_changes);
  15389. },
  15390. i(local) {
  15391. if (current) return;
  15392. transition_in(button.$$.fragment, local);
  15393. current = true;
  15394. },
  15395. o(local) {
  15396. transition_out(button.$$.fragment, local);
  15397. current = false;
  15398. },
  15399. d(detaching) {
  15400. destroy_component(button, detaching);
  15401. }
  15402. };
  15403. }
  15404. // (2480:28) <StatusAside class="PinturaStatusButton" offset={$asideOffset} opacity={$asideOpacity} >
  15405. function create_default_slot_6(ctx) {
  15406. let t;
  15407. let if_block1_anchor;
  15408. let current;
  15409. let if_block0 = /*statusState*/ ctx[13].progressIndicator.visible && create_if_block_11(ctx);
  15410. let if_block1 = /*statusState*/ ctx[13].closeButton && /*statusState*/ ctx[13].text && create_if_block_10(ctx);
  15411. return {
  15412. c() {
  15413. if (if_block0) if_block0.c();
  15414. t = space();
  15415. if (if_block1) if_block1.c();
  15416. if_block1_anchor = empty();
  15417. },
  15418. m(target, anchor) {
  15419. if (if_block0) if_block0.m(target, anchor);
  15420. insert(target, t, anchor);
  15421. if (if_block1) if_block1.m(target, anchor);
  15422. insert(target, if_block1_anchor, anchor);
  15423. current = true;
  15424. },
  15425. p(ctx, dirty) {
  15426. if (/*statusState*/ ctx[13].progressIndicator.visible) {
  15427. if (if_block0) {
  15428. if_block0.p(ctx, dirty);
  15429. if (dirty[0] & /*statusState*/ 8192) {
  15430. transition_in(if_block0, 1);
  15431. }
  15432. } else {
  15433. if_block0 = create_if_block_11(ctx);
  15434. if_block0.c();
  15435. transition_in(if_block0, 1);
  15436. if_block0.m(t.parentNode, t);
  15437. }
  15438. } else if (if_block0) {
  15439. group_outros();
  15440. transition_out(if_block0, 1, 1, () => {
  15441. if_block0 = null;
  15442. });
  15443. check_outros();
  15444. }
  15445. if (/*statusState*/ ctx[13].closeButton && /*statusState*/ ctx[13].text) {
  15446. if (if_block1) {
  15447. if_block1.p(ctx, dirty);
  15448. if (dirty[0] & /*statusState*/ 8192) {
  15449. transition_in(if_block1, 1);
  15450. }
  15451. } else {
  15452. if_block1 = create_if_block_10(ctx);
  15453. if_block1.c();
  15454. transition_in(if_block1, 1);
  15455. if_block1.m(if_block1_anchor.parentNode, if_block1_anchor);
  15456. }
  15457. } else if (if_block1) {
  15458. group_outros();
  15459. transition_out(if_block1, 1, 1, () => {
  15460. if_block1 = null;
  15461. });
  15462. check_outros();
  15463. }
  15464. },
  15465. i(local) {
  15466. if (current) return;
  15467. transition_in(if_block0);
  15468. transition_in(if_block1);
  15469. current = true;
  15470. },
  15471. o(local) {
  15472. transition_out(if_block0);
  15473. transition_out(if_block1);
  15474. current = false;
  15475. },
  15476. d(detaching) {
  15477. if (if_block0) if_block0.d(detaching);
  15478. if (detaching) detach(t);
  15479. if (if_block1) if_block1.d(detaching);
  15480. if (detaching) detach(if_block1_anchor);
  15481. }
  15482. };
  15483. }
  15484. // (2474:28) <Icon>
  15485. function create_default_slot_5(ctx) {
  15486. let g;
  15487. let raw_value = /*locale*/ ctx[2].iconSupportError + "";
  15488. return {
  15489. c() {
  15490. g = svg_element("g");
  15491. },
  15492. m(target, anchor) {
  15493. insert(target, g, anchor);
  15494. g.innerHTML = raw_value;
  15495. },
  15496. p(ctx, dirty) {
  15497. if (dirty[0] & /*locale*/ 4 && raw_value !== (raw_value = /*locale*/ ctx[2].iconSupportError + "")) g.innerHTML = raw_value; },
  15498. d(detaching) {
  15499. if (detaching) detach(g);
  15500. }
  15501. };
  15502. }
  15503. // (2469:24) <StatusAside class="PinturaStatusIcon" offset={$asideOffset} opacity={$asideOpacity} >
  15504. function create_default_slot_4$1(ctx) {
  15505. let icon;
  15506. let current;
  15507. icon = new Icon({
  15508. props: {
  15509. $$slots: { default: [create_default_slot_5] },
  15510. $$scope: { ctx }
  15511. }
  15512. });
  15513. return {
  15514. c() {
  15515. create_component(icon.$$.fragment);
  15516. },
  15517. m(target, anchor) {
  15518. mount_component(icon, target, anchor);
  15519. current = true;
  15520. },
  15521. p(ctx, dirty) {
  15522. const icon_changes = {};
  15523. if (dirty[0] & /*locale*/ 4 | dirty[11] & /*$$scope*/ 134217728) {
  15524. icon_changes.$$scope = { dirty, ctx };
  15525. }
  15526. icon.$set(icon_changes);
  15527. },
  15528. i(local) {
  15529. if (current) return;
  15530. transition_in(icon.$$.fragment, local);
  15531. current = true;
  15532. },
  15533. o(local) {
  15534. transition_out(icon.$$.fragment, local);
  15535. current = false;
  15536. },
  15537. d(detaching) {
  15538. destroy_component(icon, detaching);
  15539. }
  15540. };
  15541. }
  15542. // (2501:8) {#if isReady}
  15543. function create_if_block_2$6(ctx) {
  15544. let t0;
  15545. let t1;
  15546. let current_block_type_index;
  15547. let if_block2;
  15548. let t2;
  15549. let canvas;
  15550. let t3;
  15551. let div;
  15552. let current;
  15553. let if_block0 = /*enableToolbar*/ ctx[6] && create_if_block_5$3(ctx);
  15554. let if_block1 = /*shouldRenderTabs*/ ctx[17] && /*showUtils*/ ctx[15] && create_if_block_4$4(ctx);
  15555. const if_block_creators = [create_if_block_3$4, create_else_block$2];
  15556. const if_blocks = [];
  15557. function select_block_type_1(ctx, dirty) {
  15558. if (/*shouldRenderTabs*/ ctx[17]) return 0;
  15559. return 1;
  15560. }
  15561. current_block_type_index = select_block_type_1(ctx);
  15562. if_block2 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  15563. canvas = new Canvas({
  15564. props: {
  15565. animate: /*$shouldAnimate*/ ctx[18],
  15566. pixelRatio: /*$pixelRatio*/ ctx[46],
  15567. backgroundColor: /*$rootBackgroundColor*/ ctx[47],
  15568. maskRect: /*$imageSelectionRectPresentation*/ ctx[37],
  15569. maskOpacity: /*imageCanvasState*/ ctx[36]
  15570. ? /*imageCanvasState*/ ctx[36].maskOpacity
  15571. : 1,
  15572. maskFrameOpacity: /*$utilSelectedStore*/ ctx[48] === "frame" && /*$stagePadded*/ ctx[49]
  15573. ? 0
  15574. : 0.95,
  15575. images: /*$activeImages*/ ctx[22],
  15576. interfaceImages: /*$interfaceImages*/ ctx[50],
  15577. loadImageData: /*imageSourceToImageData*/ ctx[8],
  15578. willRender: /*func_2*/ ctx[282]
  15579. }
  15580. });
  15581. return {
  15582. c() {
  15583. if (if_block0) if_block0.c();
  15584. t0 = space();
  15585. if (if_block1) if_block1.c();
  15586. t1 = space();
  15587. if_block2.c();
  15588. t2 = space();
  15589. create_component(canvas.$$.fragment);
  15590. t3 = space();
  15591. div = element("div");
  15592. attr(div, "class", "PinturaRootPortal");
  15593. },
  15594. m(target, anchor) {
  15595. if (if_block0) if_block0.m(target, anchor);
  15596. insert(target, t0, anchor);
  15597. if (if_block1) if_block1.m(target, anchor);
  15598. insert(target, t1, anchor);
  15599. if_blocks[current_block_type_index].m(target, anchor);
  15600. insert(target, t2, anchor);
  15601. mount_component(canvas, target, anchor);
  15602. insert(target, t3, anchor);
  15603. insert(target, div, anchor);
  15604. /*div_binding*/ ctx[283](div);
  15605. current = true;
  15606. },
  15607. p(ctx, dirty) {
  15608. if (/*enableToolbar*/ ctx[6]) {
  15609. if (if_block0) {
  15610. if_block0.p(ctx, dirty);
  15611. if (dirty[0] & /*enableToolbar*/ 64) {
  15612. transition_in(if_block0, 1);
  15613. }
  15614. } else {
  15615. if_block0 = create_if_block_5$3(ctx);
  15616. if_block0.c();
  15617. transition_in(if_block0, 1);
  15618. if_block0.m(t0.parentNode, t0);
  15619. }
  15620. } else if (if_block0) {
  15621. group_outros();
  15622. transition_out(if_block0, 1, 1, () => {
  15623. if_block0 = null;
  15624. });
  15625. check_outros();
  15626. }
  15627. if (/*shouldRenderTabs*/ ctx[17] && /*showUtils*/ ctx[15]) {
  15628. if (if_block1) {
  15629. if_block1.p(ctx, dirty);
  15630. if (dirty[0] & /*shouldRenderTabs, showUtils*/ 163840) {
  15631. transition_in(if_block1, 1);
  15632. }
  15633. } else {
  15634. if_block1 = create_if_block_4$4(ctx);
  15635. if_block1.c();
  15636. transition_in(if_block1, 1);
  15637. if_block1.m(t1.parentNode, t1);
  15638. }
  15639. } else if (if_block1) {
  15640. group_outros();
  15641. transition_out(if_block1, 1, 1, () => {
  15642. if_block1 = null;
  15643. });
  15644. check_outros();
  15645. }
  15646. let previous_block_index = current_block_type_index;
  15647. current_block_type_index = select_block_type_1(ctx);
  15648. if (current_block_type_index === previous_block_index) {
  15649. if_blocks[current_block_type_index].p(ctx, dirty);
  15650. } else {
  15651. group_outros();
  15652. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  15653. if_blocks[previous_block_index] = null;
  15654. });
  15655. check_outros();
  15656. if_block2 = if_blocks[current_block_type_index];
  15657. if (!if_block2) {
  15658. if_block2 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  15659. if_block2.c();
  15660. } else {
  15661. if_block2.p(ctx, dirty);
  15662. }
  15663. transition_in(if_block2, 1);
  15664. if_block2.m(t2.parentNode, t2);
  15665. }
  15666. const canvas_changes = {};
  15667. if (dirty[0] & /*$shouldAnimate*/ 262144) canvas_changes.animate = /*$shouldAnimate*/ ctx[18];
  15668. if (dirty[1] & /*$pixelRatio*/ 32768) canvas_changes.pixelRatio = /*$pixelRatio*/ ctx[46];
  15669. if (dirty[1] & /*$rootBackgroundColor*/ 65536) canvas_changes.backgroundColor = /*$rootBackgroundColor*/ ctx[47];
  15670. if (dirty[1] & /*$imageSelectionRectPresentation*/ 64) canvas_changes.maskRect = /*$imageSelectionRectPresentation*/ ctx[37];
  15671. if (dirty[1] & /*imageCanvasState*/ 32) canvas_changes.maskOpacity = /*imageCanvasState*/ ctx[36]
  15672. ? /*imageCanvasState*/ ctx[36].maskOpacity
  15673. : 1;
  15674. if (dirty[1] & /*$utilSelectedStore, $stagePadded*/ 393216) canvas_changes.maskFrameOpacity = /*$utilSelectedStore*/ ctx[48] === "frame" && /*$stagePadded*/ ctx[49]
  15675. ? 0
  15676. : 0.95;
  15677. if (dirty[0] & /*$activeImages*/ 4194304) canvas_changes.images = /*$activeImages*/ ctx[22];
  15678. if (dirty[1] & /*$interfaceImages*/ 524288) canvas_changes.interfaceImages = /*$interfaceImages*/ ctx[50];
  15679. if (dirty[0] & /*imageSourceToImageData*/ 256) canvas_changes.loadImageData = /*imageSourceToImageData*/ ctx[8];
  15680. if (dirty[0] & /*willRenderCanvas, blendShapes*/ 268435488 | dirty[1] & /*$imageAnnotation, $imageDecoration, $imageFrame, $imageOverlay*/ 15728640) canvas_changes.willRender = /*func_2*/ ctx[282];
  15681. canvas.$set(canvas_changes);
  15682. },
  15683. i(local) {
  15684. if (current) return;
  15685. transition_in(if_block0);
  15686. transition_in(if_block1);
  15687. transition_in(if_block2);
  15688. transition_in(canvas.$$.fragment, local);
  15689. current = true;
  15690. },
  15691. o(local) {
  15692. transition_out(if_block0);
  15693. transition_out(if_block1);
  15694. transition_out(if_block2);
  15695. transition_out(canvas.$$.fragment, local);
  15696. current = false;
  15697. },
  15698. d(detaching) {
  15699. if (if_block0) if_block0.d(detaching);
  15700. if (detaching) detach(t0);
  15701. if (if_block1) if_block1.d(detaching);
  15702. if (detaching) detach(t1);
  15703. if_blocks[current_block_type_index].d(detaching);
  15704. if (detaching) detach(t2);
  15705. destroy_component(canvas, detaching);
  15706. if (detaching) detach(t3);
  15707. if (detaching) detach(div);
  15708. /*div_binding*/ ctx[283](null);
  15709. }
  15710. };
  15711. }
  15712. // (2502:12) {#if enableToolbar}
  15713. function create_if_block_5$3(ctx) {
  15714. let div;
  15715. let dynamiccomponenttree;
  15716. let current;
  15717. let mounted;
  15718. let dispose;
  15719. dynamiccomponenttree = new DynamicComponentTree_1({
  15720. props: { items: /*toolbarItems*/ ctx[39] }
  15721. });
  15722. return {
  15723. c() {
  15724. div = element("div");
  15725. create_component(dynamiccomponenttree.$$.fragment);
  15726. attr(div, "class", "PinturaNav PinturaNavTools");
  15727. },
  15728. m(target, anchor) {
  15729. insert(target, div, anchor);
  15730. mount_component(dynamiccomponenttree, div, null);
  15731. current = true;
  15732. if (!mounted) {
  15733. dispose = [
  15734. listen(div, "measure", /*measure_handler*/ ctx[267]),
  15735. action_destroyer(measurable.call(null, div))
  15736. ];
  15737. mounted = true;
  15738. }
  15739. },
  15740. p(ctx, dirty) {
  15741. const dynamiccomponenttree_changes = {};
  15742. if (dirty[1] & /*toolbarItems*/ 256) dynamiccomponenttree_changes.items = /*toolbarItems*/ ctx[39];
  15743. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  15744. },
  15745. i(local) {
  15746. if (current) return;
  15747. transition_in(dynamiccomponenttree.$$.fragment, local);
  15748. current = true;
  15749. },
  15750. o(local) {
  15751. transition_out(dynamiccomponenttree.$$.fragment, local);
  15752. current = false;
  15753. },
  15754. d(detaching) {
  15755. if (detaching) detach(div);
  15756. destroy_component(dynamiccomponenttree);
  15757. mounted = false;
  15758. run_all(dispose);
  15759. }
  15760. };
  15761. }
  15762. // (2512:12) {#if shouldRenderTabs && showUtils}
  15763. function create_if_block_4$4(ctx) {
  15764. let div;
  15765. let scrollable;
  15766. let current;
  15767. scrollable = new Scrollable({
  15768. props: {
  15769. elasticity: /*elasticityMultiplier*/ ctx[4] * scrollElasticity,
  15770. scrollDirection: /*isLandscape*/ ctx[34] ? "y" : "x",
  15771. $$slots: { default: [create_default_slot_1$4] },
  15772. $$scope: { ctx }
  15773. }
  15774. });
  15775. return {
  15776. c() {
  15777. div = element("div");
  15778. create_component(scrollable.$$.fragment);
  15779. attr(div, "class", "PinturaNav PinturaNavMain");
  15780. },
  15781. m(target, anchor) {
  15782. insert(target, div, anchor);
  15783. mount_component(scrollable, div, null);
  15784. current = true;
  15785. },
  15786. p(ctx, dirty) {
  15787. const scrollable_changes = {};
  15788. if (dirty[0] & /*elasticityMultiplier*/ 16) scrollable_changes.elasticity = /*elasticityMultiplier*/ ctx[4] * scrollElasticity;
  15789. if (dirty[1] & /*isLandscape*/ 8) scrollable_changes.scrollDirection = /*isLandscape*/ ctx[34] ? "y" : "x";
  15790. if (dirty[0] & /*tabsConfig, utilSelected*/ 1074266112 | dirty[1] & /*tabs*/ 1 | dirty[11] & /*$$scope*/ 134217728) {
  15791. scrollable_changes.$$scope = { dirty, ctx };
  15792. }
  15793. scrollable.$set(scrollable_changes);
  15794. },
  15795. i(local) {
  15796. if (current) return;
  15797. transition_in(scrollable.$$.fragment, local);
  15798. current = true;
  15799. },
  15800. o(local) {
  15801. transition_out(scrollable.$$.fragment, local);
  15802. current = false;
  15803. },
  15804. d(detaching) {
  15805. if (detaching) detach(div);
  15806. destroy_component(scrollable);
  15807. }
  15808. };
  15809. }
  15810. // (2524:28) <Icon>
  15811. function create_default_slot_3$1(ctx) {
  15812. let g;
  15813. let raw_value = /*tab*/ ctx[367].icon + "";
  15814. return {
  15815. c() {
  15816. g = svg_element("g");
  15817. },
  15818. m(target, anchor) {
  15819. insert(target, g, anchor);
  15820. g.innerHTML = raw_value;
  15821. },
  15822. p(ctx, dirty) {
  15823. if (dirty[11] & /*tab*/ 67108864 && raw_value !== (raw_value = /*tab*/ ctx[367].icon + "")) g.innerHTML = raw_value; },
  15824. d(detaching) {
  15825. if (detaching) detach(g);
  15826. }
  15827. };
  15828. }
  15829. // (2518:24) <TabList {...tabsConfig} {tabs} on:select={({ detail }) => (utilSelected = detail)} let:tab >
  15830. function create_default_slot_2$3(ctx) {
  15831. let icon;
  15832. let t0;
  15833. let span;
  15834. let t1_value = /*tab*/ ctx[367].label + "";
  15835. let t1;
  15836. let current;
  15837. icon = new Icon({
  15838. props: {
  15839. $$slots: { default: [create_default_slot_3$1] },
  15840. $$scope: { ctx }
  15841. }
  15842. });
  15843. return {
  15844. c() {
  15845. create_component(icon.$$.fragment);
  15846. t0 = space();
  15847. span = element("span");
  15848. t1 = text(t1_value);
  15849. },
  15850. m(target, anchor) {
  15851. mount_component(icon, target, anchor);
  15852. insert(target, t0, anchor);
  15853. insert(target, span, anchor);
  15854. append(span, t1);
  15855. current = true;
  15856. },
  15857. p(ctx, dirty) {
  15858. const icon_changes = {};
  15859. if (dirty[11] & /*$$scope, tab*/ 201326592) {
  15860. icon_changes.$$scope = { dirty, ctx };
  15861. }
  15862. icon.$set(icon_changes);
  15863. if ((!current || dirty[11] & /*tab*/ 67108864) && t1_value !== (t1_value = /*tab*/ ctx[367].label + "")) set_data(t1, t1_value);
  15864. },
  15865. i(local) {
  15866. if (current) return;
  15867. transition_in(icon.$$.fragment, local);
  15868. current = true;
  15869. },
  15870. o(local) {
  15871. transition_out(icon.$$.fragment, local);
  15872. current = false;
  15873. },
  15874. d(detaching) {
  15875. destroy_component(icon, detaching);
  15876. if (detaching) detach(t0);
  15877. if (detaching) detach(span);
  15878. }
  15879. };
  15880. }
  15881. // (2514:20) <Scrollable elasticity={elasticityMultiplier * scrollElasticity} scrollDirection={isLandscape ? 'y' : 'x'} >
  15882. function create_default_slot_1$4(ctx) {
  15883. let tablist;
  15884. let current;
  15885. const tablist_spread_levels = [/*tabsConfig*/ ctx[30], { tabs: /*tabs*/ ctx[31] }];
  15886. let tablist_props = {
  15887. $$slots: {
  15888. default: [
  15889. create_default_slot_2$3,
  15890. ({ tab }) => ({ 367: tab }),
  15891. ({ tab }) => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, tab ? 67108864 : 0]
  15892. ]
  15893. },
  15894. $$scope: { ctx }
  15895. };
  15896. for (let i = 0; i < tablist_spread_levels.length; i += 1) {
  15897. tablist_props = assign(tablist_props, tablist_spread_levels[i]);
  15898. }
  15899. tablist = new TabList({ props: tablist_props });
  15900. tablist.$on("select", /*select_handler*/ ctx[268]);
  15901. return {
  15902. c() {
  15903. create_component(tablist.$$.fragment);
  15904. },
  15905. m(target, anchor) {
  15906. mount_component(tablist, target, anchor);
  15907. current = true;
  15908. },
  15909. p(ctx, dirty) {
  15910. const tablist_changes = (dirty[0] & /*tabsConfig*/ 1073741824 | dirty[1] & /*tabs*/ 1)
  15911. ? get_spread_update(tablist_spread_levels, [
  15912. dirty[0] & /*tabsConfig*/ 1073741824 && get_spread_object(/*tabsConfig*/ ctx[30]),
  15913. dirty[1] & /*tabs*/ 1 && { tabs: /*tabs*/ ctx[31] }
  15914. ])
  15915. : {};
  15916. if (dirty[11] & /*$$scope, tab*/ 201326592) {
  15917. tablist_changes.$$scope = { dirty, ctx };
  15918. }
  15919. tablist.$set(tablist_changes);
  15920. },
  15921. i(local) {
  15922. if (current) return;
  15923. transition_in(tablist.$$.fragment, local);
  15924. current = true;
  15925. },
  15926. o(local) {
  15927. transition_out(tablist.$$.fragment, local);
  15928. current = false;
  15929. },
  15930. d(detaching) {
  15931. destroy_component(tablist, detaching);
  15932. }
  15933. };
  15934. }
  15935. // (2557:12) {:else}
  15936. function create_else_block$2(ctx) {
  15937. let panel;
  15938. let updating_component;
  15939. let current;
  15940. function panel_component_binding_1(value) {
  15941. /*panel_component_binding_1*/ ctx[277](value);
  15942. }
  15943. let panel_props = {
  15944. class: "PinturaMain",
  15945. content: {
  15946. .../*utilsMerged*/ ctx[20].find(/*func_1*/ ctx[276]),
  15947. props: /*pluginOptions*/ ctx[7][/*utilSelected*/ ctx[19]]
  15948. },
  15949. locale: /*locale*/ ctx[2],
  15950. isAnimated: /*$shouldAnimate*/ ctx[18],
  15951. stores: /*utilStores*/ ctx[115]
  15952. };
  15953. if (/*pluginInterface*/ ctx[0][/*utilSelected*/ ctx[19]] !== void 0) {
  15954. panel_props.component = /*pluginInterface*/ ctx[0][/*utilSelected*/ ctx[19]];
  15955. }
  15956. panel = new Panel({ props: panel_props });
  15957. binding_callbacks.push(() => bind(panel, "component", panel_component_binding_1));
  15958. panel.$on("measure", /*measure_handler_3*/ ctx[278]);
  15959. panel.$on("show", /*show_handler_1*/ ctx[279]);
  15960. panel.$on("hide", /*hide_handler_1*/ ctx[280]);
  15961. panel.$on("fade", /*fade_handler_1*/ ctx[281]);
  15962. return {
  15963. c() {
  15964. create_component(panel.$$.fragment);
  15965. },
  15966. m(target, anchor) {
  15967. mount_component(panel, target, anchor);
  15968. current = true;
  15969. },
  15970. p(ctx, dirty) {
  15971. const panel_changes = {};
  15972. if (dirty[0] & /*utilsMerged, utilSelected, pluginOptions*/ 1572992) panel_changes.content = {
  15973. .../*utilsMerged*/ ctx[20].find(/*func_1*/ ctx[276]),
  15974. props: /*pluginOptions*/ ctx[7][/*utilSelected*/ ctx[19]]
  15975. };
  15976. if (dirty[0] & /*locale*/ 4) panel_changes.locale = /*locale*/ ctx[2];
  15977. if (dirty[0] & /*$shouldAnimate*/ 262144) panel_changes.isAnimated = /*$shouldAnimate*/ ctx[18];
  15978. if (!updating_component && dirty[0] & /*pluginInterface, utilSelected*/ 524289) {
  15979. updating_component = true;
  15980. panel_changes.component = /*pluginInterface*/ ctx[0][/*utilSelected*/ ctx[19]];
  15981. add_flush_callback(() => updating_component = false);
  15982. }
  15983. panel.$set(panel_changes);
  15984. },
  15985. i(local) {
  15986. if (current) return;
  15987. transition_in(panel.$$.fragment, local);
  15988. current = true;
  15989. },
  15990. o(local) {
  15991. transition_out(panel.$$.fragment, local);
  15992. current = false;
  15993. },
  15994. d(detaching) {
  15995. destroy_component(panel, detaching);
  15996. }
  15997. };
  15998. }
  15999. // (2531:12) {#if shouldRenderTabs}
  16000. function create_if_block_3$4(ctx) {
  16001. let tabpanels;
  16002. let current;
  16003. const tabpanels_spread_levels = [
  16004. { class: "PinturaMain" },
  16005. { visible: /*utilsVisible*/ ctx[27] },
  16006. /*tabsConfig*/ ctx[30],
  16007. { panels: /*panels*/ ctx[32] }
  16008. ];
  16009. let tabpanels_props = {
  16010. $$slots: {
  16011. default: [
  16012. create_default_slot$a,
  16013. ({ panel }) => ({ 366: panel }),
  16014. ({ panel }) => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, panel ? 33554432 : 0]
  16015. ]
  16016. },
  16017. $$scope: { ctx }
  16018. };
  16019. for (let i = 0; i < tabpanels_spread_levels.length; i += 1) {
  16020. tabpanels_props = assign(tabpanels_props, tabpanels_spread_levels[i]);
  16021. }
  16022. tabpanels = new TabPanels({ props: tabpanels_props });
  16023. tabpanels.$on("measure", /*measure_handler_2*/ ctx[275]);
  16024. return {
  16025. c() {
  16026. create_component(tabpanels.$$.fragment);
  16027. },
  16028. m(target, anchor) {
  16029. mount_component(tabpanels, target, anchor);
  16030. current = true;
  16031. },
  16032. p(ctx, dirty) {
  16033. const tabpanels_changes = (dirty[0] & /*utilsVisible, tabsConfig*/ 1207959552 | dirty[1] & /*panels*/ 2)
  16034. ? get_spread_update(tabpanels_spread_levels, [
  16035. tabpanels_spread_levels[0],
  16036. dirty[0] & /*utilsVisible*/ 134217728 && { visible: /*utilsVisible*/ ctx[27] },
  16037. dirty[0] & /*tabsConfig*/ 1073741824 && get_spread_object(/*tabsConfig*/ ctx[30]),
  16038. dirty[1] & /*panels*/ 2 && { panels: /*panels*/ ctx[32] }
  16039. ])
  16040. : {};
  16041. if (dirty[0] & /*utilsMerged, pluginOptions, locale, utilSelected, $shouldAnimate, pluginInterface, utilsVisible, utilsVisibleFraction*/ 138150021 | dirty[1] & /*$utilRect*/ 16384 | dirty[11] & /*$$scope, panel*/ 167772160) {
  16042. tabpanels_changes.$$scope = { dirty, ctx };
  16043. }
  16044. tabpanels.$set(tabpanels_changes);
  16045. },
  16046. i(local) {
  16047. if (current) return;
  16048. transition_in(tabpanels.$$.fragment, local);
  16049. current = true;
  16050. },
  16051. o(local) {
  16052. transition_out(tabpanels.$$.fragment, local);
  16053. current = false;
  16054. },
  16055. d(detaching) {
  16056. destroy_component(tabpanels, detaching);
  16057. }
  16058. };
  16059. }
  16060. // (2532:16) <TabPanels class="PinturaMain" visible={utilsVisible} {...tabsConfig} {panels} let:panel on:measure={(e) => ($tabRect = e.detail)} >
  16061. function create_default_slot$a(ctx) {
  16062. let panel;
  16063. let updating_component;
  16064. let current;
  16065. function func(...args) {
  16066. return /*func*/ ctx[269](/*panel*/ ctx[366], ...args);
  16067. }
  16068. function panel_component_binding(value) {
  16069. /*panel_component_binding*/ ctx[270](value, /*panel*/ ctx[366]);
  16070. }
  16071. function show_handler() {
  16072. return /*show_handler*/ ctx[272](/*panel*/ ctx[366]);
  16073. }
  16074. function hide_handler() {
  16075. return /*hide_handler*/ ctx[273](/*panel*/ ctx[366]);
  16076. }
  16077. function fade_handler(...args) {
  16078. return /*fade_handler*/ ctx[274](/*panel*/ ctx[366], ...args);
  16079. }
  16080. let panel_props = {
  16081. content: {
  16082. .../*utilsMerged*/ ctx[20].find(func),
  16083. props: /*pluginOptions*/ ctx[7][/*panel*/ ctx[366]]
  16084. },
  16085. locale: /*locale*/ ctx[2],
  16086. isActive: /*panel*/ ctx[366] === /*utilSelected*/ ctx[19],
  16087. isAnimated: /*$shouldAnimate*/ ctx[18],
  16088. stores: /*utilStores*/ ctx[115]
  16089. };
  16090. if (/*pluginInterface*/ ctx[0][/*panel*/ ctx[366]] !== void 0) {
  16091. panel_props.component = /*pluginInterface*/ ctx[0][/*panel*/ ctx[366]];
  16092. }
  16093. panel = new Panel({ props: panel_props });
  16094. binding_callbacks.push(() => bind(panel, "component", panel_component_binding));
  16095. panel.$on("measure", /*measure_handler_1*/ ctx[271]);
  16096. panel.$on("show", show_handler);
  16097. panel.$on("hide", hide_handler);
  16098. panel.$on("fade", fade_handler);
  16099. return {
  16100. c() {
  16101. create_component(panel.$$.fragment);
  16102. },
  16103. m(target, anchor) {
  16104. mount_component(panel, target, anchor);
  16105. current = true;
  16106. },
  16107. p(new_ctx, dirty) {
  16108. ctx = new_ctx;
  16109. const panel_changes = {};
  16110. if (dirty[0] & /*utilsMerged, pluginOptions*/ 1048704 | dirty[11] & /*panel*/ 33554432) panel_changes.content = {
  16111. .../*utilsMerged*/ ctx[20].find(func),
  16112. props: /*pluginOptions*/ ctx[7][/*panel*/ ctx[366]]
  16113. };
  16114. if (dirty[0] & /*locale*/ 4) panel_changes.locale = /*locale*/ ctx[2];
  16115. if (dirty[0] & /*utilSelected*/ 524288 | dirty[11] & /*panel*/ 33554432) panel_changes.isActive = /*panel*/ ctx[366] === /*utilSelected*/ ctx[19];
  16116. if (dirty[0] & /*$shouldAnimate*/ 262144) panel_changes.isAnimated = /*$shouldAnimate*/ ctx[18];
  16117. if (!updating_component && dirty[0] & /*pluginInterface*/ 1 | dirty[11] & /*panel*/ 33554432) {
  16118. updating_component = true;
  16119. panel_changes.component = /*pluginInterface*/ ctx[0][/*panel*/ ctx[366]];
  16120. add_flush_callback(() => updating_component = false);
  16121. }
  16122. panel.$set(panel_changes);
  16123. },
  16124. i(local) {
  16125. if (current) return;
  16126. transition_in(panel.$$.fragment, local);
  16127. current = true;
  16128. },
  16129. o(local) {
  16130. transition_out(panel.$$.fragment, local);
  16131. current = false;
  16132. },
  16133. d(detaching) {
  16134. destroy_component(panel, detaching);
  16135. }
  16136. };
  16137. }
  16138. // (2619:4) {#if $disabledTransition > 0}
  16139. function create_if_block$7(ctx) {
  16140. let span;
  16141. let span_style_value;
  16142. return {
  16143. c() {
  16144. span = element("span");
  16145. attr(span, "class", "PinturaEditorOverlay");
  16146. attr(span, "style", span_style_value = `opacity:${/*$disabledTransition*/ ctx[55]}`);
  16147. },
  16148. m(target, anchor) {
  16149. insert(target, span, anchor);
  16150. },
  16151. p(ctx, dirty) {
  16152. if (dirty[1] & /*$disabledTransition*/ 16777216 && span_style_value !== (span_style_value = `opacity:${/*$disabledTransition*/ ctx[55]}`)) {
  16153. attr(span, "style", span_style_value);
  16154. }
  16155. },
  16156. d(detaching) {
  16157. if (detaching) detach(span);
  16158. }
  16159. };
  16160. }
  16161. function create_fragment$u(ctx) {
  16162. let div;
  16163. let t;
  16164. let current;
  16165. let mounted;
  16166. let dispose;
  16167. add_render_callback(/*onwindowresize*/ ctx[266]);
  16168. let if_block0 = /*canRender*/ ctx[40] && create_if_block_1$7(ctx);
  16169. let if_block1 = /*$disabledTransition*/ ctx[55] > 0 && create_if_block$7(ctx);
  16170. return {
  16171. c() {
  16172. div = element("div");
  16173. if (if_block0) if_block0.c();
  16174. t = space();
  16175. if (if_block1) if_block1.c();
  16176. attr(div, "id", /*id*/ ctx[3]);
  16177. attr(div, "class", /*className*/ ctx[33]);
  16178. attr(div, "data-env", /*envStr*/ ctx[35]);
  16179. },
  16180. m(target, anchor) {
  16181. insert(target, div, anchor);
  16182. if (if_block0) if_block0.m(div, null);
  16183. append(div, t);
  16184. if (if_block1) if_block1.m(div, null);
  16185. /*div_binding_1*/ ctx[284](div);
  16186. current = true;
  16187. if (!mounted) {
  16188. dispose = [
  16189. listen(window_1$1, "keydown", /*handleKeydown*/ ctx[131]),
  16190. listen(window_1$1, "keyup", /*handleKeyup*/ ctx[132]),
  16191. listen(window_1$1, "blur", /*handleWindowBlur*/ ctx[133]),
  16192. listen(window_1$1, "paste", /*handlePaste*/ ctx[136]),
  16193. listen(window_1$1, "resize", /*onwindowresize*/ ctx[266]),
  16194. listen(div, "ping", function () {
  16195. if (is_function(/*routePing*/ ctx[41])) /*routePing*/ ctx[41].apply(this, arguments);
  16196. }),
  16197. listen(div, "contextmenu", /*handleContextMenu*/ ctx[134]),
  16198. listen(div, "touchstart", /*handleTouchStart*/ ctx[127], { passive: false }),
  16199. listen(div, "touchmove", /*handleTouchMove*/ ctx[128]),
  16200. listen(div, "pointermove", /*handlePointerMove*/ ctx[129]),
  16201. listen(div, "transitionend", /*handleTransitionEnd*/ ctx[116]),
  16202. listen(div, "dropfiles", /*handleDropFiles*/ ctx[135]),
  16203. listen(div, "measure", /*measure_handler_4*/ ctx[285]),
  16204. action_destroyer(measurable.call(null, div, { observeViewRect: true })),
  16205. action_destroyer(focusvisible.call(null, div)),
  16206. action_destroyer(dropable.call(null, div))
  16207. ];
  16208. mounted = true;
  16209. }
  16210. },
  16211. p(new_ctx, dirty) {
  16212. ctx = new_ctx;
  16213. if (/*canRender*/ ctx[40]) {
  16214. if (if_block0) {
  16215. if_block0.p(ctx, dirty);
  16216. if (dirty[1] & /*canRender*/ 512) {
  16217. transition_in(if_block0, 1);
  16218. }
  16219. } else {
  16220. if_block0 = create_if_block_1$7(ctx);
  16221. if_block0.c();
  16222. transition_in(if_block0, 1);
  16223. if_block0.m(div, t);
  16224. }
  16225. } else if (if_block0) {
  16226. group_outros();
  16227. transition_out(if_block0, 1, 1, () => {
  16228. if_block0 = null;
  16229. });
  16230. check_outros();
  16231. }
  16232. if (/*$disabledTransition*/ ctx[55] > 0) {
  16233. if (if_block1) {
  16234. if_block1.p(ctx, dirty);
  16235. } else {
  16236. if_block1 = create_if_block$7(ctx);
  16237. if_block1.c();
  16238. if_block1.m(div, null);
  16239. }
  16240. } else if (if_block1) {
  16241. if_block1.d(1);
  16242. if_block1 = null;
  16243. }
  16244. if (!current || dirty[0] & /*id*/ 8) {
  16245. attr(div, "id", /*id*/ ctx[3]);
  16246. }
  16247. if (!current || dirty[1] & /*className*/ 4) {
  16248. attr(div, "class", /*className*/ ctx[33]);
  16249. }
  16250. if (!current || dirty[1] & /*envStr*/ 16) {
  16251. attr(div, "data-env", /*envStr*/ ctx[35]);
  16252. }
  16253. },
  16254. i(local) {
  16255. if (current) return;
  16256. transition_in(if_block0);
  16257. current = true;
  16258. },
  16259. o(local) {
  16260. transition_out(if_block0);
  16261. current = false;
  16262. },
  16263. d(detaching) {
  16264. if (detaching) detach(div);
  16265. if (if_block0) if_block0.d();
  16266. if (if_block1) if_block1.d();
  16267. /*div_binding_1*/ ctx[284](null);
  16268. mounted = false;
  16269. run_all(dispose);
  16270. }
  16271. };
  16272. }
  16273. const imageCropRectElasticity = 5;
  16274. // updating crop selection / the intended selection rect, combined with actual selection rect, used to render elasticity visualisation
  16275. const imageSelectionRectElasticity = 1;
  16276. const STAGE_OVERLAY_ID = "stage-overlay";
  16277. const maxOpacity = 0.85;
  16278. const scrollElasticity = 10;
  16279. const rangeInputElasticity = 5;
  16280. function instance$u($$self, $$props, $$invalidate) {
  16281. let isOverlayModeEnabled;
  16282. let showUtils;
  16283. let maxImageDataSize;
  16284. let preprocessShape;
  16285. let imageTargetSizeCurrent;
  16286. let overlayTop;
  16287. let overlayBottom;
  16288. let overlayLeft;
  16289. let overlayRight;
  16290. let gradientOverlays;
  16291. let canAnimate;
  16292. let acceptsAnimations;
  16293. let canUndo;
  16294. let canRedo;
  16295. let utilsFiltered;
  16296. let utilsAvailable;
  16297. let utilsDefined;
  16298. let utilsMerged;
  16299. let utilSelected;
  16300. let utilTools;
  16301. let utilsVisibleFraction;
  16302. let tabsConfig;
  16303. let tabs;
  16304. let panels;
  16305. let shouldRenderTabs;
  16306. let className;
  16307. let horizontalSpace;
  16308. let hasLimitedSpace;
  16309. let verticalSpace;
  16310. let isModal;
  16311. let isCenteredHorizontally;
  16312. let isCenteredVertically;
  16313. let isCentered;
  16314. let isNarrow;
  16315. let orientation;
  16316. let isLandscape;
  16317. let isCompact;
  16318. let hasSwipeNavigation;
  16319. let shouldRenderUtilTools;
  16320. let navigationHorizontalPreference;
  16321. let navigationVerticalPreference;
  16322. let rootElementComputedStyle;
  16323. let envStr;
  16324. let imageCanvasState;
  16325. let hasProps;
  16326. let missingFeatures;
  16327. let isSupportsError;
  16328. let isStartLoadingImageSource;
  16329. let isImageLoadError;
  16330. let isWaitingForImage;
  16331. let imageLoadProgress;
  16332. let isLoadingImageData;
  16333. let isCreatingImagePreview;
  16334. let isProcessingImage;
  16335. let imageLoadShowProgressIndicator;
  16336. let imageLoadStatusLabel;
  16337. let imageProcessStatusLabel;
  16338. let imageProcessProgress;
  16339. let imageProcessShowProgressIndicator;
  16340. let isImageProcessingError;
  16341. let isCustomStatus;
  16342. let isStatusActive;
  16343. let isStatusVisible;
  16344. let hasAside;
  16345. let statusIndent;
  16346. let statusTransform;
  16347. let toolbarItems;
  16348. let hasClientRect;
  16349. let canRender;
  16350. let hasImageRedaction;
  16351. let imageRedactionScalar;
  16352. let routePing;
  16353. let isReady;
  16354. let $images;
  16355. let $shapePreprocessor;
  16356. let $clientRect;
  16357. let $imageCropAspectRatio;
  16358. let $rootRect;
  16359. let $imageLoadState;
  16360. let $imageCropRect;
  16361. let $imageCropRectIntent;
  16362. let $isInteracting;
  16363. let $imageCropRectSnapshot;
  16364. let $previewShouldUpscale;
  16365. let $imageSelectionRect;
  16366. let $shouldAnimate;
  16367. let $imageSelectionRectIntent;
  16368. let $stageRect;
  16369. let $imageOutputSize;
  16370. let $stageScalar;
  16371. let $imageSize;
  16372. let $presentationScalar;
  16373. let $imageSelectionRectSnapshot;
  16374. let $overlayInset;
  16375. let $imageVisualBounds;
  16376. let $overlaySize;
  16377. let $overlayTopOpacity;
  16378. let $overlayBottomOpacity;
  16379. let $overlayLeftOpacity;
  16380. let $overlayRightOpacity;
  16381. let $imageOverlayMarkup;
  16382. let $imageFile;
  16383. let $imagePreview,
  16384. $$unsubscribe_imagePreview = noop,
  16385. $$subscribe_imagePreview = () => ($$unsubscribe_imagePreview(), $$unsubscribe_imagePreview = subscribe(imagePreview, $$value => $$invalidate(202, $imagePreview = $$value)), imagePreview);
  16386. let $imagePreviewSource;
  16387. let $prefersReducedMotion;
  16388. let $imageState;
  16389. let $tabRect;
  16390. let $history,
  16391. $$unsubscribe_history = noop,
  16392. $$subscribe_history = () => ($$unsubscribe_history(), $$unsubscribe_history = subscribe(history, $$value => $$invalidate(208, $history = $$value)), history);
  16393. let $imageProcessingPreparing;
  16394. let $env;
  16395. let $pointerAccuracy;
  16396. let $pointerHoverable;
  16397. let $imageTransforms;
  16398. let $imagePreviewModifiers;
  16399. let $imageProps;
  16400. let $activeImages;
  16401. let $imageSelectionRectPresentation;
  16402. let $imageVisualLoadComplete;
  16403. let $imageProcessState;
  16404. let $wasProcessingImage;
  16405. let $statusOpacity;
  16406. let $statusWidth;
  16407. let $asideWidth;
  16408. let $statusOffset;
  16409. let $pressedKeysStore;
  16410. let $imageRedaction;
  16411. let $imageScrambler;
  16412. let $imageBackgroundColor;
  16413. let $rootForegroundColor;
  16414. let $rootLineColor;
  16415. let $isInteractingFraction;
  16416. let $asideOffset;
  16417. let $asideOpacity;
  16418. let $toolRect;
  16419. let $utilRect;
  16420. let $pixelRatio;
  16421. let $rootBackgroundColor;
  16422. let $utilSelectedStore;
  16423. let $stagePadded;
  16424. let $interfaceImages;
  16425. let $imageAnnotation;
  16426. let $imageDecoration;
  16427. let $imageFrame;
  16428. let $imageOverlay;
  16429. let $disabledTransition;
  16430. component_subscribe($$self, prefersReducedMotion, $$value => $$invalidate(206, $prefersReducedMotion = $$value));
  16431. $$self.$$.on_destroy.push(() => $$unsubscribe_imagePreview());
  16432. $$self.$$.on_destroy.push(() => $$unsubscribe_history());
  16433. const eventProxy = pubsub();
  16434. const dispatch = createEventDispatcher();
  16435. //
  16436. // View Props
  16437. //
  16438. let { class: klass = undefined } = $$props;
  16439. let { layout: layoutMode = undefined } = $$props;
  16440. let { stores } = $$props;
  16441. let { locale = undefined } = $$props;
  16442. let { id = undefined } = $$props;
  16443. let { util = undefined } = $$props;
  16444. let { utils = undefined } = $$props; // which utils are active (list of ids), or is derived from plugins automatically
  16445. let { animations = "auto" } = $$props;
  16446. let { disabled = false } = $$props;
  16447. let { status = undefined } = $$props;
  16448. let { previewUpscale = false } = $$props;
  16449. let { elasticityMultiplier = 10 } = $$props;
  16450. let { willRevert = () => Promise.resolve(true) } = $$props;
  16451. let { willProcessImage = () => Promise.resolve(true) } = $$props;
  16452. let { willRenderCanvas = passthrough } = $$props;
  16453. let { willRenderToolbar = passthrough } = $$props;
  16454. let { willSetHistoryInitialState = passthrough } = $$props;
  16455. let { enableButtonExport = true } = $$props;
  16456. let { enableButtonRevert = true } = $$props;
  16457. let { enableNavigateHistory = true } = $$props;
  16458. let { enableToolbar = true } = $$props;
  16459. let { enableUtils = true } = $$props;
  16460. let { enableButtonClose = false } = $$props;
  16461. let { enableDropImage = false } = $$props;
  16462. let { enablePasteImage = false } = $$props;
  16463. let { previewImageDataMaxSize = undefined } = $$props;
  16464. let { layoutDirectionPreference = "auto" } = $$props;
  16465. let { layoutHorizontalUtilsPreference = "left" } = $$props;
  16466. let { layoutVerticalUtilsPreference = "bottom" } = $$props;
  16467. let { imagePreviewSrc = undefined } = $$props;
  16468. let { imageOrienter = { read: () => 1, apply: v => v } } = $$props;
  16469. let { pluginComponents = undefined } = $$props;
  16470. let { pluginOptions = {} } = $$props;
  16471. const sub = eventProxy.sub;
  16472. const pluginInterface = {};
  16473. let { root } = $$props;
  16474. let registeredPluginsComponents = [];
  16475. // editor disabled spring for animating in and out disabled state
  16476. const disabledTransition = spring();
  16477. component_subscribe($$self, disabledTransition, value => $$invalidate(55, $disabledTransition = value));
  16478. // this method is used to read image resources (preview image / shape images)
  16479. const glMaxTextureSize = getWebGLTextureSizeLimit() || 1024;
  16480. const maxTextureSize = sizeCreate(glMaxTextureSize, glMaxTextureSize);
  16481. const canvasMemoryLimit = getCanvasMemoryLimit();
  16482. let { imageSourceToImageData = src => isString(src)
  16483. ? // it's a url src
  16484. fetch(src).then(res => {
  16485. if (res.status !== 200) throw `${res.status} (${res.statusText})`;
  16486. return res.blob();
  16487. }).then(blob => blobToImageBitmap(blob, imageOrienter, canvasMemoryLimit)).then(imageData => imageDataContain(imageData, maxImageDataSize))
  16488. : isElement(src)
  16489. ? // assume src is a <canvas>
  16490. new Promise(resolve => resolve(canvasToImageData(src)))
  16491. : // assume src is a File or Blob
  16492. blobToImageBitmap(src, imageOrienter, canvasMemoryLimit).then(imageData => imageDataContain(imageData, maxImageDataSize)) } = $$props;
  16493. const imageProxy = createImageProxy();
  16494. const { file: imageFile, size: imageSize, loadState: imageLoadState, processState: imageProcessState, cropAspectRatio: imageCropAspectRatio, cropLimitToImage: imageCropLimitToImage, crop: imageCropRect, cropMinSize: imageCropMinSize, cropMaxSize: imageCropMaxSize, cropRange: imageCropRange, cropOrigin: imageCropRectOrigin, cropRectAspectRatio: imageCropRectAspectRatio, rotation: imageRotation, rotationRange: imageRotationRange, targetSize: imageOutputSize, flipX: imageFlipX, flipY: imageFlipY, backgroundColor: imageBackgroundColor, colorMatrix: imageColorMatrix, convolutionMatrix: imageConvolutionMatrix, gamma: imageGamma, vignette: imageVignette, noise: imageNoise, decoration: imageDecoration, annotation: imageAnnotation, redaction: imageRedaction, frame: imageFrame, state: imageState } = imageProxy.stores;
  16495. component_subscribe($$self, imageFile, value => $$invalidate(201, $imageFile = value));
  16496. component_subscribe($$self, imageSize, value => $$invalidate(186, $imageSize = value));
  16497. component_subscribe($$self, imageLoadState, value => $$invalidate(180, $imageLoadState = value));
  16498. component_subscribe($$self, imageProcessState, value => $$invalidate(245, $imageProcessState = value));
  16499. component_subscribe($$self, imageCropAspectRatio, value => $$invalidate(293, $imageCropAspectRatio = value));
  16500. component_subscribe($$self, imageCropRect, value => $$invalidate(181, $imageCropRect = value));
  16501. component_subscribe($$self, imageOutputSize, value => $$invalidate(185, $imageOutputSize = value));
  16502. component_subscribe($$self, imageBackgroundColor, value => $$invalidate(265, $imageBackgroundColor = value));
  16503. component_subscribe($$self, imageDecoration, value => $$invalidate(52, $imageDecoration = value));
  16504. component_subscribe($$self, imageAnnotation, value => $$invalidate(51, $imageAnnotation = value));
  16505. component_subscribe($$self, imageRedaction, value => $$invalidate(262, $imageRedaction = value));
  16506. component_subscribe($$self, imageFrame, value => $$invalidate(53, $imageFrame = value));
  16507. component_subscribe($$self, imageState, value => $$invalidate(302, $imageState = value));
  16508. const { images, shapePreprocessor, imageScrambler } = stores;
  16509. component_subscribe($$self, images, value => $$invalidate(177, $images = value));
  16510. component_subscribe($$self, shapePreprocessor, value => $$invalidate(178, $shapePreprocessor = value));
  16511. component_subscribe($$self, imageScrambler, value => $$invalidate(264, $imageScrambler = value));
  16512. // let the world know about state changes
  16513. imageState.subscribe(state => eventProxy.pub("update", state));
  16514. // this will hold the currently selected util
  16515. const utilSelectedStore = writable();
  16516. component_subscribe($$self, utilSelectedStore, value => $$invalidate(48, $utilSelectedStore = value));
  16517. //
  16518. // handles the view rect size, makes sure it is offset from the top
  16519. //
  16520. // root element reference used to read styles
  16521. const rootBackgroundColor = writable([0, 0, 0]);
  16522. component_subscribe($$self, rootBackgroundColor, value => $$invalidate(47, $rootBackgroundColor = value));
  16523. const rootForegroundColor = writable([1, 1, 1]);
  16524. component_subscribe($$self, rootForegroundColor, value => $$invalidate(304, $rootForegroundColor = value));
  16525. const rootLineColor = spring();
  16526. component_subscribe($$self, rootLineColor, value => $$invalidate(305, $rootLineColor = value));
  16527. // client rect is the editor rect excluding scroll offset
  16528. const clientRect = writable();
  16529. component_subscribe($$self, clientRect, value => $$invalidate(16, $clientRect = value));
  16530. // root rect is the editor rect including scroll offset
  16531. const rootRect = writable();
  16532. component_subscribe($$self, rootRect, value => $$invalidate(179, $rootRect = value));
  16533. // when in overlay mode force aspect ratio to aspect ratio of editor root
  16534. const syncRootAspectRatio = () => {
  16535. // get current aspect ratio and get next aspect ratio, compare, if different, reset
  16536. const currentAspectRatio = $imageCropAspectRatio;
  16537. const nextAspectRatio = rectAspectRatio($rootRect);
  16538. if (currentAspectRatio && currentAspectRatio === nextAspectRatio) return;
  16539. // set aspect ratio
  16540. imageCropAspectRatio.set(rectAspectRatio($rootRect));
  16541. // need to set history 0 point to this state
  16542. setInitialHistoryState();
  16543. };
  16544. const tabRect = writable(rectCreateEmpty());
  16545. component_subscribe($$self, tabRect, value => $$invalidate(29, $tabRect = value));
  16546. const toolRect = writable(rectCreateEmpty());
  16547. component_subscribe($$self, toolRect, value => $$invalidate(44, $toolRect = value));
  16548. const utilRect = writable(); // is undefined because we wait till util is set before defining stage rect
  16549. component_subscribe($$self, utilRect, value => $$invalidate(45, $utilRect = value));
  16550. //
  16551. // environment
  16552. //
  16553. const pointerAccuracy = mediaQueryStore("(pointer: fine)", matches => matches ? "pointer-fine" : "pointer-coarse");
  16554. component_subscribe($$self, pointerAccuracy, value => $$invalidate(230, $pointerAccuracy = value));
  16555. const pointerHoverable = mediaQueryStore("(hover: hover)", matches => matches ? "pointer-hover" : "pointer-no-hover");
  16556. component_subscribe($$self, pointerHoverable, value => $$invalidate(231, $pointerHoverable = value));
  16557. //
  16558. // app API
  16559. //
  16560. const isInteracting = writable(false);
  16561. component_subscribe($$self, isInteracting, value => $$invalidate(182, $isInteracting = value));
  16562. const isInteractingFraction = readable(undefined, set => {
  16563. const animator = spring(0);
  16564. const updater = value => {
  16565. animator.set(value ? 1 : 0);
  16566. };
  16567. const subs = [isInteracting.subscribe(updater), animator.subscribe(set)];
  16568. // destroy subs
  16569. return () => subs.forEach(unsub => unsub());
  16570. });
  16571. component_subscribe($$self, isInteractingFraction, value => $$invalidate(306, $isInteractingFraction = value));
  16572. const previewShouldUpscale = writable(previewUpscale);
  16573. component_subscribe($$self, previewShouldUpscale, value => $$invalidate(296, $previewShouldUpscale = value));
  16574. const imageCropRectSnapshot = writable();
  16575. component_subscribe($$self, imageCropRectSnapshot, value => $$invalidate(295, $imageCropRectSnapshot = value));
  16576. const imageCropRectIntent = writable(); // should always be set before setting `imageCropRect`
  16577. component_subscribe($$self, imageCropRectIntent, value => $$invalidate(294, $imageCropRectIntent = value));
  16578. const imageCropRectPresentation = readable(undefined, set => {
  16579. const animator = spring(undefined, { precision: 0.0001 });
  16580. const update = () => {
  16581. if (!$imageCropRect) return;
  16582. const instantUpdate = $imageCropRectIntent === undefined || $isInteracting;
  16583. const elasticRect = elastifyRects($imageCropRect, $imageCropRectIntent, imageCropRectElasticity * elasticityMultiplier);
  16584. animator.set(elasticRect, { hard: instantUpdate });
  16585. };
  16586. const subs = [
  16587. // need to update presentation rect when crop rect is updated
  16588. imageCropRect.subscribe(update),
  16589. // update parent store
  16590. animator.subscribe(set)
  16591. ];
  16592. return () => subs.forEach(unsub => unsub());
  16593. });
  16594. const imageSelectionRect = writable();
  16595. component_subscribe($$self, imageSelectionRect, value => $$invalidate(297, $imageSelectionRect = value));
  16596. const imageSelectionRectSnapshot = writable();
  16597. component_subscribe($$self, imageSelectionRectSnapshot, value => $$invalidate(301, $imageSelectionRectSnapshot = value));
  16598. const imageSelectionRectIntent = writable(undefined); // should always be set before setting `imageSelectionRect`
  16599. component_subscribe($$self, imageSelectionRectIntent, value => $$invalidate(298, $imageSelectionRectIntent = value));
  16600. let prevFramePadding = { left: 0, right: 0, top: 0, bottom: 0 };
  16601. const framePadding = derived([imageFrame, imageSelectionRect], ([$imageFrame, $imageSelectionRect], set) => {
  16602. if (!$imageSelectionRect) set(prevFramePadding);
  16603. // set frame padding
  16604. let newPadding = getStagePadding($imageSelectionRect, $imageFrame);
  16605. // exif if no value changes
  16606. if (fixPrecision(prevFramePadding.top, 4) === fixPrecision(newPadding.top, 4) && fixPrecision(prevFramePadding.bottom, 4) === fixPrecision(newPadding.bottom, 4) && fixPrecision(prevFramePadding.right, 4) === fixPrecision(newPadding.right, 4) && fixPrecision(prevFramePadding.left, 4) === fixPrecision(newPadding.left, 4)) return;
  16607. prevFramePadding = newPadding;
  16608. set(newPadding);
  16609. });
  16610. const framePadded = derived([framePadding], ([$framePadding], set) => {
  16611. set(Object.values($framePadding).some(value => value > 0));
  16612. });
  16613. let prevStagePadding = { left: 0, right: 0, top: 0, bottom: 0 };
  16614. const stagePadding = derived([utilSelectedStore, imageFrame, imageSelectionRect], ([$utilSelectedStore, $imageFrame, $imageSelectionRect], set) => {
  16615. if (!$imageSelectionRect) set(prevStagePadding);
  16616. // TODO: configure in plugin
  16617. let newPadding;
  16618. if ($utilSelectedStore === "frame") {
  16619. newPadding = getStagePadding($imageSelectionRect, $imageFrame);
  16620. } else {
  16621. newPadding = { left: 0, right: 0, top: 0, bottom: 0 };
  16622. }
  16623. // exif if no value changes
  16624. if (fixPrecision(prevStagePadding.top, 4) === fixPrecision(newPadding.top, 4) && fixPrecision(prevStagePadding.bottom, 4) === fixPrecision(newPadding.bottom, 4) && fixPrecision(prevStagePadding.right, 4) === fixPrecision(newPadding.right, 4) && fixPrecision(prevStagePadding.left, 4) === fixPrecision(newPadding.left, 4)) return;
  16625. prevStagePadding = newPadding;
  16626. set(newPadding);
  16627. });
  16628. const stagePadded = derived([stagePadding], ([$stagePadding], set) => {
  16629. set(Object.values($stagePadding).some(value => value > 0));
  16630. });
  16631. component_subscribe($$self, stagePadded, value => $$invalidate(49, $stagePadded = value));
  16632. const stageRect = derived([utilRect, tabRect, toolRect, stagePadding], ([$utilRect, $tabRect, $toolRect, $stagePadding], set) => {
  16633. if (!$utilRect) return set(undefined);
  16634. let utilOffsetY = 0;
  16635. // if only one util active, we don't have util tabs, so add additional offset
  16636. if (utilsFiltered.length === 1 && !isOverlayModeEnabled) {
  16637. utilOffsetY = $toolRect.y + $toolRect.height;
  16638. }
  16639. set(rectCreate($utilRect.x + $tabRect.x + $stagePadding.top, $utilRect.y + $tabRect.y + utilOffsetY + $stagePadding.top, $utilRect.width - ($stagePadding.left + $stagePadding.right), $utilRect.height - ($stagePadding.top + $stagePadding.bottom)));
  16640. });
  16641. component_subscribe($$self, stageRect, value => $$invalidate(184, $stageRect = value));
  16642. const stageScalar = derived([stageRect, imageCropRect], ([$stageRect, $imageCropRect], set) => {
  16643. const isManipulatingImageCropRect = !!($imageCropRectSnapshot || $imageCropRectIntent);
  16644. // update stage scalar, the crop output size relative to the stage, if image fits it's 1
  16645. if (!$stageRect || !$imageCropRect || isManipulatingImageCropRect) return;
  16646. // calculate scale factor needed to fit crop rect to stage
  16647. const scalar = Math.min($stageRect.width / $imageCropRect.width, $stageRect.height / $imageCropRect.height);
  16648. // always scaled down to fit stage, if is allowed to upscale, zoom to fit stage
  16649. const scale = $previewShouldUpscale ? scalar : Math.min(1, scalar);
  16650. set(scale);
  16651. });
  16652. component_subscribe($$self, stageScalar, value => $$invalidate(299, $stageScalar = value));
  16653. //
  16654. // Image selection
  16655. //
  16656. const getStagePadding = (presentationRect, imageFrame) => {
  16657. if (!imageFrame || !presentationRect) return { top: 0, right: 0, bottom: 0, left: 0 };
  16658. const shapes = shapesFromCompositShape(imageFrame, presentationRect, preprocessShape);
  16659. const bounds = shapesBounds(shapes, presentationRect);
  16660. return {
  16661. top: Math.abs(bounds.top),
  16662. right: Math.abs(bounds.right),
  16663. bottom: Math.abs(bounds.bottom),
  16664. left: Math.abs(bounds.left)
  16665. };
  16666. };
  16667. const imageSelectionRectPresentation = readable(undefined, set => {
  16668. const animator = spring(undefined, { precision: 0.0001 });
  16669. const updater = () => {
  16670. if (!$imageSelectionRect) return;
  16671. const instantUpdate = $isInteracting || !$shouldAnimate;
  16672. const elasticRect = elastifyRects($imageSelectionRect, $imageSelectionRectIntent, imageSelectionRectElasticity * elasticityMultiplier);
  16673. // prevent negative size (can happen because of elastics)
  16674. if (elasticRect.width < 0) {
  16675. elasticRect.width = 0;
  16676. elasticRect.x = $imageSelectionRect.x;
  16677. }
  16678. if (elasticRect.height < 0) {
  16679. elasticRect.height = 0;
  16680. elasticRect.y = $imageSelectionRect.y;
  16681. }
  16682. // translate elastic rect x,y by stage rect x,y
  16683. rectTranslate(elasticRect, $stageRect);
  16684. // adjust size if needed
  16685. // TODO: MAKE THIS CONTROLLABLE FROM PLUGIN
  16686. if ($imageCropRect) {
  16687. if (utilSelected === "resize") {
  16688. const visualSize = $imageOutputSize || $imageCropRect;
  16689. rectScale(elasticRect, visualSize.width / $imageSelectionRect.width || visualSize.height / $imageSelectionRect.height);
  16690. }
  16691. }
  16692. animator.set(elasticRect, { hard: instantUpdate });
  16693. };
  16694. const subs = [
  16695. // need to update selection rect when stage is resized
  16696. stageRect.subscribe(updater),
  16697. // listen for selection rect changes (as is assigned rect will always trigger, even if assigned same rect, this is needed to also update when intent changes)
  16698. imageSelectionRect.subscribe(updater),
  16699. // if output size changes need to update presentation
  16700. imageOutputSize.subscribe(updater),
  16701. // need to update if frame exceeds bounds
  16702. imageFrame.subscribe(updater),
  16703. // update parent store
  16704. animator.subscribe(set)
  16705. ];
  16706. // destroy subs
  16707. return () => subs.forEach(unsub => unsub());
  16708. });
  16709. component_subscribe($$self, imageSelectionRectPresentation, value => $$invalidate(37, $imageSelectionRectPresentation = value));
  16710. // when scaling the stage we need to recenter the image selection
  16711. let stageRectPrev;
  16712. const calculateImageSelectionRect = rect => {
  16713. // don't recalculate if no change
  16714. if (isOverlayModeEnabled && stageRectPrev && rectEqual(stageRectPrev, rect)) return;
  16715. // remember so we can compare later on if has changed
  16716. stageRectPrev = rect;
  16717. const imageCropRectFitsStage = $imageCropRect.width <= rect.width && $imageCropRect.height <= rect.height;
  16718. const centeredImageSelectionRect = // if we have a crop rect and it fits the stage, center it
  16719. imageCropRectFitsStage
  16720. ? // center the crop rectangle to the stage
  16721. rectCenterRect(rect, rectMultiply(rectClone($imageCropRect), $stageScalar || 1))
  16722. : // render a rectangle based on the fixed crop aspect ratio, or the aspect ratio of the current crop rectangle, or as a last resort the input image
  16723. rectContainRect(rect, rectAspectRatio($imageCropRect || $imageSize));
  16724. imageSelectionRect.set(centeredImageSelectionRect);
  16725. };
  16726. // this runs once so we use the correct scale for the initial image selection rect
  16727. let hasSetInitialStageScalar = false;
  16728. stageScalar.subscribe(scalar => {
  16729. // can't recalculate without these prosp
  16730. if (hasSetInitialStageScalar || scalar === undefined || !$imageCropRect) return;
  16731. calculateImageSelectionRect($stageRect);
  16732. hasSetInitialStageScalar = true;
  16733. });
  16734. // this recenters the crop when the window/stage is resized
  16735. stageRect.subscribe(rect => {
  16736. // can't recalculate without these prosp
  16737. if (!rect || $stageScalar === undefined || !$imageCropRect) return;
  16738. calculateImageSelectionRect(rect);
  16739. });
  16740. // if we've taken a snapshot of the selection, also take a snapshot of the crop rect and the presentationScalar
  16741. // - cropRect so we can adjust it based on the adjustments to the imageSelectionRect
  16742. // - presentationScalar so we can use the snapshot for the calculation of the cropRect scale relative to the original imageSelectionRect (if we use the live $presentationScalar small rounding errors of the scalar result in weird glitches)
  16743. let presentationScalarSnapshot;
  16744. imageSelectionRectSnapshot.subscribe(rect => {
  16745. if (!rect) {
  16746. presentationScalarSnapshot = undefined;
  16747. set_store_value(imageCropRectSnapshot, $imageCropRectSnapshot = undefined, $imageCropRectSnapshot);
  16748. return;
  16749. }
  16750. presentationScalarSnapshot = $presentationScalar;
  16751. const cropRectClone = rectClone($imageCropRect);
  16752. imageCropRectSnapshot.set(cropRectClone);
  16753. });
  16754. // if image selection rect is being manipulated, and imageSelectionRectSnapshot has been defined, we also need to update the crop rect
  16755. imageSelectionRect.subscribe(rect => {
  16756. // only sync crop rect with image selection rect when no longer manipulating
  16757. if (!rect || !$imageSelectionRectSnapshot) return;
  16758. const offset = rectSubtract(rectClone(rect), $imageSelectionRectSnapshot);
  16759. rectDivide(offset, presentationScalarSnapshot);
  16760. const crop = rectAdd(rectClone($imageCropRectSnapshot), offset);
  16761. imageCropRect.set(crop);
  16762. });
  16763. imageCropRect.subscribe(rect => {
  16764. // don't update image selection rect while we're intertacting with the view, this prevents feedback loop from cropRect model updates
  16765. if ($isInteracting || $imageSelectionRectSnapshot || $imageCropRectIntent) return;
  16766. // if no rect, we can't do anything
  16767. // if no selection rect yet, we wait for a selection rect to be loaded
  16768. if (!rect || !$imageSelectionRect) return;
  16769. // only if crop aspect ratio differs from image selection aspect ratio we update image selection rectangle
  16770. const imageSelectionRectAspectRatio = rectAspectRatio($imageSelectionRect);
  16771. const cropRectAspectRatio = rectAspectRatio(rect);
  16772. if (fixPrecision(imageSelectionRectAspectRatio, 6) === fixPrecision(cropRectAspectRatio, 6)) return;
  16773. // TEMP DUPLICATE OF STAGESCALAR DERIVED STORE TO FIX ZOOM OUT AFTER WHEEL ISSUE
  16774. // reproduce -> crop view => resize selection rect vertically, tap recenter, zoom out with scroll wheel
  16775. const scalar = Math.min($stageRect.width / $imageCropRect.width, $stageRect.height / $imageCropRect.height);
  16776. // const scale = $previewShouldUpscale ? scalar : Math.min(1, scalar);
  16777. const size = sizeCreate(rect.width * scalar, rect.height * scalar);
  16778. const tx = ($imageSelectionRect.width - size.width) * 0.5;
  16779. const ty = ($imageSelectionRect.height - size.height) * 0.5;
  16780. const selectionRect = rectCreate($imageSelectionRect.x + tx, $imageSelectionRect.y + ty, size.width, size.height);
  16781. imageSelectionRect.set(selectionRect);
  16782. });
  16783. const imageScalar = derived([stageScalar, imageCropRect, imageSelectionRect], ([$stageScalar, $imageCropRect, $imageSelectionRect], set) => {
  16784. // update the image scalar, the image zoom calculated by the image selection and the actual crop coordinates
  16785. if (!$stageScalar || !$imageCropRect || !$imageSelectionRect) return;
  16786. const selectionScaledWidth = $imageSelectionRect.width / $imageCropRect.width;
  16787. const selectionScaledHeight = $imageSelectionRect.height / $imageCropRect.height;
  16788. // need to correct for scale of stage
  16789. let scalar = Math.max(selectionScaledWidth, selectionScaledHeight) / $stageScalar;
  16790. set(scalar);
  16791. });
  16792. const presentationScalar = derived([stageScalar, imageScalar], ([$stageScalar, $imageScalar], set) => {
  16793. // can't scale presentation if no image scalar defined
  16794. if (!$imageScalar) return;
  16795. const scalar = $stageScalar * $imageScalar;
  16796. set(scalar);
  16797. });
  16798. component_subscribe($$self, presentationScalar, value => $$invalidate(300, $presentationScalar = value));
  16799. // const imagePresentationScale = writable(1);
  16800. // const imagePresentationPan = writable(vectorCreateEmpty());
  16801. //
  16802. // UI Elements
  16803. //
  16804. // image outline
  16805. const imageOutlineOpacity = spring(0.075, {
  16806. stiffness: 0.03,
  16807. damping: 0.4,
  16808. precision: 0.001
  16809. });
  16810. const imageVisualBounds = derived([imageSelectionRectPresentation, framePadding], ([$rect, $padding], set) => {
  16811. if (!$rect) return;
  16812. let { x, y, width, height } = $rect;
  16813. let { left, right, top, bottom } = $padding;
  16814. if (utilSelected === "resize") {
  16815. const visualSize = $imageOutputSize || $imageCropRect;
  16816. const scalar = visualSize.width / $imageSelectionRect.width || visualSize.height / $imageSelectionRect.height;
  16817. left *= scalar;
  16818. right *= scalar;
  16819. top *= scalar;
  16820. bottom *= scalar;
  16821. }
  16822. set({
  16823. x: x - left,
  16824. y: y - right,
  16825. width: width + left + right,
  16826. height: height + top + bottom
  16827. });
  16828. });
  16829. component_subscribe($$self, imageVisualBounds, value => $$invalidate(189, $imageVisualBounds = value));
  16830. const imageOutline = derived(
  16831. [
  16832. rootLineColor,
  16833. imageOutlineOpacity,
  16834. imageSelectionRectPresentation,
  16835. imageFrame,
  16836. framePadded,
  16837. framePadding
  16838. ],
  16839. ([
  16840. $rootLineColor,
  16841. $colorOpacity,
  16842. $rect,
  16843. $imageFrame,
  16844. $framePadded,
  16845. $framePadding
  16846. ], set) => {
  16847. if (!$rect || isOverlayModeEnabled) return set([]);
  16848. let { x, y, width, height } = $rect;
  16849. x += 0.5;
  16850. y += 0.5;
  16851. width -= 0.5;
  16852. height -= 0.5;
  16853. const shapes = [];
  16854. if ($framePadded) {
  16855. if ($colorOpacity > 0.1) {
  16856. // image outline
  16857. shapes.push({
  16858. x,
  16859. y,
  16860. width: width - 0.5,
  16861. height: height - 0.5,
  16862. strokeWidth: 1,
  16863. strokeColor: $rootLineColor,
  16864. opacity: $colorOpacity
  16865. });
  16866. }
  16867. let { left, right, top, bottom } = $framePadding;
  16868. if (utilSelected === "resize") {
  16869. const visualSize = $imageOutputSize || $imageCropRect;
  16870. const scalar = visualSize.width / $imageSelectionRect.width || visualSize.height / $imageSelectionRect.height;
  16871. left *= scalar;
  16872. right *= scalar;
  16873. top *= scalar;
  16874. bottom *= scalar;
  16875. }
  16876. set([
  16877. ...shapes,
  16878. // frame outline
  16879. {
  16880. x: x - left,
  16881. y: y - right,
  16882. width: width + left + right,
  16883. height: height + top + bottom,
  16884. strokeWidth: 1,
  16885. strokeColor: $rootLineColor,
  16886. opacity: 0.05
  16887. }
  16888. ]);
  16889. return;
  16890. }
  16891. // draw shadow behind frame if is dark outline on dark frame or bright outline on bright frame
  16892. const isDarkLine = isDarkColor($rootLineColor);
  16893. const isDarkFrame = $imageFrame && $imageFrame.frameColor && isDarkColor($imageFrame.frameColor);
  16894. if (isDarkLine && isDarkFrame || !isDarkLine && !isDarkLine) {
  16895. const shadeColor = isDarkLine ? [1, 1, 1, 0.3] : [0, 0, 0, 0.075];
  16896. shapes.push({
  16897. x,
  16898. y,
  16899. width,
  16900. height,
  16901. strokeWidth: 3.5,
  16902. strokeColor: shadeColor,
  16903. opacity: $colorOpacity
  16904. });
  16905. }
  16906. set([
  16907. ...shapes,
  16908. // outline
  16909. {
  16910. x,
  16911. y,
  16912. width,
  16913. height,
  16914. strokeWidth: 1,
  16915. strokeColor: $rootLineColor,
  16916. opacity: $colorOpacity
  16917. }
  16918. ]);
  16919. }
  16920. );
  16921. // custom markup rendered on top of image
  16922. const imageOverlayMarkup = writable([]);
  16923. component_subscribe($$self, imageOverlayMarkup, value => $$invalidate(200, $imageOverlayMarkup = value));
  16924. // the resulting overlay markup
  16925. const imageOverlay = derived([imageOutline, imageOverlayMarkup], ([$imageOutline, $imageOverlayMarkup], set) => {
  16926. set([...$imageOutline, ...$imageOverlayMarkup]);
  16927. });
  16928. component_subscribe($$self, imageOverlay, value => $$invalidate(54, $imageOverlay = value));
  16929. //
  16930. // Stage overlay
  16931. //
  16932. // create canvas gradient for use as menu backdrop
  16933. const getOverlayGradient = (width, height, color) => {
  16934. const ctx = h("canvas", {
  16935. width: Math.max(1, width),
  16936. height: Math.max(1, height)
  16937. }).getContext("2d");
  16938. const gradient = ctx.createLinearGradient(0, 0, width, height);
  16939. [
  16940. [0, 0],
  16941. [0.013, 0.081],
  16942. [0.049, 0.155],
  16943. [0.104, 0.225],
  16944. [0.175, 0.29],
  16945. [0.259, 0.353],
  16946. [0.352, 0.412],
  16947. [0.45, 0.471],
  16948. [0.55, 0.529],
  16949. [0.648, 0.588],
  16950. [0.741, 0.647],
  16951. [0.825, 0.71],
  16952. [0.896, 0.775],
  16953. [0.951, 0.845],
  16954. [0.987, 0.919],
  16955. [1, 1]
  16956. ].forEach(([o, s]) => gradient.addColorStop(s, `rgba(${color[0] * 255}, ${color[1] * 255}, ${color[2] * 255}, ${o})`));
  16957. ctx.fillStyle = gradient;
  16958. ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  16959. return ctx.canvas;
  16960. };
  16961. const calculateImageTargetSize = (outputSize, cropRect) => {
  16962. let { width, height } = outputSize;
  16963. const aspectRatio = rectAspectRatio(cropRect);
  16964. if (width && height) return outputSize;
  16965. if (width && !height) {
  16966. height = width / aspectRatio;
  16967. }
  16968. if (height && !width) {
  16969. width = height * aspectRatio;
  16970. }
  16971. if (!width && !height) {
  16972. width = cropRect.width;
  16973. height = cropRect.height;
  16974. }
  16975. return sizeApply(sizeCreate(width, height), Math.round);
  16976. };
  16977. const overlayInset = spring(40);
  16978. component_subscribe($$self, overlayInset, value => $$invalidate(188, $overlayInset = value));
  16979. const overlaySize = spring(70);
  16980. component_subscribe($$self, overlaySize, value => $$invalidate(191, $overlaySize = value));
  16981. const overlayLeftOpacity = spring(0);
  16982. component_subscribe($$self, overlayLeftOpacity, value => $$invalidate(196, $overlayLeftOpacity = value));
  16983. const overlayRightOpacity = spring(0);
  16984. component_subscribe($$self, overlayRightOpacity, value => $$invalidate(198, $overlayRightOpacity = value));
  16985. const overlayTopOpacity = spring(0);
  16986. component_subscribe($$self, overlayTopOpacity, value => $$invalidate(192, $overlayTopOpacity = value));
  16987. const overlayBottomOpacity = spring(0);
  16988. component_subscribe($$self, overlayBottomOpacity, value => $$invalidate(194, $overlayBottomOpacity = value));
  16989. // make sure canvas only redraws if background color changes
  16990. let gradientOverlayHorizontal;
  16991. let gradientOverlayVertical;
  16992. rootBackgroundColor.subscribe(color => {
  16993. if (!color) return;
  16994. $$invalidate(169, gradientOverlayHorizontal = getOverlayGradient(16, 0, color));
  16995. $$invalidate(169, gradientOverlayHorizontal.dataset.retain = 1, gradientOverlayHorizontal);
  16996. $$invalidate(170, gradientOverlayVertical = getOverlayGradient(0, 16, color));
  16997. $$invalidate(170, gradientOverlayVertical.dataset.retain = 1, gradientOverlayVertical);
  16998. });
  16999. //
  17000. // Loading the preview
  17001. //
  17002. const imageVisualLoadComplete = writable(false);
  17003. component_subscribe($$self, imageVisualLoadComplete, value => $$invalidate(242, $imageVisualLoadComplete = value));
  17004. const imagePreviewSource = writable();
  17005. component_subscribe($$self, imagePreviewSource, value => $$invalidate(203, $imagePreviewSource = value));
  17006. const createImagePreviewLoader = (src, token) => new Promise((resolve, reject) => {
  17007. // try not to show preview loader if updating active images array
  17008. const minPreviewLoaderDuration = activeImages.length ? 0 : 250;
  17009. let cancelled = false;
  17010. let timer;
  17011. token.cancel = () => cancelled = true;
  17012. const now = Date.now();
  17013. imageSourceToImageData(src).then(imageData => {
  17014. const dist = Date.now() - now;
  17015. clearTimeout(timer);
  17016. timer = setTimeout(
  17017. () => {
  17018. if (cancelled) return;
  17019. resolve(imageData);
  17020. },
  17021. Math.max(0, minPreviewLoaderDuration - dist)
  17022. );
  17023. }).catch(reject);
  17024. });
  17025. let imagePreviewLoaderCancelToken;
  17026. const imagePreview = derived([imageVisualLoadComplete, imagePreviewSource], ([$imageVisualLoadComplete, $imagePreviewSource], set) => {
  17027. // no data, reset preview data
  17028. if (!$imageVisualLoadComplete || !$imagePreviewSource) return set(undefined);
  17029. // cancel existing loader
  17030. if (imagePreviewLoaderCancelToken) {
  17031. imagePreviewLoaderCancelToken.cancel();
  17032. $$invalidate(171, imagePreviewLoaderCancelToken = undefined);
  17033. }
  17034. // if image preview source is a canvas we can update immediately
  17035. if (isCanvas($imagePreviewSource)) {
  17036. // update image preview to canvas
  17037. return set(canvasClone($imagePreviewSource));
  17038. }
  17039. // load preview
  17040. $$invalidate(171, imagePreviewLoaderCancelToken = { cancel: noop$1 });
  17041. createImagePreviewLoader($imagePreviewSource, imagePreviewLoaderCancelToken).then(set).catch(err => {
  17042. // update load state
  17043. set_store_value(imageLoadState, $imageLoadState.error = err, $imageLoadState);
  17044. // log to console for debuggin purposes
  17045. }).finally(() => {
  17046. // no longer loading
  17047. $$invalidate(171, imagePreviewLoaderCancelToken = undefined);
  17048. });
  17049. });
  17050. $$subscribe_imagePreview();
  17051. let { imagePreviewCurrent = undefined } = $$props;
  17052. //
  17053. // Calculates the image transforms and effects necessary for the preview
  17054. //
  17055. const imagePreviewModifiers = writable({});
  17056. component_subscribe($$self, imagePreviewModifiers, value => $$invalidate(233, $imagePreviewModifiers = value));
  17057. const interfaceImages = writable([]);
  17058. component_subscribe($$self, interfaceImages, value => $$invalidate(50, $interfaceImages = value));
  17059. // reset image UI previews when new file is loaded
  17060. const resetPreviews = () => interfaceImages.set([]);
  17061. const imageTransforms = derived(
  17062. [
  17063. stageRect,
  17064. rootRect,
  17065. imageSize,
  17066. imageCropRectPresentation,
  17067. imageSelectionRect,
  17068. presentationScalar,
  17069. imageRotation,
  17070. imageFlipX,
  17071. imageFlipY,
  17072. imageOutputSize
  17073. ],
  17074. ([
  17075. $stageRect,
  17076. $rootRect,
  17077. $imageSize,
  17078. $imageCropRectPresentation,
  17079. $imageSelectionRect,
  17080. $presentationScalar,
  17081. $imageRotation,
  17082. $imageFlipX,
  17083. $imageFlipY,
  17084. $imageOutputSize
  17085. ], set) => {
  17086. if (!$stageRect) return;
  17087. // TODO: MAKE THIS CONTROLLABLE FROM PLUGIN
  17088. if (utilSelected === "resize") {
  17089. const visualSize = $imageOutputSize || $imageCropRectPresentation;
  17090. $presentationScalar = visualSize.width / $imageCropRectPresentation.width || visualSize.height / $imageCropRectPresentation.height;
  17091. }
  17092. set(calculateImageTransforms($stageRect, $rootRect, $imageSize, $imageCropRectPresentation, $imageSelectionRect, $presentationScalar, 0, 0, $imageRotation, $imageFlipX, $imageFlipY));
  17093. }
  17094. );
  17095. component_subscribe($$self, imageTransforms, value => $$invalidate(232, $imageTransforms = value));
  17096. const imageEffects = derived(
  17097. [
  17098. imageColorMatrix,
  17099. imageConvolutionMatrix,
  17100. imageGamma,
  17101. imageVignette,
  17102. imageNoise
  17103. ],
  17104. ([$colorMatrix, $convolutionMatrix, $gamma, $vignette, $noise], set) => {
  17105. const colorMatrices = $colorMatrix && Object.keys($colorMatrix).map(name => $colorMatrix[name]).filter(Boolean);
  17106. const effects = {
  17107. gamma: $gamma || undefined,
  17108. vignette: $vignette || undefined,
  17109. noise: $noise || undefined,
  17110. convolutionMatrix: $convolutionMatrix || undefined,
  17111. colorMatrix: colorMatrices && colorMatrices.length && getColorMatrixFromColorMatrices(colorMatrices)
  17112. };
  17113. set(effects);
  17114. }
  17115. );
  17116. //
  17117. // current environment variables
  17118. //
  17119. let windowWidth;
  17120. let windowHeight;
  17121. const shouldPreventSwipe = canPreventNavSwipe();
  17122. const env = writable({});
  17123. component_subscribe($$self, env, value => $$invalidate(229, $env = value));
  17124. const initialPixelRatio = getDevicePixelRatio();
  17125. const pixelRatio = readable(initialPixelRatio, set => {
  17126. const handleResolutionChange = () => set(getDevicePixelRatio());
  17127. const resolutionObserver = matchMedia(`(resolution: ${initialPixelRatio}dppx)`);
  17128. resolutionObserver.addListener(handleResolutionChange);
  17129. return () => resolutionObserver.removeListener(handleResolutionChange);
  17130. });
  17131. component_subscribe($$self, pixelRatio, value => $$invalidate(46, $pixelRatio = value));
  17132. //
  17133. // Animations based on prefers-reduced-motion, automatically checks if user prefers reduced animations
  17134. //
  17135. const shouldAnimate = writable();
  17136. component_subscribe($$self, shouldAnimate, value => $$invalidate(18, $shouldAnimate = value));
  17137. const history = historyCreate(
  17138. () => {
  17139. // $imageState is always a clone of the current state
  17140. return $imageState;
  17141. },
  17142. state => {
  17143. // set new state from history, $imageState will store a clone of the received state
  17144. set_store_value(imageState, $imageState = state, $imageState);
  17145. // trigger recenter of image selection rect
  17146. tabRect.set($tabRect);
  17147. }
  17148. );
  17149. $$subscribe_history();
  17150. const setInitialHistoryState = () => {
  17151. // set history state
  17152. const baseRect = { x: 0, y: 0, ...$imageSize };
  17153. const baseCropRect = rectApply(rectContainRect(baseRect, $imageState.cropAspectRatio), v => Math.round(v));
  17154. const baseEditorState = willSetHistoryInitialState(
  17155. {
  17156. // the base state is the image state but the `rotation` and `crop` are reset
  17157. ...$imageState,
  17158. // should be read from imageInitialProps?
  17159. rotation: 0,
  17160. crop: baseCropRect
  17161. },
  17162. $imageState
  17163. );
  17164. // this will be the base state
  17165. const editorInitialHistoryState = [baseEditorState];
  17166. // only add additional entry if base state and current state are different
  17167. if (JSON.stringify(baseEditorState) !== JSON.stringify($imageState)) {
  17168. editorInitialHistoryState.push({ ...$imageState });
  17169. }
  17170. // loading done, set this as base state
  17171. history.set(editorInitialHistoryState);
  17172. };
  17173. imageLoadState.subscribe(state => {
  17174. // not ready yet
  17175. if (!state || !state.complete) return;
  17176. // set initial state after image load has completed
  17177. setInitialHistoryState();
  17178. });
  17179. const revert = () => willRevert().then(shouldReset => shouldReset && history.revert());
  17180. //
  17181. // Visual processing of the image
  17182. //
  17183. const imageProcessingPreparing = writable(false);
  17184. component_subscribe($$self, imageProcessingPreparing, value => $$invalidate(210, $imageProcessingPreparing = value));
  17185. const handleExport = () => {
  17186. // this will trigger status overlay fade in
  17187. set_store_value(imageProcessingPreparing, $imageProcessingPreparing = true, $imageProcessingPreparing);
  17188. willProcessImage().then(shouldProcess => {
  17189. // nope, restore hide processing overlay and back to editing
  17190. if (!shouldProcess) {
  17191. set_store_value(imageProcessingPreparing, $imageProcessingPreparing = false, $imageProcessingPreparing);
  17192. return;
  17193. }
  17194. // wait for status to be done fading in, then requests image writing
  17195. let unsub;
  17196. unsub = statusOpacity.subscribe(value => {
  17197. if (value !== 1) return;
  17198. // stop listening for
  17199. unsub && unsub();
  17200. // request write image
  17201. dispatch("processImage");
  17202. });
  17203. });
  17204. };
  17205. imageProcessState.subscribe(state => {
  17206. if (!state) return;
  17207. set_store_value(imageProcessingPreparing, $imageProcessingPreparing = true, $imageProcessingPreparing);
  17208. const { complete, abort } = state;
  17209. if (complete || abort) set_store_value(imageProcessingPreparing, $imageProcessingPreparing = false, $imageProcessingPreparing);
  17210. });
  17211. //
  17212. // Configure the available views
  17213. //
  17214. const utilStores = {
  17215. // model stores
  17216. ...stores,
  17217. // image
  17218. imageFile,
  17219. imageSize,
  17220. imageBackgroundColor,
  17221. imageCropAspectRatio,
  17222. imageCropMinSize,
  17223. imageCropMaxSize,
  17224. imageCropLimitToImage,
  17225. imageCropRect,
  17226. imageCropRectOrigin,
  17227. imageCropRectSnapshot,
  17228. imageCropRectAspectRatio,
  17229. imageCropRange,
  17230. imageRotation,
  17231. imageRotationRange,
  17232. imageFlipX,
  17233. imageFlipY,
  17234. imageOutputSize,
  17235. // effects
  17236. imageColorMatrix,
  17237. imageConvolutionMatrix,
  17238. imageGamma,
  17239. imageVignette,
  17240. imageNoise,
  17241. // markup
  17242. imageDecoration,
  17243. imageAnnotation,
  17244. imageRedaction,
  17245. imageFrame,
  17246. // image preview for utils that need access to pixel data
  17247. imagePreview,
  17248. // image preview source so utils can update preview
  17249. imagePreviewSource,
  17250. // top left position of image preview
  17251. imageTransforms,
  17252. // allows utils to control how the preview is presented (for example more opacity for mask)
  17253. imagePreviewModifiers,
  17254. // history state and update
  17255. history,
  17256. // static env info
  17257. animation: shouldAnimate,
  17258. pixelRatio,
  17259. elasticityMultiplier,
  17260. scrollElasticity,
  17261. rangeInputElasticity,
  17262. // dynamic env info
  17263. pointerAccuracy,
  17264. pointerHoverable,
  17265. env,
  17266. rootRect,
  17267. stageRect,
  17268. stageScalar,
  17269. framePadded,
  17270. utilRect,
  17271. presentationScalar,
  17272. rootBackgroundColor,
  17273. rootForegroundColor,
  17274. rootLineColor,
  17275. imageOutlineOpacity,
  17276. // interaction
  17277. // imagePresentationPan,
  17278. // imagePresentationScale,
  17279. // (write) add guides to ui (for example is used by markup util to add lines for shape manipulator)
  17280. imageOverlayMarkup,
  17281. // (write) interface images to render
  17282. interfaceImages,
  17283. // (write) set to true to disable animations
  17284. isInteracting,
  17285. // (read) goes from 0 to 1 while interacting
  17286. isInteractingFraction,
  17287. // (write) the current intended crop rect
  17288. imageCropRectIntent,
  17289. // (read) the current presented crop rect
  17290. imageCropRectPresentation,
  17291. // (write) the current limited size of the image selection rect
  17292. imageSelectionRect,
  17293. // (write) the inteded rectangle by the user
  17294. imageSelectionRectIntent,
  17295. // (read) the current presentation of the image selection rect, includes elasticity etc.
  17296. imageSelectionRectPresentation,
  17297. // (read) a snapshot of the image selection rectangle, use to store the rectangle before modification so alterations to the rectangle can be applied to the snapshot
  17298. imageSelectionRectSnapshot,
  17299. // scalar of image in view
  17300. imageScalar
  17301. };
  17302. // don't expose image store
  17303. delete utilStores.image;
  17304. const utilsUniqueId = `util-${getUniqueId()}`;
  17305. let utilsVisible = [];
  17306. // env
  17307. let iOS = isIOS();
  17308. const getOrientation = (rect, layoutPreference) => {
  17309. if (!$rootRect) return "landscape";
  17310. if (layoutPreference === "auto") return rect.width > rect.height ? "landscape" : "portrait";
  17311. if (layoutPreference === "horizontal") return rect.width < 500 ? "portrait" : "landscape";
  17312. if (layoutPreference === "vertical") return rect.height < 400 ? "landscape" : "portrait";
  17313. };
  17314. const getColorPropertyValue = name => {
  17315. const colorString = rootElementComputedStyle.getPropertyValue(name);
  17316. return colorStringToColorArray(colorString);
  17317. };
  17318. const syncColor = (property, store) => {
  17319. const colorArray = getColorPropertyValue(property);
  17320. // hide transparent color
  17321. if (!colorArray || colorArray[3] === 0) return;
  17322. // limit to opaque colors
  17323. colorArray.length = 3;
  17324. // update store
  17325. store.set(colorArray);
  17326. };
  17327. const syncColors = () => {
  17328. syncColor("color", rootForegroundColor);
  17329. syncColor("background-color", rootBackgroundColor);
  17330. syncColor("outline-color", rootLineColor);
  17331. };
  17332. const handleTransitionEnd = ({ target, propertyName }) => {
  17333. if (target !== root || !(/background|outline/).test(propertyName)) return;
  17334. syncColors();
  17335. };
  17336. const imageProps = derived([imageTransforms, imageEffects, imageBackgroundColor], ([$imageTransforms, $imageEffects, backgroundColor]) => {
  17337. return $imageTransforms && {
  17338. ...$imageTransforms,
  17339. ...$imageEffects,
  17340. backgroundColor
  17341. };
  17342. });
  17343. component_subscribe($$self, imageProps, value => $$invalidate(235, $imageProps = value));
  17344. const activeImages = storeList();
  17345. component_subscribe($$self, activeImages, value => $$invalidate(22, $activeImages = value));
  17346. const addImagePreview = () => {
  17347. // if is first image scale up slightly on entrance
  17348. const imageIntro = activeImages.length ? undefined : { resize: 1.05 };
  17349. // create the new image
  17350. const image = createImage($imagePreview, $imageSize, imageIntro);
  17351. // new image on top
  17352. activeImages.unshift(image);
  17353. // update images in activeImages array
  17354. updateImagePreviews($imageProps);
  17355. };
  17356. const updateImagePreviews = currentImageProps => {
  17357. activeImages.forEach((image, index) => {
  17358. const opacity = index === 0 ? 1 : 0;
  17359. const resize = 1;
  17360. image.set({ ...currentImageProps, opacity, resize }, $shouldAnimate);
  17361. });
  17362. };
  17363. // if image preview changes, push it on the stack
  17364. let lastImagePreview;
  17365. // test if some shapes have left/top/bottom/right offsets, if so, convert to crop space
  17366. // updates original shape (which at this point is a flattened shape (clone))
  17367. const positionDecorationShape = (shape, canvasState) => shapeComputeDisplay(shape, {
  17368. x: $imageSelectionRectPresentation.x / canvasState.scale,
  17369. y: $imageSelectionRectPresentation.y / canvasState.scale,
  17370. width: $imageSelectionRectPresentation.width / canvasState.scale,
  17371. height: $imageSelectionRectPresentation.height / canvasState.scale
  17372. });
  17373. // decoration is drawn relative to view space, so we need to translate relative to crop presentation rect
  17374. const transformDecorationShape = (shape, canvasState) => {
  17375. shapeComputeTransform(shape, $imageSelectionRectPresentation, canvasState.scale, canvasState.size);
  17376. return shape;
  17377. };
  17378. const flattenShapes = shapes => {
  17379. const flattenedShapes = [];
  17380. shapes.forEach(shape => flattenedShapes.push(flattenShape(shape)));
  17381. return flattenedShapes.filter(Boolean);
  17382. };
  17383. const flattenShape = shape => {
  17384. // at this point shape is a copy of the original shape
  17385. if (shapeIsLine(shape)) {
  17386. shape.points = [vectorCreate(shape.x1, shape.y1), vectorCreate(shape.x2, shape.y2)];
  17387. } else if (shapeIsTriangle(shape)) {
  17388. shape.points = [
  17389. vectorCreate(shape.x1, shape.y1),
  17390. vectorCreate(shape.x2, shape.y2),
  17391. vectorCreate(shape.x3, shape.y3)
  17392. ];
  17393. } else // is empty text
  17394. if (shapeIsTextEmpty(shape)) {
  17395. // make sure shape is still visible
  17396. if (shapeIsTextLine(shape)) {
  17397. shape.width = 5;
  17398. shape.height = isFunction(shape.lineHeight)
  17399. ? shape.lineHeight(shape.fontSize)
  17400. : shape.lineHeight;
  17401. }
  17402. // set to empty text style
  17403. shape.strokeWidth = 1;
  17404. shape.strokeColor = [1, 1, 1, 0.5];
  17405. shape.backgroundColor = [0, 0, 0, 0.1];
  17406. } else if (shapeIsText(shape)) {
  17407. shape.fontFamily = shape.fontFamily || "sans-serif";
  17408. shape.fontSize = shape.fontSize || 16;
  17409. }
  17410. return shape;
  17411. };
  17412. const statusOpacity = tweened(undefined, { duration: 500 });
  17413. component_subscribe($$self, statusOpacity, value => $$invalidate(24, $statusOpacity = value));
  17414. let loadTimer;
  17415. // this adds a little delay to the status fade out after an image was processed
  17416. // needed because when the modal fades out this would otherwise create a weird flash (modal fade out, but status fade out as well showing interface)
  17417. const wasProcessingImage = writable(false);
  17418. component_subscribe($$self, wasProcessingImage, value => $$invalidate(254, $wasProcessingImage = value));
  17419. let statusState;
  17420. const asideOffset = spring(undefined, {
  17421. stiffness: 0.1,
  17422. damping: 0.7,
  17423. precision: 0.25
  17424. });
  17425. component_subscribe($$self, asideOffset, value => $$invalidate(42, $asideOffset = value));
  17426. const asideOpacity = spring(0, { stiffness: 0.1, precision: 0.05 });
  17427. component_subscribe($$self, asideOpacity, value => $$invalidate(43, $asideOpacity = value));
  17428. const asideWidth = spring(0, {
  17429. stiffness: 0.02,
  17430. damping: 0.5,
  17431. precision: 0.25
  17432. });
  17433. component_subscribe($$self, asideWidth, value => $$invalidate(258, $asideWidth = value));
  17434. const statusWidth = spring(undefined, {
  17435. stiffness: 0.02,
  17436. damping: 0.5,
  17437. precision: 0.25
  17438. });
  17439. component_subscribe($$self, statusWidth, value => $$invalidate(256, $statusWidth = value));
  17440. const statusOffset = spring(undefined, {
  17441. stiffness: 0.02,
  17442. damping: 0.5,
  17443. precision: 0.25
  17444. });
  17445. component_subscribe($$self, statusOffset, value => $$invalidate(259, $statusOffset = value));
  17446. let asideWidthUpdateTimer;
  17447. const offsetAside = e => {
  17448. // if error occured, snap in possition
  17449. const hard = !!(statusState && statusState.closeButton);
  17450. // where to render the progress indicator or close button
  17451. statusWidth.set(e.detail.width, { hard });
  17452. // offsets text so it's better centered to the viewport
  17453. statusOffset.set(Math.round(-e.detail.width * 0.5), { hard });
  17454. };
  17455. const handleCloseImageLoadError = () => {
  17456. dispatch("abortLoadImage");
  17457. };
  17458. const handleCloseImageProcessError = () => {
  17459. dispatch("abortProcessImage");
  17460. set_store_value(imageProcessingPreparing, $imageProcessingPreparing = false, $imageProcessingPreparing);
  17461. };
  17462. // helper to block iOS events
  17463. const preventDefault = e => e.preventDefault();
  17464. // prevents swipe to navigate back on iOS >= 13.4+
  17465. const handleTouchStart = shouldPreventSwipe
  17466. ? e => {
  17467. // get touch or event itself (fixes issue with chrome dev tools)
  17468. const event = e.touches ? e.touches[0] : e;
  17469. // if is not an attempt to swipe back or forward
  17470. if (event.pageX > 10 && event.pageX < windowWidth - 10) return;
  17471. // stop the navigation attempt
  17472. preventDefault(e);
  17473. }
  17474. : noop$1;
  17475. // these are again needed since iOS 15 (was needed for 12 and lower, but wasn't needed for 13, 14)
  17476. const handleTouchMove = isIOS() ? preventDefault : noop$1;
  17477. const handlePointerMove = isIOS() ? preventDefault : noop$1;
  17478. // context for children to know if a key is down
  17479. const pressedKeysStore = writable([]);
  17480. component_subscribe($$self, pressedKeysStore, value => $$invalidate(303, $pressedKeysStore = value));
  17481. setContext("keysPressed", pressedKeysStore);
  17482. const handleKeydown = e => {
  17483. const { keyCode, metaKey, ctrlKey, shiftKey } = e;
  17484. // prevent tabbing through fields if editor is disabled
  17485. if (keyCode === 9 && disabled) {
  17486. e.preventDefault();
  17487. return;
  17488. }
  17489. // undo/redo
  17490. if (keyCode === 90 && (metaKey || ctrlKey)) {
  17491. if (shiftKey && metaKey) {
  17492. // redo on macos
  17493. history.redo();
  17494. } else {
  17495. // undo
  17496. history.undo();
  17497. }
  17498. return;
  17499. } else if (keyCode === 89 && ctrlKey) {
  17500. // redo on windows
  17501. history.redo();
  17502. return;
  17503. }
  17504. // ignore IME popup keycode, fixes keycode 229 sticking around, as it's not triggered in keyup "If an Input Method Editor is processing key input and the event is keydown, return 229."
  17505. // https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html
  17506. if (keyCode === 229) return;
  17507. // add to set
  17508. const keySet = new Set([...$pressedKeysStore, keyCode]);
  17509. pressedKeysStore.set(Array.from(keySet));
  17510. };
  17511. const handleKeyup = ({ keyCode }) => {
  17512. pressedKeysStore.set($pressedKeysStore.filter(pressedKey => pressedKey !== keyCode));
  17513. };
  17514. // so no keys get stuck when user cmd-tabs out of the window, or when dev-tools open by key-press
  17515. const handleWindowBlur = () => {
  17516. pressedKeysStore.set([]);
  17517. };
  17518. // block context menu on everything but text input fields
  17519. const handleContextMenu = e => {
  17520. if (isTextField(e.target)) return;
  17521. e.preventDefault();
  17522. };
  17523. // handle files being dropped on the editor
  17524. const handleUserFile = file => {
  17525. // no file received, isn't an image file, is not a URL
  17526. if (// no file received
  17527. !file || // if it's a file object it should be a bitmap
  17528. isBinary(file) && !isBitmap(file) || // if it's not a file object it should be a URL
  17529. !isBinary(file) && !(/^http/).test(file)) return;
  17530. // request load image
  17531. dispatch("loadImage", file);
  17532. };
  17533. const handleDropFiles = e => {
  17534. // not allowed to drop
  17535. if (!enableDropImage) return;
  17536. handleUserFile(e.detail.resources[0]);
  17537. };
  17538. const handlePaste = e => {
  17539. // not allowed to paste
  17540. if (!enablePasteImage) return;
  17541. // calculate percentage of editor that is in view
  17542. const xPercentage = clamp((windowWidth - Math.abs($rootRect.x)) / $rootRect.width, 0, 1);
  17543. const yPercentage = clamp((windowHeight - Math.abs($rootRect.y)) / $rootRect.height, 0, 1);
  17544. // editor needs to be in view
  17545. if (xPercentage < 0.75 && yPercentage < 0.75) return;
  17546. // request load image
  17547. handleUserFile((e.clipboardData || window.clipboardData).files[0]);
  17548. };
  17549. //
  17550. // canvas drawing
  17551. //
  17552. let scrambledPreviewImage = undefined;
  17553. const updateScrambledPreview = (imagePreviewData, imageScrambler, imageRedactionScalar, imageBackgroundColor) => {
  17554. if (!imageScrambler) return;
  17555. // remove transparency
  17556. const editorOptions = { dataSizeScalar: imageRedactionScalar };
  17557. if (imageBackgroundColor && imageBackgroundColor[3] > 0) {
  17558. editorOptions.backgroundColor = [...imageBackgroundColor];
  17559. }
  17560. imageScrambler(imagePreviewData, editorOptions).then(scrambledCanvas => {
  17561. // we've created a new scrambled preview so force release memory of old one
  17562. if (scrambledPreviewImage) releaseCanvas(scrambledPreviewImage);
  17563. // update scrambled preview with new image
  17564. $$invalidate(175, scrambledPreviewImage = scrambledCanvas);
  17565. });
  17566. };
  17567. let blendShapes = [];
  17568. const getStageState = () => ({
  17569. // add foreground color
  17570. foregroundColor: [...$rootForegroundColor],
  17571. // add line color
  17572. lineColor: [...$rootLineColor],
  17573. // add information on which util is active
  17574. utilVisibility: { ...utilsVisibleFraction },
  17575. // used to fade in elements when interacting
  17576. isInteracting: $isInteracting,
  17577. isInteractingFraction: $isInteractingFraction,
  17578. // add the root rectangle so will render can use width/height of root element
  17579. rootRect: rectClone($rootRect),
  17580. // add the stage rectangle so will render knows where stage starts and ends
  17581. stageRect: rectClone($stageRect),
  17582. // preview selection rect
  17583. selectionRect: rectClone($imageSelectionRectPresentation)
  17584. });
  17585. const createCanvasState = (canvasState, blendShapes, annotationShapes, decorationShapes, interfaceShapes, frameShapes) => ({
  17586. blendShapes: blendShapes.filter(shapeIsVisible).map(shape => shapeComputeDisplay(shape, $imageSize)),
  17587. annotationShapes: flattenShapes(annotationShapes.filter(shapeIsVisible).map(shapeDeepCopy).map(shape => shapeComputeDisplay(shape, $imageSize)).map(preprocessShape).flat()),
  17588. decorationShapes: flattenShapes(decorationShapes.filter(shapeIsVisible).map(shapeDeepCopy).map(shape => positionDecorationShape(shape, canvasState)).map(preprocessShape).flat().map(shape => transformDecorationShape(shape, canvasState))),
  17589. interfaceShapes: flattenShapes(interfaceShapes.filter(shapeIsVisible)),
  17590. frameShapes: flattenShapes(frameShapes.map(shapeDeepCopy).map(shape => positionDecorationShape(shape, canvasState)).map(preprocessShape).flat().map(shape => transformDecorationShape(shape, canvasState)))
  17591. });
  17592. // setup root portal for detail panel dropdown
  17593. let rootPortal;
  17594. const rootPortalStore = writable();
  17595. setContext("rootPortal", rootPortalStore);
  17596. // setup root rect store for global access
  17597. setContext("rootRect", rootRect);
  17598. function onwindowresize() {
  17599. $$invalidate(11, windowWidth = window_1$1.innerWidth);
  17600. $$invalidate(12, windowHeight = window_1$1.innerHeight);
  17601. }
  17602. const measure_handler = e => set_store_value(toolRect, $toolRect = e.detail, $toolRect);
  17603. const select_handler = ({ detail }) => $$invalidate(19, utilSelected = detail);
  17604. const func = (panel, util) => util.id === panel;
  17605. function panel_component_binding(value, panel) {
  17606. if ($$self.$$.not_equal(pluginInterface[panel], value)) {
  17607. pluginInterface[panel] = value;
  17608. (($$invalidate(0, pluginInterface), $$invalidate(7, pluginOptions)), $$invalidate(166, pluginComponents));
  17609. }
  17610. }
  17611. const measure_handler_1 = e => set_store_value(utilRect, $utilRect = e.detail, $utilRect);
  17612. const show_handler = panel => $$invalidate(27, utilsVisible = utilsVisible.concat(panel));
  17613. const hide_handler = panel => $$invalidate(27, utilsVisible = utilsVisible.filter(util => util !== panel));
  17614. const fade_handler = (panel, { detail }) => $$invalidate(21, utilsVisibleFraction[panel] = detail, utilsVisibleFraction);
  17615. const measure_handler_2 = e => set_store_value(tabRect, $tabRect = e.detail, $tabRect);
  17616. const func_1 = util => util.id === utilSelected;
  17617. function panel_component_binding_1(value) {
  17618. if ($$self.$$.not_equal(pluginInterface[utilSelected], value)) {
  17619. pluginInterface[utilSelected] = value;
  17620. (($$invalidate(0, pluginInterface), $$invalidate(7, pluginOptions)), $$invalidate(166, pluginComponents));
  17621. }
  17622. }
  17623. const measure_handler_3 = e => set_store_value(utilRect, $utilRect = e.detail, $utilRect);
  17624. const show_handler_1 = () => $$invalidate(27, utilsVisible = utilsVisible.concat(utilSelected));
  17625. const hide_handler_1 = () => $$invalidate(27, utilsVisible = utilsVisible.filter(util => util !== utilSelected));
  17626. const fade_handler_1 = ({ detail }) => $$invalidate(21, utilsVisibleFraction[utilSelected] = detail, utilsVisibleFraction);
  17627. const func_2 = canvasState => {
  17628. // current draw state
  17629. const drawState = { ...canvasState, ...getStageState() };
  17630. // allow devs to add custom overlay to `imageOverlay`
  17631. const { annotationShapes, decorationShapes, interfaceShapes, frameShapes } = willRenderCanvas(
  17632. {
  17633. annotationShapes: $imageAnnotation,
  17634. decorationShapes: $imageDecoration,
  17635. frameShapes: [$imageFrame],
  17636. interfaceShapes: $imageOverlay
  17637. },
  17638. drawState
  17639. );
  17640. // need to map shapes
  17641. return createCanvasState(drawState, blendShapes, annotationShapes, decorationShapes, interfaceShapes, frameShapes);
  17642. };
  17643. function div_binding($$value) {
  17644. binding_callbacks[$$value ? "unshift" : "push"](() => {
  17645. rootPortal = $$value;
  17646. $$invalidate(14, rootPortal);
  17647. });
  17648. }
  17649. function div_binding_1($$value) {
  17650. binding_callbacks[$$value ? "unshift" : "push"](() => {
  17651. root = $$value;
  17652. $$invalidate(1, root);
  17653. });
  17654. }
  17655. const measure_handler_4 = e => set_store_value(clientRect, $clientRect = e.detail, $clientRect);
  17656. $$self.$$set = $$props => {
  17657. if ("class" in $$props) $$invalidate(141, klass = $$props.class);
  17658. if ("layout" in $$props) $$invalidate(142, layoutMode = $$props.layout);
  17659. if ("stores" in $$props) $$invalidate(143, stores = $$props.stores);
  17660. if ("locale" in $$props) $$invalidate(2, locale = $$props.locale);
  17661. if ("id" in $$props) $$invalidate(3, id = $$props.id);
  17662. if ("util" in $$props) $$invalidate(144, util = $$props.util);
  17663. if ("utils" in $$props) $$invalidate(145, utils = $$props.utils);
  17664. if ("animations" in $$props) $$invalidate(146, animations = $$props.animations);
  17665. if ("disabled" in $$props) $$invalidate(147, disabled = $$props.disabled);
  17666. if ("status" in $$props) $$invalidate(139, status = $$props.status);
  17667. if ("previewUpscale" in $$props) $$invalidate(148, previewUpscale = $$props.previewUpscale);
  17668. if ("elasticityMultiplier" in $$props) $$invalidate(4, elasticityMultiplier = $$props.elasticityMultiplier);
  17669. if ("willRevert" in $$props) $$invalidate(149, willRevert = $$props.willRevert);
  17670. if ("willProcessImage" in $$props) $$invalidate(150, willProcessImage = $$props.willProcessImage);
  17671. if ("willRenderCanvas" in $$props) $$invalidate(5, willRenderCanvas = $$props.willRenderCanvas);
  17672. if ("willRenderToolbar" in $$props) $$invalidate(151, willRenderToolbar = $$props.willRenderToolbar);
  17673. if ("willSetHistoryInitialState" in $$props) $$invalidate(152, willSetHistoryInitialState = $$props.willSetHistoryInitialState);
  17674. if ("enableButtonExport" in $$props) $$invalidate(153, enableButtonExport = $$props.enableButtonExport);
  17675. if ("enableButtonRevert" in $$props) $$invalidate(154, enableButtonRevert = $$props.enableButtonRevert);
  17676. if ("enableNavigateHistory" in $$props) $$invalidate(155, enableNavigateHistory = $$props.enableNavigateHistory);
  17677. if ("enableToolbar" in $$props) $$invalidate(6, enableToolbar = $$props.enableToolbar);
  17678. if ("enableUtils" in $$props) $$invalidate(156, enableUtils = $$props.enableUtils);
  17679. if ("enableButtonClose" in $$props) $$invalidate(157, enableButtonClose = $$props.enableButtonClose);
  17680. if ("enableDropImage" in $$props) $$invalidate(158, enableDropImage = $$props.enableDropImage);
  17681. if ("enablePasteImage" in $$props) $$invalidate(159, enablePasteImage = $$props.enablePasteImage);
  17682. if ("previewImageDataMaxSize" in $$props) $$invalidate(160, previewImageDataMaxSize = $$props.previewImageDataMaxSize);
  17683. if ("layoutDirectionPreference" in $$props) $$invalidate(161, layoutDirectionPreference = $$props.layoutDirectionPreference);
  17684. if ("layoutHorizontalUtilsPreference" in $$props) $$invalidate(162, layoutHorizontalUtilsPreference = $$props.layoutHorizontalUtilsPreference);
  17685. if ("layoutVerticalUtilsPreference" in $$props) $$invalidate(163, layoutVerticalUtilsPreference = $$props.layoutVerticalUtilsPreference);
  17686. if ("imagePreviewSrc" in $$props) $$invalidate(164, imagePreviewSrc = $$props.imagePreviewSrc);
  17687. if ("imageOrienter" in $$props) $$invalidate(165, imageOrienter = $$props.imageOrienter);
  17688. if ("pluginComponents" in $$props) $$invalidate(166, pluginComponents = $$props.pluginComponents);
  17689. if ("pluginOptions" in $$props) $$invalidate(7, pluginOptions = $$props.pluginOptions);
  17690. if ("root" in $$props) $$invalidate(1, root = $$props.root);
  17691. if ("imageSourceToImageData" in $$props) $$invalidate(8, imageSourceToImageData = $$props.imageSourceToImageData);
  17692. if ("imagePreviewCurrent" in $$props) $$invalidate(140, imagePreviewCurrent = $$props.imagePreviewCurrent);
  17693. };
  17694. $$self.$$.update = () => {
  17695. if ($$self.$$.dirty[4] & /*layoutMode*/ 262144) {
  17696. // set to new object to force redraw
  17697. $$invalidate(176, isOverlayModeEnabled = layoutMode === "overlay");
  17698. }
  17699. if ($$self.$$.dirty[5] & /*enableUtils, isOverlayModeEnabled*/ 2097154) {
  17700. $$invalidate(15, showUtils = enableUtils && !isOverlayModeEnabled);
  17701. }
  17702. if ($$self.$$.dirty[0] & /*pluginOptions, pluginInterface*/ 129) {
  17703. // map plugin options to plugin interface
  17704. if (pluginOptions) {
  17705. // for every plugin in plugin options
  17706. Object.entries(pluginOptions).forEach(([name, plugin]) => {
  17707. // for every prop defined for this plugin
  17708. Object.entries(plugin).forEach(([prop, value]) => {
  17709. // set value to interface
  17710. if (!pluginInterface[name]) return;
  17711. // set prop value
  17712. $$invalidate(0, pluginInterface[name][prop] = value, pluginInterface);
  17713. });
  17714. });
  17715. }
  17716. }
  17717. if ($$self.$$.dirty[0] & /*pluginInterface*/ 1 | $$self.$$.dirty[5] & /*pluginComponents*/ 2048) {
  17718. {
  17719. let changed = false;
  17720. pluginComponents.forEach(([key]) => {
  17721. if (pluginInterface[key]) return;
  17722. $$invalidate(0, pluginInterface[key] = {}, pluginInterface);
  17723. changed = true;
  17724. });
  17725. if (changed) {
  17726. $$invalidate(168, registeredPluginsComponents = [...pluginComponents]);
  17727. }
  17728. }
  17729. }
  17730. if ($$self.$$.dirty[4] & /*disabled*/ 8388608) {
  17731. disabledTransition.set(disabled ? 1 : 0);
  17732. }
  17733. if ($$self.$$.dirty[5] & /*previewImageDataMaxSize*/ 32) {
  17734. maxImageDataSize = previewImageDataMaxSize
  17735. ? sizeMin(previewImageDataMaxSize, maxTextureSize)
  17736. : maxTextureSize;
  17737. }
  17738. if ($$self.$$.dirty[5] & /*$images*/ 4194304) {
  17739. imageProxy.update($images[0]);
  17740. }
  17741. if ($$self.$$.dirty[5] & /*$shapePreprocessor*/ 8388608) {
  17742. preprocessShape = $shapePreprocessor
  17743. ? shape => $shapePreprocessor(shape, { isPreview: true })
  17744. : passthrough;
  17745. }
  17746. if ($$self.$$.dirty[0] & /*$clientRect*/ 65536) {
  17747. $clientRect && rootRect.set(rectCreate($clientRect.x, $clientRect.y, $clientRect.width, $clientRect.height));
  17748. }
  17749. if ($$self.$$.dirty[5] & /*$rootRect, isOverlayModeEnabled, $imageLoadState*/ 52428800) {
  17750. $rootRect && isOverlayModeEnabled && $imageLoadState && $imageLoadState.complete && syncRootAspectRatio();
  17751. }
  17752. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[4] & /*utils*/ 2097152 | $$self.$$.dirty[5] & /*registeredPluginsComponents*/ 8192) {
  17753. $$invalidate(183, utilsFiltered = locale && registeredPluginsComponents.length
  17754. ? utils || registeredPluginsComponents.map(([id]) => id)
  17755. : []);
  17756. }
  17757. if ($$self.$$.dirty[5] & /*utilsFiltered*/ 268435456) {
  17758. $$invalidate(17, shouldRenderTabs = utilsFiltered.length > 1);
  17759. }
  17760. if ($$self.$$.dirty[0] & /*shouldRenderTabs*/ 131072) {
  17761. if (!shouldRenderTabs) tabRect.set(rectCreateEmpty());
  17762. }
  17763. if ($$self.$$.dirty[0] & /*enableToolbar*/ 64) {
  17764. if (!enableToolbar) toolRect.set(rectCreateEmpty());
  17765. }
  17766. if ($$self.$$.dirty[4] & /*previewUpscale*/ 16777216 | $$self.$$.dirty[5] & /*isOverlayModeEnabled*/ 2097152) {
  17767. previewShouldUpscale.set(previewUpscale || isOverlayModeEnabled);
  17768. }
  17769. if ($$self.$$.dirty[5] & /*registeredPluginsComponents, utilsFiltered*/ 268443648) {
  17770. $$invalidate(211, utilsAvailable = registeredPluginsComponents.filter(([id]) => utilsFiltered.includes(id)));
  17771. }
  17772. if ($$self.$$.dirty[6] & /*utilsAvailable*/ 33554432) {
  17773. $$invalidate(212, utilsDefined = utilsAvailable.length);
  17774. }
  17775. if ($$self.$$.dirty[4] & /*util*/ 1048576 | $$self.$$.dirty[5] & /*utilsFiltered*/ 268435456 | $$self.$$.dirty[6] & /*utilsDefined*/ 67108864) {
  17776. $$invalidate(19, utilSelected = util && typeof util === "string" && utilsFiltered.includes(util)
  17777. ? util
  17778. : utilsDefined > 0 ? utilsFiltered[0] : undefined);
  17779. }
  17780. if ($$self.$$.dirty[0] & /*utilSelected*/ 524288) {
  17781. utilSelected && imageOutlineOpacity.set(0.075);
  17782. }
  17783. if ($$self.$$.dirty[0] & /*utilSelected*/ 524288) {
  17784. overlayInset.set(utilSelected === "resize" ? 40 : 30);
  17785. }
  17786. if ($$self.$$.dirty[0] & /*utilSelected*/ 524288) {
  17787. overlaySize.set(utilSelected === "resize" ? 140 : 70);
  17788. }
  17789. if ($$self.$$.dirty[5] & /*$imageCropRect, $imageOutputSize*/ 1140850688) {
  17790. $$invalidate(187, imageTargetSizeCurrent = $imageCropRect && calculateImageTargetSize($imageOutputSize || {}, $imageCropRect));
  17791. }
  17792. if ($$self.$$.dirty[5] & /*$stageRect*/ 536870912 | $$self.$$.dirty[6] & /*imageTargetSizeCurrent, $overlayInset, $imageVisualBounds*/ 14) {
  17793. imageTargetSizeCurrent && $stageRect && overlayTopOpacity.set(smoothstep($stageRect.y, $stageRect.y - $overlayInset, $imageVisualBounds.y));
  17794. }
  17795. if ($$self.$$.dirty[5] & /*$stageRect*/ 536870912 | $$self.$$.dirty[6] & /*imageTargetSizeCurrent, $overlayInset, $imageVisualBounds*/ 14) {
  17796. imageTargetSizeCurrent && $stageRect && overlayRightOpacity.set(smoothstep($stageRect.x + $stageRect.width, $stageRect.x + $stageRect.width + $overlayInset, $imageVisualBounds.x + $imageVisualBounds.width));
  17797. }
  17798. if ($$self.$$.dirty[5] & /*$stageRect*/ 536870912 | $$self.$$.dirty[6] & /*imageTargetSizeCurrent, $overlayInset, $imageVisualBounds*/ 14) {
  17799. imageTargetSizeCurrent && $stageRect && overlayBottomOpacity.set(smoothstep($stageRect.y + $stageRect.height, $stageRect.y + $stageRect.height + $overlayInset, $imageVisualBounds.y + $imageVisualBounds.height));
  17800. }
  17801. if ($$self.$$.dirty[5] & /*$stageRect*/ 536870912 | $$self.$$.dirty[6] & /*imageTargetSizeCurrent, $overlayInset, $imageVisualBounds*/ 14) {
  17802. imageTargetSizeCurrent && $stageRect && overlayLeftOpacity.set(smoothstep($stageRect.x, $stageRect.x - $overlayInset, $imageVisualBounds.x));
  17803. }
  17804. if ($$self.$$.dirty[5] & /*$rootRect, gradientOverlayVertical*/ 16809984 | $$self.$$.dirty[6] & /*$overlaySize, $overlayTopOpacity*/ 96) {
  17805. $$invalidate(190, overlayTop = $rootRect && {
  17806. id: STAGE_OVERLAY_ID,
  17807. x: 0,
  17808. y: 0,
  17809. width: $rootRect.width,
  17810. height: $overlaySize,
  17811. rotation: Math.PI,
  17812. opacity: maxOpacity * $overlayTopOpacity,
  17813. backgroundImage: gradientOverlayVertical
  17814. });
  17815. }
  17816. if ($$self.$$.dirty[5] & /*$rootRect, gradientOverlayVertical*/ 16809984 | $$self.$$.dirty[6] & /*$overlaySize, $overlayBottomOpacity*/ 288) {
  17817. $$invalidate(193, overlayBottom = $rootRect && {
  17818. id: STAGE_OVERLAY_ID,
  17819. x: 0,
  17820. y: $rootRect.height - $overlaySize,
  17821. width: $rootRect.width,
  17822. height: $overlaySize,
  17823. opacity: maxOpacity * $overlayBottomOpacity,
  17824. backgroundImage: gradientOverlayVertical
  17825. });
  17826. }
  17827. if ($$self.$$.dirty[5] & /*$rootRect, gradientOverlayHorizontal*/ 16793600 | $$self.$$.dirty[6] & /*$overlaySize, $overlayLeftOpacity*/ 1056) {
  17828. $$invalidate(195, overlayLeft = $rootRect && {
  17829. id: STAGE_OVERLAY_ID,
  17830. x: 0,
  17831. y: 0,
  17832. height: $rootRect.height,
  17833. width: $overlaySize,
  17834. rotation: Math.PI,
  17835. opacity: maxOpacity * $overlayLeftOpacity,
  17836. backgroundImage: gradientOverlayHorizontal
  17837. });
  17838. }
  17839. if ($$self.$$.dirty[5] & /*$rootRect, gradientOverlayHorizontal*/ 16793600 | $$self.$$.dirty[6] & /*$overlaySize, $overlayRightOpacity*/ 4128) {
  17840. $$invalidate(197, overlayRight = $rootRect && {
  17841. id: STAGE_OVERLAY_ID,
  17842. x: $rootRect.width - $overlaySize,
  17843. y: 0,
  17844. height: $rootRect.height,
  17845. width: $overlaySize,
  17846. opacity: maxOpacity * $overlayRightOpacity,
  17847. backgroundImage: gradientOverlayHorizontal
  17848. });
  17849. }
  17850. if ($$self.$$.dirty[6] & /*overlayTop, overlayRight, overlayBottom, overlayLeft*/ 2704) {
  17851. $$invalidate(199, gradientOverlays = [overlayTop, overlayRight, overlayBottom, overlayLeft].filter(Boolean));
  17852. }
  17853. if ($$self.$$.dirty[6] & /*gradientOverlays, $imageOverlayMarkup*/ 24576) {
  17854. // if overlay top changes
  17855. if (gradientOverlays && $imageOverlayMarkup) {
  17856. // remove existing resize overlays
  17857. const overlayMarkup = $imageOverlayMarkup.filter(markup => markup.id !== STAGE_OVERLAY_ID);
  17858. set_store_value(imageOverlayMarkup, $imageOverlayMarkup = [...overlayMarkup, ...gradientOverlays], $imageOverlayMarkup);
  17859. }
  17860. }
  17861. if ($$self.$$.dirty[5] & /*imagePreviewSrc*/ 512 | $$self.$$.dirty[6] & /*$imageFile*/ 32768) {
  17862. imagePreviewSource.set(imagePreviewSrc
  17863. ? imagePreviewSrc
  17864. : $imageFile || undefined);
  17865. }
  17866. if ($$self.$$.dirty[0] & /*root*/ 2 | $$self.$$.dirty[4] & /*imagePreviewCurrent*/ 65536 | $$self.$$.dirty[6] & /*$imagePreview*/ 65536) {
  17867. {
  17868. $$invalidate(140, imagePreviewCurrent = $imagePreview);
  17869. if ($imagePreview) root.dispatchEvent(createPing("loadpreview", imagePreviewCurrent));
  17870. }
  17871. }
  17872. if ($$self.$$.dirty[6] & /*$imagePreviewSource*/ 131072) {
  17873. if ($imagePreviewSource) resetPreviews();
  17874. }
  17875. if ($$self.$$.dirty[5] & /*$isInteracting*/ 134217728) {
  17876. $$invalidate(204, canAnimate = !$isInteracting && !isSoftwareRendering());
  17877. }
  17878. if ($$self.$$.dirty[6] & /*$prefersReducedMotion*/ 1048576) {
  17879. $$invalidate(205, acceptsAnimations = !$prefersReducedMotion);
  17880. }
  17881. if ($$self.$$.dirty[4] & /*animations*/ 4194304 | $$self.$$.dirty[6] & /*canAnimate, acceptsAnimations*/ 786432) {
  17882. set_store_value(
  17883. shouldAnimate,
  17884. $shouldAnimate = animations === "always"
  17885. ? canAnimate
  17886. : animations === "never"
  17887. ? false
  17888. : canAnimate && acceptsAnimations,
  17889. $shouldAnimate
  17890. );
  17891. }
  17892. if ($$self.$$.dirty[6] & /*$history*/ 4194304) {
  17893. $$invalidate(207, canUndo = $history.index > 0);
  17894. }
  17895. if ($$self.$$.dirty[6] & /*$history*/ 4194304) {
  17896. $$invalidate(209, canRedo = $history.index < $history.length - 1);
  17897. }
  17898. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[5] & /*utilsFiltered*/ 268435456 | $$self.$$.dirty[6] & /*utilsAvailable*/ 33554432) {
  17899. $$invalidate(20, utilsMerged = utilsFiltered.map(utilId => {
  17900. const util = utilsAvailable.find(([id]) => utilId === id); // [id, view]
  17901. if (!util) return;
  17902. return {
  17903. id: utilId,
  17904. view: util[1],
  17905. tabIcon: locale[`${utilId}Icon`],
  17906. tabLabel: locale[`${utilId}Label`]
  17907. };
  17908. }).filter(Boolean) || []);
  17909. }
  17910. if ($$self.$$.dirty[0] & /*utilSelected*/ 524288) {
  17911. utilSelectedStore.set(utilSelected);
  17912. }
  17913. if ($$self.$$.dirty[0] & /*utilSelected, pluginInterface*/ 524289) {
  17914. $$invalidate(213, utilTools = utilSelected && pluginInterface[utilSelected].tools || []);
  17915. }
  17916. if ($$self.$$.dirty[0] & /*utilsMerged, utilsVisibleFraction*/ 3145728) {
  17917. $$invalidate(21, utilsVisibleFraction = utilsMerged.reduce(
  17918. (prev, curr) => {
  17919. prev[curr.id] = utilsVisibleFraction && utilsVisibleFraction[curr.id] || 0;
  17920. return prev;
  17921. },
  17922. {}
  17923. ));
  17924. }
  17925. if ($$self.$$.dirty[0] & /*utilSelected*/ 524288) {
  17926. $$invalidate(30, tabsConfig = {
  17927. name: utilsUniqueId,
  17928. selected: utilSelected
  17929. });
  17930. }
  17931. if ($$self.$$.dirty[0] & /*utilsMerged*/ 1048576) {
  17932. $$invalidate(31, tabs = utilsMerged.map(util => ({
  17933. id: util.id,
  17934. icon: util.tabIcon,
  17935. label: util.tabLabel
  17936. })));
  17937. }
  17938. if ($$self.$$.dirty[0] & /*utilsMerged*/ 1048576) {
  17939. $$invalidate(32, panels = utilsMerged.map(util => util.id));
  17940. }
  17941. if ($$self.$$.dirty[4] & /*klass*/ 131072) {
  17942. $$invalidate(33, className = arrayJoin(["PinturaRoot", "PinturaRootComponent", klass]));
  17943. }
  17944. if ($$self.$$.dirty[5] & /*$rootRect*/ 16777216) {
  17945. $$invalidate(214, horizontalSpace = $rootRect && ($rootRect.width > 1000
  17946. ? "wide"
  17947. : $rootRect.width < 600 ? "narrow" : undefined));
  17948. }
  17949. if ($$self.$$.dirty[5] & /*$rootRect*/ 16777216) {
  17950. $$invalidate(215, hasLimitedSpace = $rootRect && ($rootRect.width <= 320 || $rootRect.height <= 460));
  17951. }
  17952. if ($$self.$$.dirty[5] & /*$rootRect*/ 16777216) {
  17953. $$invalidate(216, verticalSpace = $rootRect && ($rootRect.height > 1000
  17954. ? "tall"
  17955. : $rootRect.height < 600 ? "short" : undefined));
  17956. }
  17957. if ($$self.$$.dirty[0] & /*root*/ 2) {
  17958. $$invalidate(217, isModal = root && root.parentNode && root.parentNode.classList.contains("PinturaModal"));
  17959. }
  17960. if ($$self.$$.dirty[0] & /*windowWidth*/ 2048 | $$self.$$.dirty[5] & /*$rootRect*/ 16777216 | $$self.$$.dirty[7] & /*isModal*/ 1) {
  17961. $$invalidate(218, isCenteredHorizontally = isModal && $rootRect && windowWidth > $rootRect.width);
  17962. }
  17963. if ($$self.$$.dirty[0] & /*windowHeight*/ 4096 | $$self.$$.dirty[5] & /*$rootRect*/ 16777216 | $$self.$$.dirty[7] & /*isModal*/ 1) {
  17964. $$invalidate(219, isCenteredVertically = isModal && $rootRect && windowHeight > $rootRect.height);
  17965. }
  17966. if ($$self.$$.dirty[7] & /*isCenteredHorizontally, isCenteredVertically*/ 6) {
  17967. $$invalidate(220, isCentered = isCenteredHorizontally && isCenteredVertically);
  17968. }
  17969. if ($$self.$$.dirty[6] & /*horizontalSpace*/ 268435456) {
  17970. $$invalidate(221, isNarrow = horizontalSpace === "narrow");
  17971. }
  17972. if ($$self.$$.dirty[5] & /*$rootRect, layoutDirectionPreference*/ 16777280) {
  17973. $$invalidate(222, orientation = getOrientation($rootRect, layoutDirectionPreference));
  17974. }
  17975. if ($$self.$$.dirty[7] & /*orientation*/ 32) {
  17976. $$invalidate(34, isLandscape = orientation === "landscape");
  17977. }
  17978. if ($$self.$$.dirty[6] & /*verticalSpace*/ 1073741824 | $$self.$$.dirty[7] & /*isNarrow*/ 16) {
  17979. $$invalidate(223, isCompact = isNarrow || verticalSpace === "short");
  17980. }
  17981. if ($$self.$$.dirty[0] & /*windowWidth*/ 2048 | $$self.$$.dirty[5] & /*$rootRect*/ 16777216) {
  17982. $$invalidate(224, hasSwipeNavigation = iOS && $rootRect && windowWidth === $rootRect.width && !shouldPreventSwipe);
  17983. }
  17984. if ($$self.$$.dirty[5] & /*isOverlayModeEnabled*/ 2097152 | $$self.$$.dirty[6] & /*utilTools, verticalSpace*/ 1207959552) {
  17985. $$invalidate(225, shouldRenderUtilTools = utilTools.length && (verticalSpace === "short" || isOverlayModeEnabled));
  17986. }
  17987. if ($$self.$$.dirty[5] & /*layoutHorizontalUtilsPreference*/ 128) {
  17988. $$invalidate(226, navigationHorizontalPreference = `has-navigation-preference-${layoutHorizontalUtilsPreference}`);
  17989. }
  17990. if ($$self.$$.dirty[5] & /*layoutVerticalUtilsPreference*/ 256) {
  17991. $$invalidate(227, navigationVerticalPreference = `has-navigation-preference-${layoutVerticalUtilsPreference}`);
  17992. }
  17993. if ($$self.$$.dirty[0] & /*root*/ 2) {
  17994. // will update when root element is available (computed style is live, so is updated when the style is updated)
  17995. $$invalidate(228, rootElementComputedStyle = root && getComputedStyle(root));
  17996. }
  17997. if ($$self.$$.dirty[7] & /*rootElementComputedStyle*/ 2048) {
  17998. // sync for first time
  17999. if (rootElementComputedStyle) syncColors();
  18000. }
  18001. if ($$self.$$.dirty[0] & /*$shouldAnimate, enableToolbar, shouldRenderTabs, showUtils*/ 426048 | $$self.$$.dirty[4] & /*layoutMode, disabled*/ 8650752 | $$self.$$.dirty[6] & /*horizontalSpace, verticalSpace, hasLimitedSpace*/ 1879048192 | $$self.$$.dirty[7] & /*$env, orientation, navigationHorizontalPreference, navigationVerticalPreference, isModal, isCentered, isCenteredHorizontally, isCenteredVertically, $pointerAccuracy, $pointerHoverable, isCompact, hasSwipeNavigation*/ 30447) {
  18002. env.set({
  18003. ...$env,
  18004. layoutMode,
  18005. orientation,
  18006. horizontalSpace,
  18007. verticalSpace,
  18008. navigationHorizontalPreference,
  18009. navigationVerticalPreference,
  18010. isModal,
  18011. isDisabled: disabled,
  18012. isCentered,
  18013. isCenteredHorizontally,
  18014. isCenteredVertically,
  18015. isAnimated: $shouldAnimate,
  18016. pointerAccuracy: $pointerAccuracy,
  18017. pointerHoverable: $pointerHoverable,
  18018. isCompact,
  18019. hasSwipeNavigation,
  18020. hasLimitedSpace,
  18021. hasToolbar: enableToolbar,
  18022. hasNavigation: shouldRenderTabs && showUtils,
  18023. isIOS: iOS
  18024. });
  18025. }
  18026. if ($$self.$$.dirty[7] & /*$env*/ 4096) {
  18027. $$invalidate(35, envStr = Object.entries($env).map(([key, value]) => {
  18028. // is true boolean prop, use key
  18029. if ((/^is|has/).test(key)) {
  18030. return value ? toKebabCase(key) : undefined;
  18031. }
  18032. // use value
  18033. return value;
  18034. }).filter(Boolean).join(" "));
  18035. }
  18036. if ($$self.$$.dirty[7] & /*$imageTransforms, $imagePreviewModifiers*/ 98304) {
  18037. $$invalidate(36, imageCanvasState = $imageTransforms && Object.entries($imagePreviewModifiers).filter(([,value]) => value != null).reduce(
  18038. (prev, [,value]) => {
  18039. prev = { ...prev, ...value };
  18040. return prev;
  18041. },
  18042. {}
  18043. ));
  18044. }
  18045. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432) {
  18046. //
  18047. // loading status
  18048. //
  18049. $$invalidate(234, isStartLoadingImageSource = $imageLoadState && $imageLoadState.task === "any-to-file");
  18050. }
  18051. if ($$self.$$.dirty[7] & /*isStartLoadingImageSource*/ 131072) {
  18052. // reset active images when loading a new image source
  18053. if (isStartLoadingImageSource && activeImages) {
  18054. activeImages.clear();
  18055. }
  18056. }
  18057. if ($$self.$$.dirty[7] & /*$imageProps*/ 262144) {
  18058. // if image props are ready
  18059. $$invalidate(236, hasProps = !!$imageProps && !!$imageProps.translation);
  18060. }
  18061. if ($$self.$$.dirty[5] & /*lastImagePreview*/ 131072 | $$self.$$.dirty[6] & /*$imagePreview*/ 65536 | $$self.$$.dirty[7] & /*hasProps*/ 524288) {
  18062. if (hasProps && $imagePreview && $imagePreview !== lastImagePreview) {
  18063. $$invalidate(172, lastImagePreview = $imagePreview);
  18064. addImagePreview();
  18065. }
  18066. }
  18067. if ($$self.$$.dirty[7] & /*hasProps, $imageProps*/ 786432) {
  18068. // update images when image props change
  18069. hasProps && updateImagePreviews($imageProps);
  18070. }
  18071. if ($$self.$$.dirty[0] & /*$activeImages*/ 4194304) {
  18072. // clean active images array, removes 'inactive' images when their opacity is 0
  18073. if ($activeImages && $activeImages.length > 1) {
  18074. let imagesToRemove = [];
  18075. activeImages.forEach((image, index) => {
  18076. if (index === 0) return;
  18077. if (image.get().opacity <= 0) imagesToRemove.push(image);
  18078. });
  18079. imagesToRemove.forEach(image => activeImages.remove(image));
  18080. }
  18081. }
  18082. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[7] & /*missingFeatures*/ 1048576) {
  18083. $$invalidate(23, isSupportsError = locale && missingFeatures.length && locale.labelSupportError(missingFeatures));
  18084. }
  18085. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432) {
  18086. $$invalidate(238, isImageLoadError = $imageLoadState && !!$imageLoadState.error);
  18087. }
  18088. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432) {
  18089. $$invalidate(239, isWaitingForImage = !$imageLoadState || !$imageLoadState.complete && $imageLoadState.task === undefined);
  18090. }
  18091. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432) {
  18092. $$invalidate(240, imageLoadProgress = $imageLoadState && ($imageLoadState.taskLengthComputable
  18093. ? $imageLoadState.taskProgress
  18094. : Infinity));
  18095. }
  18096. if ($$self.$$.dirty[7] & /*isStartLoadingImageSource*/ 131072) {
  18097. if (isStartLoadingImageSource) set_store_value(imageVisualLoadComplete, $imageVisualLoadComplete = false, $imageVisualLoadComplete);
  18098. }
  18099. if ($$self.$$.dirty[5] & /*$imageLoadState, loadTimer*/ 33816576) {
  18100. if ($imageLoadState && $imageLoadState.complete) {
  18101. const minLoaderDuration = 500;
  18102. // TODO: derive visual load complete from interface rest state instead of arbitrary timer
  18103. clearTimeout(loadTimer);
  18104. $$invalidate(173, loadTimer = setTimeout(
  18105. () => {
  18106. set_store_value(imageVisualLoadComplete, $imageVisualLoadComplete = true, $imageVisualLoadComplete);
  18107. },
  18108. minLoaderDuration
  18109. ));
  18110. }
  18111. }
  18112. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432 | $$self.$$.dirty[7] & /*isImageLoadError, isWaitingForImage, $imageVisualLoadComplete*/ 39845888) {
  18113. $$invalidate(241, isLoadingImageData = $imageLoadState && !isImageLoadError && !isWaitingForImage && !$imageVisualLoadComplete);
  18114. }
  18115. if ($$self.$$.dirty[5] & /*imagePreviewLoaderCancelToken*/ 65536 | $$self.$$.dirty[6] & /*$imagePreviewSource, $imagePreview*/ 196608) {
  18116. // is creating a preview while an image source is set and the preview isn't ready or when a cancel token is found
  18117. $$invalidate(243, isCreatingImagePreview = !!$imagePreviewSource && (!$imagePreview || !!imagePreviewLoaderCancelToken));
  18118. }
  18119. if ($$self.$$.dirty[6] & /*$imageProcessingPreparing*/ 16777216 | $$self.$$.dirty[7] & /*$imageProcessState*/ 268435456) {
  18120. //
  18121. // processing status
  18122. //
  18123. $$invalidate(244, isProcessingImage = $imageProcessingPreparing || $imageProcessState && $imageProcessState.progress !== undefined && !$imageProcessState.complete);
  18124. }
  18125. if ($$self.$$.dirty[5] & /*$imageLoadState*/ 33554432 | $$self.$$.dirty[7] & /*isWaitingForImage*/ 4194304) {
  18126. $$invalidate(246, imageLoadShowProgressIndicator = $imageLoadState && !($imageLoadState.error || isWaitingForImage));
  18127. }
  18128. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[5] & /*$imageLoadState*/ 33554432) {
  18129. $$invalidate(247, imageLoadStatusLabel = locale && (!$imageLoadState
  18130. ? locale.statusLabelLoadImage($imageLoadState)
  18131. : !$imageLoadState.complete || $imageLoadState.error
  18132. ? stringReplace(locale.statusLabelLoadImage($imageLoadState), $imageLoadState.error && $imageLoadState.error.metadata, "{", "}")
  18133. : locale.statusLabelLoadImage({
  18134. progress: Infinity,
  18135. task: "blob-to-bitmap"
  18136. })));
  18137. }
  18138. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[7] & /*$imageProcessState*/ 268435456) {
  18139. $$invalidate(248, imageProcessStatusLabel = $imageProcessState && locale && locale.statusLabelProcessImage($imageProcessState));
  18140. }
  18141. if ($$self.$$.dirty[7] & /*$imageProcessState*/ 268435456) {
  18142. $$invalidate(249, imageProcessProgress = $imageProcessState && ($imageProcessState.taskLengthComputable
  18143. ? $imageProcessState.taskProgress
  18144. : Infinity));
  18145. }
  18146. if ($$self.$$.dirty[7] & /*$imageProcessState*/ 268435456) {
  18147. $$invalidate(250, imageProcessShowProgressIndicator = $imageProcessState && !$imageProcessState.error);
  18148. }
  18149. if ($$self.$$.dirty[7] & /*$imageProcessState*/ 268435456) {
  18150. $$invalidate(251, isImageProcessingError = $imageProcessState && $imageProcessState.error);
  18151. }
  18152. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[4] & /*status*/ 32768 | $$self.$$.dirty[7] & /*isWaitingForImage, isImageLoadError, isLoadingImageData, isCreatingImagePreview, imageLoadStatusLabel, imageLoadShowProgressIndicator, imageLoadProgress, isProcessingImage*/ 1843396608 | $$self.$$.dirty[8] & /*imageProcessStatusLabel, isImageProcessingError, imageProcessShowProgressIndicator, imageProcessProgress*/ 15) {
  18153. if (status) {
  18154. let label;
  18155. let progress;
  18156. let showProgress;
  18157. let isError;
  18158. let errorCallback;
  18159. if (isString(status)) label = status;
  18160. if (isNumber(status)) progress = status; else if (Array.isArray(status)) {
  18161. [label, progress, errorCallback] = status;
  18162. if (progress === false) isError = true;
  18163. if (isNumber(progress)) showProgress = true;
  18164. }
  18165. $$invalidate(13, statusState = (label || progress) && {
  18166. text: label,
  18167. aside: isError || showProgress,
  18168. progressIndicator: { visible: showProgress, progress },
  18169. closeButton: isError && {
  18170. label: locale.statusLabelButtonClose,
  18171. icon: locale.statusIconButtonClose,
  18172. onclick: errorCallback || (() => $$invalidate(139, status = undefined))
  18173. }
  18174. });
  18175. } else if (locale && isWaitingForImage || isImageLoadError || isLoadingImageData || isCreatingImagePreview) {
  18176. $$invalidate(13, statusState = {
  18177. text: imageLoadStatusLabel,
  18178. aside: isImageLoadError || imageLoadShowProgressIndicator,
  18179. progressIndicator: {
  18180. visible: imageLoadShowProgressIndicator,
  18181. progress: imageLoadProgress
  18182. },
  18183. closeButton: isImageLoadError && {
  18184. label: locale.statusLabelButtonClose,
  18185. icon: locale.statusIconButtonClose,
  18186. onclick: handleCloseImageLoadError
  18187. }
  18188. });
  18189. } else if (locale && isProcessingImage && imageProcessStatusLabel) {
  18190. $$invalidate(13, statusState = {
  18191. text: imageProcessStatusLabel,
  18192. aside: isImageProcessingError || imageProcessShowProgressIndicator,
  18193. progressIndicator: {
  18194. visible: imageProcessShowProgressIndicator,
  18195. progress: imageProcessProgress
  18196. },
  18197. closeButton: isImageProcessingError && {
  18198. label: locale.statusLabelButtonClose,
  18199. icon: locale.statusIconButtonClose,
  18200. onclick: handleCloseImageProcessError
  18201. }
  18202. });
  18203. } else {
  18204. $$invalidate(13, statusState = undefined);
  18205. }
  18206. }
  18207. if ($$self.$$.dirty[4] & /*status*/ 32768) {
  18208. $$invalidate(252, isCustomStatus = status !== undefined);
  18209. }
  18210. if ($$self.$$.dirty[7] & /*isModal, $imageProcessState*/ 268435457) {
  18211. if (isModal && $imageProcessState && $imageProcessState.complete) {
  18212. wasProcessingImage.set(true);
  18213. setTimeout(() => wasProcessingImage.set(false), 100);
  18214. }
  18215. }
  18216. if ($$self.$$.dirty[0] & /*isSupportsError*/ 8388608 | $$self.$$.dirty[7] & /*isWaitingForImage, isImageLoadError, isLoadingImageData, isCreatingImagePreview, isProcessingImage*/ 224395264 | $$self.$$.dirty[8] & /*$wasProcessingImage, isCustomStatus*/ 80) {
  18217. $$invalidate(253, isStatusActive = $wasProcessingImage || isSupportsError || isWaitingForImage || isImageLoadError || isLoadingImageData || isCreatingImagePreview || isProcessingImage || isCustomStatus);
  18218. }
  18219. if ($$self.$$.dirty[8] & /*isStatusActive*/ 32) {
  18220. set_store_value(statusOpacity, $statusOpacity = isStatusActive ? 1 : 0, $statusOpacity);
  18221. }
  18222. if ($$self.$$.dirty[0] & /*$statusOpacity*/ 16777216) {
  18223. $$invalidate(25, isStatusVisible = $statusOpacity > 0);
  18224. }
  18225. if ($$self.$$.dirty[0] & /*statusState*/ 8192) {
  18226. $$invalidate(255, hasAside = !!(statusState && statusState.aside));
  18227. }
  18228. if ($$self.$$.dirty[0] & /*isStatusVisible, statusState*/ 33562624 | $$self.$$.dirty[5] & /*asideWidthUpdateTimer*/ 524288 | $$self.$$.dirty[8] & /*hasAside, $statusWidth*/ 384) {
  18229. if (isStatusVisible && statusState) {
  18230. clearTimeout(asideWidthUpdateTimer);
  18231. // has aside
  18232. if (hasAside) {
  18233. // if error occured, snap in possition
  18234. const hard = !!statusState.error;
  18235. asideOpacity.set(1);
  18236. // update offset of aside
  18237. asideOffset.set($statusWidth, { hard });
  18238. // update width of aside, this pushes message to left so it stays centered
  18239. $$invalidate(174, asideWidthUpdateTimer = setTimeout(
  18240. () => {
  18241. asideWidth.set(16);
  18242. },
  18243. 1
  18244. ));
  18245. } else {
  18246. asideOpacity.set(0);
  18247. $$invalidate(174, asideWidthUpdateTimer = setTimeout(
  18248. () => {
  18249. asideWidth.set(0);
  18250. },
  18251. 1
  18252. ));
  18253. }
  18254. }
  18255. }
  18256. if ($$self.$$.dirty[0] & /*isStatusVisible*/ 33554432) {
  18257. if (!isStatusVisible) {
  18258. statusOffset.set(undefined, { hard: true });
  18259. asideOffset.set(undefined, { hard: true });
  18260. asideWidth.set(0, { hard: true });
  18261. }
  18262. }
  18263. if ($$self.$$.dirty[8] & /*$asideWidth*/ 1024) {
  18264. $$invalidate(257, statusIndent = $asideWidth * 0.5);
  18265. }
  18266. if ($$self.$$.dirty[8] & /*$statusOffset, statusIndent*/ 2560) {
  18267. $$invalidate(38, statusTransform = `transform: translateX(${$statusOffset - statusIndent}px)`);
  18268. }
  18269. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[4] & /*willRenderToolbar, enableButtonRevert, enableButtonExport*/ 1744830464 | $$self.$$.dirty[5] & /*enableButtonClose, enableNavigateHistory*/ 5 | $$self.$$.dirty[6] & /*canUndo, canRedo, utilTools*/ 144703488 | $$self.$$.dirty[7] & /*shouldRenderUtilTools, isNarrow, $env*/ 4368) {
  18270. // dynamic IO menu
  18271. $$invalidate(39, toolbarItems = locale && willRenderToolbar(
  18272. [
  18273. [
  18274. "div",
  18275. "alpha",
  18276. { class: "PinturaNavGroup" },
  18277. [
  18278. [
  18279. "div",
  18280. "alpha-set",
  18281. { class: "PinturaNavSet" },
  18282. [
  18283. // button close
  18284. enableButtonClose && [
  18285. "Button",
  18286. "close",
  18287. {
  18288. label: locale.labelClose,
  18289. icon: locale.iconButtonClose,
  18290. onclick: () => dispatch("close"),
  18291. hideLabel: true
  18292. }
  18293. ],
  18294. // button revert
  18295. enableButtonRevert && [
  18296. "Button",
  18297. "revert",
  18298. {
  18299. label: locale.labelButtonRevert,
  18300. icon: locale.iconButtonRevert,
  18301. disabled: !canUndo,
  18302. onclick: revert,
  18303. hideLabel: true
  18304. }
  18305. ]
  18306. ]
  18307. ]
  18308. ]
  18309. ],
  18310. [
  18311. "div",
  18312. "beta",
  18313. {
  18314. class: "PinturaNavGroup PinturaNavGroupFloat"
  18315. },
  18316. [
  18317. enableNavigateHistory && [
  18318. "div",
  18319. "history",
  18320. { class: "PinturaNavSet" },
  18321. [
  18322. [
  18323. "Button",
  18324. "undo",
  18325. {
  18326. label: locale.labelButtonUndo,
  18327. icon: locale.iconButtonUndo,
  18328. disabled: !canUndo,
  18329. onclick: history.undo,
  18330. hideLabel: true
  18331. }
  18332. ],
  18333. [
  18334. "Button",
  18335. "redo",
  18336. {
  18337. label: locale.labelButtonRedo,
  18338. icon: locale.iconButtonRedo,
  18339. disabled: !canRedo,
  18340. onclick: history.redo,
  18341. hideLabel: true
  18342. }
  18343. ]
  18344. ]
  18345. ],
  18346. shouldRenderUtilTools && [
  18347. "div",
  18348. "plugin-tools",
  18349. { class: "PinturaNavSet" },
  18350. utilTools.filter(Boolean).map(// in
  18351. ([component, key, props]) => // out
  18352. [component, key, { ...props, hideLabel: true }])
  18353. ]
  18354. ]
  18355. ],
  18356. [
  18357. "div",
  18358. "gamma",
  18359. { class: "PinturaNavGroup" },
  18360. [
  18361. enableButtonExport && [
  18362. "Button",
  18363. "export",
  18364. {
  18365. label: locale.labelButtonExport,
  18366. icon: isNarrow && locale.iconButtonExport,
  18367. class: "PinturaButtonExport",
  18368. onclick: handleExport,
  18369. hideLabel: isNarrow
  18370. }
  18371. ]
  18372. ]
  18373. ]
  18374. ],
  18375. { ...$env }
  18376. ));
  18377. }
  18378. if ($$self.$$.dirty[0] & /*$clientRect*/ 65536) {
  18379. $$invalidate(260, hasClientRect = $clientRect && $clientRect.width > 0 && $clientRect.height > 0);
  18380. }
  18381. if ($$self.$$.dirty[0] & /*locale*/ 4 | $$self.$$.dirty[6] & /*utilsDefined*/ 67108864 | $$self.$$.dirty[8] & /*hasClientRect*/ 4096) {
  18382. $$invalidate(40, canRender = hasClientRect && locale && utilsDefined);
  18383. }
  18384. if ($$self.$$.dirty[8] & /*$imageRedaction*/ 16384) {
  18385. // toggles on/off depending on active redaction shapes
  18386. $$invalidate(261, hasImageRedaction = $imageRedaction && !!$imageRedaction.length);
  18387. }
  18388. if ($$self.$$.dirty[6] & /*$imageSize*/ 1 | $$self.$$.dirty[8] & /*hasImageRedaction, $imageRedaction*/ 24576) {
  18389. // scales down resolution of scrambled image if redaction takes up more than half of view
  18390. $$invalidate(263, imageRedactionScalar = hasImageRedaction && getImageRedactionScaleFactor($imageSize, $imageRedaction));
  18391. }
  18392. if ($$self.$$.dirty[6] & /*$imagePreview*/ 65536 | $$self.$$.dirty[8] & /*hasImageRedaction, $imageScrambler, imageRedactionScalar, $imageBackgroundColor*/ 237568) {
  18393. // only update/render preview if image redaction shapes are found
  18394. hasImageRedaction && updateScrambledPreview($imagePreview, $imageScrambler, imageRedactionScalar, $imageBackgroundColor);
  18395. }
  18396. if ($$self.$$.dirty[5] & /*scrambledPreviewImage*/ 1048576 | $$self.$$.dirty[6] & /*$imageSize*/ 1 | $$self.$$.dirty[8] & /*$imageRedaction*/ 16384) {
  18397. if ($imageRedaction && scrambledPreviewImage && $imageSize) {
  18398. // used to calculate fraction x y coordinates of shape corners
  18399. const { width, height } = $imageSize;
  18400. // to blended shapes
  18401. $$invalidate(28, blendShapes = $imageRedaction.map(shape => {
  18402. const rect = rectCreate(shape.x, shape.y, shape.width, shape.height);
  18403. const corners = rectRotate(rectClone(rect), shape.rotation);
  18404. const backgroundCorners = corners.map(corner => vectorCreate(corner.x / width, corner.y / height));
  18405. return {
  18406. ...shape,
  18407. id: "redaction",
  18408. flipX: false,
  18409. flipY: false,
  18410. cornerRadius: 0,
  18411. strokeWidth: 0,
  18412. strokeColor: undefined,
  18413. backgroundColor: [0, 0, 0],
  18414. backgroundImage: scrambledPreviewImage,
  18415. backgroundImageRendering: "pixelated",
  18416. backgroundCorners
  18417. };
  18418. }));
  18419. }
  18420. }
  18421. if ($$self.$$.dirty[0] & /*rootPortal*/ 16384) {
  18422. rootPortal && rootPortalStore.set(rootPortal);
  18423. }
  18424. if ($$self.$$.dirty[0] & /*isSupportsError*/ 8388608 | $$self.$$.dirty[6] & /*$imagePreview*/ 65536) {
  18425. // ready bool
  18426. $$invalidate(26, isReady = $imagePreview && !isSupportsError);
  18427. }
  18428. if ($$self.$$.dirty[0] & /*isReady, root*/ 67108866) {
  18429. // now ready for interaction
  18430. isReady && root.dispatchEvent(createPing("ready"));
  18431. }
  18432. };
  18433. $$invalidate(237, missingFeatures = [!supportsWebGL() && "WebGL"].filter(Boolean));
  18434. // used to route ping events
  18435. $$invalidate(41, routePing = createPingRouter(eventProxy.pub));
  18436. return [
  18437. pluginInterface,
  18438. root,
  18439. locale,
  18440. id,
  18441. elasticityMultiplier,
  18442. willRenderCanvas,
  18443. enableToolbar,
  18444. pluginOptions,
  18445. imageSourceToImageData,
  18446. imagePreview,
  18447. history,
  18448. windowWidth,
  18449. windowHeight,
  18450. statusState,
  18451. rootPortal,
  18452. showUtils,
  18453. $clientRect,
  18454. shouldRenderTabs,
  18455. $shouldAnimate,
  18456. utilSelected,
  18457. utilsMerged,
  18458. utilsVisibleFraction,
  18459. $activeImages,
  18460. isSupportsError,
  18461. $statusOpacity,
  18462. isStatusVisible,
  18463. isReady,
  18464. utilsVisible,
  18465. blendShapes,
  18466. $tabRect,
  18467. tabsConfig,
  18468. tabs,
  18469. panels,
  18470. className,
  18471. isLandscape,
  18472. envStr,
  18473. imageCanvasState,
  18474. $imageSelectionRectPresentation,
  18475. statusTransform,
  18476. toolbarItems,
  18477. canRender,
  18478. routePing,
  18479. $asideOffset,
  18480. $asideOpacity,
  18481. $toolRect,
  18482. $utilRect,
  18483. $pixelRatio,
  18484. $rootBackgroundColor,
  18485. $utilSelectedStore,
  18486. $stagePadded,
  18487. $interfaceImages,
  18488. $imageAnnotation,
  18489. $imageDecoration,
  18490. $imageFrame,
  18491. $imageOverlay,
  18492. $disabledTransition,
  18493. disabledTransition,
  18494. imageFile,
  18495. imageSize,
  18496. imageLoadState,
  18497. imageProcessState,
  18498. imageCropAspectRatio,
  18499. imageCropRect,
  18500. imageOutputSize,
  18501. imageBackgroundColor,
  18502. imageDecoration,
  18503. imageAnnotation,
  18504. imageRedaction,
  18505. imageFrame,
  18506. imageState,
  18507. images,
  18508. shapePreprocessor,
  18509. imageScrambler,
  18510. utilSelectedStore,
  18511. rootBackgroundColor,
  18512. rootForegroundColor,
  18513. rootLineColor,
  18514. clientRect,
  18515. rootRect,
  18516. tabRect,
  18517. toolRect,
  18518. utilRect,
  18519. pointerAccuracy,
  18520. pointerHoverable,
  18521. isInteracting,
  18522. isInteractingFraction,
  18523. previewShouldUpscale,
  18524. imageCropRectSnapshot,
  18525. imageCropRectIntent,
  18526. imageSelectionRect,
  18527. imageSelectionRectSnapshot,
  18528. imageSelectionRectIntent,
  18529. stagePadded,
  18530. stageRect,
  18531. stageScalar,
  18532. imageSelectionRectPresentation,
  18533. presentationScalar,
  18534. imageVisualBounds,
  18535. imageOverlayMarkup,
  18536. imageOverlay,
  18537. overlayInset,
  18538. overlaySize,
  18539. overlayLeftOpacity,
  18540. overlayRightOpacity,
  18541. overlayTopOpacity,
  18542. overlayBottomOpacity,
  18543. imageVisualLoadComplete,
  18544. imagePreviewSource,
  18545. imagePreviewModifiers,
  18546. interfaceImages,
  18547. imageTransforms,
  18548. env,
  18549. pixelRatio,
  18550. shouldAnimate,
  18551. imageProcessingPreparing,
  18552. utilStores,
  18553. handleTransitionEnd,
  18554. imageProps,
  18555. activeImages,
  18556. statusOpacity,
  18557. wasProcessingImage,
  18558. asideOffset,
  18559. asideOpacity,
  18560. asideWidth,
  18561. statusWidth,
  18562. statusOffset,
  18563. offsetAside,
  18564. handleTouchStart,
  18565. handleTouchMove,
  18566. handlePointerMove,
  18567. pressedKeysStore,
  18568. handleKeydown,
  18569. handleKeyup,
  18570. handleWindowBlur,
  18571. handleContextMenu,
  18572. handleDropFiles,
  18573. handlePaste,
  18574. getStageState,
  18575. createCanvasState,
  18576. status,
  18577. imagePreviewCurrent,
  18578. klass,
  18579. layoutMode,
  18580. stores,
  18581. util,
  18582. utils,
  18583. animations,
  18584. disabled,
  18585. previewUpscale,
  18586. willRevert,
  18587. willProcessImage,
  18588. willRenderToolbar,
  18589. willSetHistoryInitialState,
  18590. enableButtonExport,
  18591. enableButtonRevert,
  18592. enableNavigateHistory,
  18593. enableUtils,
  18594. enableButtonClose,
  18595. enableDropImage,
  18596. enablePasteImage,
  18597. previewImageDataMaxSize,
  18598. layoutDirectionPreference,
  18599. layoutHorizontalUtilsPreference,
  18600. layoutVerticalUtilsPreference,
  18601. imagePreviewSrc,
  18602. imageOrienter,
  18603. pluginComponents,
  18604. sub,
  18605. registeredPluginsComponents,
  18606. gradientOverlayHorizontal,
  18607. gradientOverlayVertical,
  18608. imagePreviewLoaderCancelToken,
  18609. lastImagePreview,
  18610. loadTimer,
  18611. asideWidthUpdateTimer,
  18612. scrambledPreviewImage,
  18613. isOverlayModeEnabled,
  18614. $images,
  18615. $shapePreprocessor,
  18616. $rootRect,
  18617. $imageLoadState,
  18618. $imageCropRect,
  18619. $isInteracting,
  18620. utilsFiltered,
  18621. $stageRect,
  18622. $imageOutputSize,
  18623. $imageSize,
  18624. imageTargetSizeCurrent,
  18625. $overlayInset,
  18626. $imageVisualBounds,
  18627. overlayTop,
  18628. $overlaySize,
  18629. $overlayTopOpacity,
  18630. overlayBottom,
  18631. $overlayBottomOpacity,
  18632. overlayLeft,
  18633. $overlayLeftOpacity,
  18634. overlayRight,
  18635. $overlayRightOpacity,
  18636. gradientOverlays,
  18637. $imageOverlayMarkup,
  18638. $imageFile,
  18639. $imagePreview,
  18640. $imagePreviewSource,
  18641. canAnimate,
  18642. acceptsAnimations,
  18643. $prefersReducedMotion,
  18644. canUndo,
  18645. $history,
  18646. canRedo,
  18647. $imageProcessingPreparing,
  18648. utilsAvailable,
  18649. utilsDefined,
  18650. utilTools,
  18651. horizontalSpace,
  18652. hasLimitedSpace,
  18653. verticalSpace,
  18654. isModal,
  18655. isCenteredHorizontally,
  18656. isCenteredVertically,
  18657. isCentered,
  18658. isNarrow,
  18659. orientation,
  18660. isCompact,
  18661. hasSwipeNavigation,
  18662. shouldRenderUtilTools,
  18663. navigationHorizontalPreference,
  18664. navigationVerticalPreference,
  18665. rootElementComputedStyle,
  18666. $env,
  18667. $pointerAccuracy,
  18668. $pointerHoverable,
  18669. $imageTransforms,
  18670. $imagePreviewModifiers,
  18671. isStartLoadingImageSource,
  18672. $imageProps,
  18673. hasProps,
  18674. missingFeatures,
  18675. isImageLoadError,
  18676. isWaitingForImage,
  18677. imageLoadProgress,
  18678. isLoadingImageData,
  18679. $imageVisualLoadComplete,
  18680. isCreatingImagePreview,
  18681. isProcessingImage,
  18682. $imageProcessState,
  18683. imageLoadShowProgressIndicator,
  18684. imageLoadStatusLabel,
  18685. imageProcessStatusLabel,
  18686. imageProcessProgress,
  18687. imageProcessShowProgressIndicator,
  18688. isImageProcessingError,
  18689. isCustomStatus,
  18690. isStatusActive,
  18691. $wasProcessingImage,
  18692. hasAside,
  18693. $statusWidth,
  18694. statusIndent,
  18695. $asideWidth,
  18696. $statusOffset,
  18697. hasClientRect,
  18698. hasImageRedaction,
  18699. $imageRedaction,
  18700. imageRedactionScalar,
  18701. $imageScrambler,
  18702. $imageBackgroundColor,
  18703. onwindowresize,
  18704. measure_handler,
  18705. select_handler,
  18706. func,
  18707. panel_component_binding,
  18708. measure_handler_1,
  18709. show_handler,
  18710. hide_handler,
  18711. fade_handler,
  18712. measure_handler_2,
  18713. func_1,
  18714. panel_component_binding_1,
  18715. measure_handler_3,
  18716. show_handler_1,
  18717. hide_handler_1,
  18718. fade_handler_1,
  18719. func_2,
  18720. div_binding,
  18721. div_binding_1,
  18722. measure_handler_4
  18723. ];
  18724. }
  18725. class Ui extends SvelteComponent {
  18726. constructor(options) {
  18727. super();
  18728. init(
  18729. this,
  18730. options,
  18731. instance$u,
  18732. create_fragment$u,
  18733. safe_not_equal,
  18734. {
  18735. class: 141,
  18736. layout: 142,
  18737. stores: 143,
  18738. locale: 2,
  18739. id: 3,
  18740. util: 144,
  18741. utils: 145,
  18742. animations: 146,
  18743. disabled: 147,
  18744. status: 139,
  18745. previewUpscale: 148,
  18746. elasticityMultiplier: 4,
  18747. willRevert: 149,
  18748. willProcessImage: 150,
  18749. willRenderCanvas: 5,
  18750. willRenderToolbar: 151,
  18751. willSetHistoryInitialState: 152,
  18752. enableButtonExport: 153,
  18753. enableButtonRevert: 154,
  18754. enableNavigateHistory: 155,
  18755. enableToolbar: 6,
  18756. enableUtils: 156,
  18757. enableButtonClose: 157,
  18758. enableDropImage: 158,
  18759. enablePasteImage: 159,
  18760. previewImageDataMaxSize: 160,
  18761. layoutDirectionPreference: 161,
  18762. layoutHorizontalUtilsPreference: 162,
  18763. layoutVerticalUtilsPreference: 163,
  18764. imagePreviewSrc: 164,
  18765. imageOrienter: 165,
  18766. pluginComponents: 166,
  18767. pluginOptions: 7,
  18768. sub: 167,
  18769. pluginInterface: 0,
  18770. root: 1,
  18771. imageSourceToImageData: 8,
  18772. imagePreview: 9,
  18773. imagePreviewCurrent: 140,
  18774. history: 10
  18775. },
  18776. [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
  18777. );
  18778. }
  18779. get class() {
  18780. return this.$$.ctx[141];
  18781. }
  18782. set class(klass) {
  18783. this.$set({ class: klass });
  18784. flush();
  18785. }
  18786. get layout() {
  18787. return this.$$.ctx[142];
  18788. }
  18789. set layout(layoutMode) {
  18790. this.$set({ layout: layoutMode });
  18791. flush();
  18792. }
  18793. get stores() {
  18794. return this.$$.ctx[143];
  18795. }
  18796. set stores(stores) {
  18797. this.$set({ stores });
  18798. flush();
  18799. }
  18800. get locale() {
  18801. return this.$$.ctx[2];
  18802. }
  18803. set locale(locale) {
  18804. this.$set({ locale });
  18805. flush();
  18806. }
  18807. get id() {
  18808. return this.$$.ctx[3];
  18809. }
  18810. set id(id) {
  18811. this.$set({ id });
  18812. flush();
  18813. }
  18814. get util() {
  18815. return this.$$.ctx[144];
  18816. }
  18817. set util(util) {
  18818. this.$set({ util });
  18819. flush();
  18820. }
  18821. get utils() {
  18822. return this.$$.ctx[145];
  18823. }
  18824. set utils(utils) {
  18825. this.$set({ utils });
  18826. flush();
  18827. }
  18828. get animations() {
  18829. return this.$$.ctx[146];
  18830. }
  18831. set animations(animations) {
  18832. this.$set({ animations });
  18833. flush();
  18834. }
  18835. get disabled() {
  18836. return this.$$.ctx[147];
  18837. }
  18838. set disabled(disabled) {
  18839. this.$set({ disabled });
  18840. flush();
  18841. }
  18842. get status() {
  18843. return this.$$.ctx[139];
  18844. }
  18845. set status(status) {
  18846. this.$set({ status });
  18847. flush();
  18848. }
  18849. get previewUpscale() {
  18850. return this.$$.ctx[148];
  18851. }
  18852. set previewUpscale(previewUpscale) {
  18853. this.$set({ previewUpscale });
  18854. flush();
  18855. }
  18856. get elasticityMultiplier() {
  18857. return this.$$.ctx[4];
  18858. }
  18859. set elasticityMultiplier(elasticityMultiplier) {
  18860. this.$set({ elasticityMultiplier });
  18861. flush();
  18862. }
  18863. get willRevert() {
  18864. return this.$$.ctx[149];
  18865. }
  18866. set willRevert(willRevert) {
  18867. this.$set({ willRevert });
  18868. flush();
  18869. }
  18870. get willProcessImage() {
  18871. return this.$$.ctx[150];
  18872. }
  18873. set willProcessImage(willProcessImage) {
  18874. this.$set({ willProcessImage });
  18875. flush();
  18876. }
  18877. get willRenderCanvas() {
  18878. return this.$$.ctx[5];
  18879. }
  18880. set willRenderCanvas(willRenderCanvas) {
  18881. this.$set({ willRenderCanvas });
  18882. flush();
  18883. }
  18884. get willRenderToolbar() {
  18885. return this.$$.ctx[151];
  18886. }
  18887. set willRenderToolbar(willRenderToolbar) {
  18888. this.$set({ willRenderToolbar });
  18889. flush();
  18890. }
  18891. get willSetHistoryInitialState() {
  18892. return this.$$.ctx[152];
  18893. }
  18894. set willSetHistoryInitialState(willSetHistoryInitialState) {
  18895. this.$set({ willSetHistoryInitialState });
  18896. flush();
  18897. }
  18898. get enableButtonExport() {
  18899. return this.$$.ctx[153];
  18900. }
  18901. set enableButtonExport(enableButtonExport) {
  18902. this.$set({ enableButtonExport });
  18903. flush();
  18904. }
  18905. get enableButtonRevert() {
  18906. return this.$$.ctx[154];
  18907. }
  18908. set enableButtonRevert(enableButtonRevert) {
  18909. this.$set({ enableButtonRevert });
  18910. flush();
  18911. }
  18912. get enableNavigateHistory() {
  18913. return this.$$.ctx[155];
  18914. }
  18915. set enableNavigateHistory(enableNavigateHistory) {
  18916. this.$set({ enableNavigateHistory });
  18917. flush();
  18918. }
  18919. get enableToolbar() {
  18920. return this.$$.ctx[6];
  18921. }
  18922. set enableToolbar(enableToolbar) {
  18923. this.$set({ enableToolbar });
  18924. flush();
  18925. }
  18926. get enableUtils() {
  18927. return this.$$.ctx[156];
  18928. }
  18929. set enableUtils(enableUtils) {
  18930. this.$set({ enableUtils });
  18931. flush();
  18932. }
  18933. get enableButtonClose() {
  18934. return this.$$.ctx[157];
  18935. }
  18936. set enableButtonClose(enableButtonClose) {
  18937. this.$set({ enableButtonClose });
  18938. flush();
  18939. }
  18940. get enableDropImage() {
  18941. return this.$$.ctx[158];
  18942. }
  18943. set enableDropImage(enableDropImage) {
  18944. this.$set({ enableDropImage });
  18945. flush();
  18946. }
  18947. get enablePasteImage() {
  18948. return this.$$.ctx[159];
  18949. }
  18950. set enablePasteImage(enablePasteImage) {
  18951. this.$set({ enablePasteImage });
  18952. flush();
  18953. }
  18954. get previewImageDataMaxSize() {
  18955. return this.$$.ctx[160];
  18956. }
  18957. set previewImageDataMaxSize(previewImageDataMaxSize) {
  18958. this.$set({ previewImageDataMaxSize });
  18959. flush();
  18960. }
  18961. get layoutDirectionPreference() {
  18962. return this.$$.ctx[161];
  18963. }
  18964. set layoutDirectionPreference(layoutDirectionPreference) {
  18965. this.$set({ layoutDirectionPreference });
  18966. flush();
  18967. }
  18968. get layoutHorizontalUtilsPreference() {
  18969. return this.$$.ctx[162];
  18970. }
  18971. set layoutHorizontalUtilsPreference(layoutHorizontalUtilsPreference) {
  18972. this.$set({ layoutHorizontalUtilsPreference });
  18973. flush();
  18974. }
  18975. get layoutVerticalUtilsPreference() {
  18976. return this.$$.ctx[163];
  18977. }
  18978. set layoutVerticalUtilsPreference(layoutVerticalUtilsPreference) {
  18979. this.$set({ layoutVerticalUtilsPreference });
  18980. flush();
  18981. }
  18982. get imagePreviewSrc() {
  18983. return this.$$.ctx[164];
  18984. }
  18985. set imagePreviewSrc(imagePreviewSrc) {
  18986. this.$set({ imagePreviewSrc });
  18987. flush();
  18988. }
  18989. get imageOrienter() {
  18990. return this.$$.ctx[165];
  18991. }
  18992. set imageOrienter(imageOrienter) {
  18993. this.$set({ imageOrienter });
  18994. flush();
  18995. }
  18996. get pluginComponents() {
  18997. return this.$$.ctx[166];
  18998. }
  18999. set pluginComponents(pluginComponents) {
  19000. this.$set({ pluginComponents });
  19001. flush();
  19002. }
  19003. get pluginOptions() {
  19004. return this.$$.ctx[7];
  19005. }
  19006. set pluginOptions(pluginOptions) {
  19007. this.$set({ pluginOptions });
  19008. flush();
  19009. }
  19010. get sub() {
  19011. return this.$$.ctx[167];
  19012. }
  19013. get pluginInterface() {
  19014. return this.$$.ctx[0];
  19015. }
  19016. get root() {
  19017. return this.$$.ctx[1];
  19018. }
  19019. set root(root) {
  19020. this.$set({ root });
  19021. flush();
  19022. }
  19023. get imageSourceToImageData() {
  19024. return this.$$.ctx[8];
  19025. }
  19026. set imageSourceToImageData(imageSourceToImageData) {
  19027. this.$set({ imageSourceToImageData });
  19028. flush();
  19029. }
  19030. get imagePreview() {
  19031. return this.$$.ctx[9];
  19032. }
  19033. get imagePreviewCurrent() {
  19034. return this.$$.ctx[140];
  19035. }
  19036. set imagePreviewCurrent(imagePreviewCurrent) {
  19037. this.$set({ imagePreviewCurrent });
  19038. flush();
  19039. }
  19040. get history() {
  19041. return this.$$.ctx[10];
  19042. }
  19043. }
  19044. // which props to filter out of exported props
  19045. const utilPrivateProps = ['klass', 'stores', 'isVisible', 'isActive', 'isActiveFraction', 'locale'];
  19046. const viewPrivateProps = [
  19047. // methods
  19048. 'history',
  19049. // props
  19050. 'klass',
  19051. 'stores',
  19052. 'navButtons',
  19053. 'pluginComponents',
  19054. 'pluginInterface',
  19055. 'pluginOptions',
  19056. 'sub',
  19057. 'imagePreviewSrc',
  19058. 'imagePreview',
  19059. 'imagePreviewCurrent',
  19060. ];
  19061. // view options array
  19062. let editorProps;
  19063. const pluginProps = new Set([]);
  19064. const propPluginRef = {};
  19065. // loops over plugins and registers all available options so we can define getters/setters
  19066. const pluginComponents = new Map();
  19067. const setEditorViewPlugins = (...args) => {
  19068. args.filter((plugin) => !!plugin.util).forEach((plugin) => {
  19069. const [id, Component] = plugin.util;
  19070. if (pluginComponents.has(id))
  19071. return;
  19072. pluginComponents.set(id, Component);
  19073. getComponentExportedProps(Component)
  19074. .filter((prop) => !utilPrivateProps.includes(prop))
  19075. .forEach((prop) => {
  19076. pluginProps.add(prop);
  19077. if (propPluginRef[prop]) {
  19078. propPluginRef[prop].push(id);
  19079. return;
  19080. }
  19081. propPluginRef[prop] = [id];
  19082. });
  19083. });
  19084. };
  19085. const getEditorViewProps = () => {
  19086. editorProps = new Set(getComponentExportedProps(Ui).filter((prop) => !viewPrivateProps.includes(prop)));
  19087. return [...editorProps, ...pluginProps];
  19088. };
  19089. const attachEditorView = (target, stores) => {
  19090. const accessors = {};
  19091. // creates the editor component instance
  19092. const editor = new Ui({
  19093. target,
  19094. props: {
  19095. stores,
  19096. pluginComponents: Array.from(pluginComponents),
  19097. },
  19098. });
  19099. // destroys the editor component instance
  19100. let isDestroyed = false;
  19101. const destroy = () => {
  19102. if (isDestroyed)
  19103. return;
  19104. if (isBrowser())
  19105. window.removeEventListener('pagehide', destroy);
  19106. if (!editor)
  19107. return;
  19108. isDestroyed = true;
  19109. editor.$destroy();
  19110. };
  19111. // set up accessors for editor props
  19112. if (!editorProps)
  19113. editorProps = new Set(getComponentExportedProps(Ui).filter((prop) => !viewPrivateProps.includes(prop)));
  19114. editorProps.forEach((prop) => {
  19115. Object.defineProperty(accessors, prop, {
  19116. get: () => editor[prop],
  19117. set: (value) => (editor[prop] = value),
  19118. });
  19119. });
  19120. // this reads the imagePreview store so third parties can interact with image data
  19121. Object.defineProperty(accessors, 'previewImageData', {
  19122. get: () => editor.imagePreviewCurrent,
  19123. });
  19124. // set up accessors for plugin props
  19125. pluginProps.forEach((prop) => {
  19126. const plugins = propPluginRef[prop];
  19127. const plugin = plugins[0]; // will always get value from first plugin, when plugins share a property the value will be in sync when set
  19128. Object.defineProperty(accessors, prop, {
  19129. get: () => editor.pluginInterface[plugin][prop],
  19130. set: (value) => {
  19131. const opts = plugins.reduce((prev, plugin) => {
  19132. prev[plugin] = {
  19133. ...editor.pluginOptions[plugin],
  19134. [prop]: value,
  19135. };
  19136. return prev;
  19137. }, {});
  19138. editor.pluginOptions = {
  19139. ...editor.pluginOptions,
  19140. ...opts,
  19141. };
  19142. },
  19143. });
  19144. });
  19145. // add `element` root query
  19146. Object.defineProperty(accessors, 'element', {
  19147. get: () => editor.root,
  19148. set: () => undefined,
  19149. });
  19150. // history shortcut
  19151. const history = editor.history;
  19152. defineMethods(accessors, {
  19153. on: (event, cb) => {
  19154. // exit if editor was destroyed, will return stub function so unsubs can be called without issues
  19155. if (isDestroyed)
  19156. return () => {
  19157. // Do nothing
  19158. };
  19159. // catch history events and route to history object
  19160. if (/undo|redo|revert/.test(event))
  19161. return history.on(event, cb);
  19162. // gather unsub methods
  19163. const unsubs = [
  19164. editor.sub(event, cb),
  19165. editor.$on(event, (e) => cb(e instanceof CustomEvent && !e.detail ? undefined : e)),
  19166. ].filter(Boolean);
  19167. // set up unsubscribe group
  19168. return () => unsubs.forEach((unsub) => unsub());
  19169. },
  19170. updateImagePreview: (src) => {
  19171. editor.imagePreviewSrc = src;
  19172. },
  19173. close: () => !isDestroyed && editor.pub('close'),
  19174. destroy,
  19175. });
  19176. Object.defineProperty(accessors, 'history', {
  19177. get: () => ({
  19178. undo: () => history.undo(),
  19179. redo: () => history.redo(),
  19180. revert: () => history.revert(),
  19181. get: () => history.get(),
  19182. set: (entries) => history.set(entries),
  19183. write: (state) => history.write(state),
  19184. get length() {
  19185. return history.length();
  19186. },
  19187. get index() {
  19188. return history.index;
  19189. },
  19190. }),
  19191. });
  19192. // clean up on window unload
  19193. if (isBrowser())
  19194. window.addEventListener('pagehide', destroy);
  19195. return accessors;
  19196. };
  19197. var editorEvents = [
  19198. // core editor events that should be re-dispatched
  19199. ...editorEventsToBubble,
  19200. // ui editor events
  19201. 'undo',
  19202. 'redo',
  19203. 'update',
  19204. 'revert',
  19205. 'destroy',
  19206. 'show',
  19207. 'hide',
  19208. 'close',
  19209. 'ready',
  19210. 'loadpreview',
  19211. 'selectshape',
  19212. 'updateshape',
  19213. 'addshape',
  19214. 'removeshape',
  19215. ];
  19216. const dispatchElementEvent = (target, event, detail) => target.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, cancelable: true }));
  19217. var dispatchEditorEvents = (editor, handler, options = {}) => {
  19218. const { prefix = 'pintura:' } = options;
  19219. return editorEvents.map((event) => editor.on(event, (value) => isElement(handler)
  19220. ? dispatchElementEvent(handler, `${prefix}${event}`, value)
  19221. : handler(event, value)));
  19222. };
  19223. var arrayInsert = (array, index, item) => {
  19224. array.splice(index, 0, item);
  19225. return array;
  19226. };
  19227. // first index is always id, so if is string, it's a node
  19228. const isNode = (item) => isString(item[0]);
  19229. // if it's not a node, it's a nodelist
  19230. const isNodeList = (item) => !isNode(item);
  19231. const getNodeId = (node) => node[1];
  19232. const getNodeChildren = (node) => node[3] || [];
  19233. function createNode(instance, id, props, children) {
  19234. // if three arguments received, props can be children
  19235. if (Array.isArray(props)) {
  19236. children = props;
  19237. props = {};
  19238. }
  19239. // node is always array of four entries
  19240. return [instance, id, props || {}, children || []];
  19241. }
  19242. const insertNode = (node, needle, haystack, getIndex = (index) => index) => {
  19243. const nodeList = findNodeList(needle, haystack);
  19244. const targetIndex = nodeList.findIndex((item) => getNodeId(item) === needle);
  19245. arrayInsert(nodeList, getIndex(targetIndex), node);
  19246. };
  19247. const insertNodeBefore = (node, needle, haystack) => insertNode(node, needle, haystack);
  19248. const insertNodeAfter = (node, needle, haystack) => insertNode(node, needle, haystack, (index) => index + 1);
  19249. const appendNode = (node, haystack) => {
  19250. // if is list, add to list
  19251. if (isNodeList(haystack))
  19252. return haystack.push(node);
  19253. // else it's a node, add to node children
  19254. haystack[3] = [...getNodeChildren(haystack), node];
  19255. };
  19256. const removeNode = (needle, haystack) => {
  19257. const nodeList = findNodeList(needle, haystack);
  19258. arrayRemove(nodeList, (item) => getNodeId(item) === needle);
  19259. return nodeList;
  19260. };
  19261. const findNode = (needle, haystack) => {
  19262. return isNode(haystack)
  19263. ? // haystack is a node, maybe node is a match or one of children is a match
  19264. getNodeId(haystack) === needle
  19265. ? haystack
  19266. : findNode(needle, getNodeChildren(haystack))
  19267. : // haystack is a list of nodes
  19268. haystack.find((item) => findNode(needle, item));
  19269. };
  19270. const findNodeList = (needle, haystack) => {
  19271. // haystack is node list
  19272. if (isNodeList(haystack)) {
  19273. // lets search nodes in this haystack
  19274. if (haystack.find((item) => getNodeId(item) === needle))
  19275. return haystack;
  19276. // not found, lets move the search to the childnodes
  19277. return haystack.find((item) => findNodeList(needle, getNodeChildren(item)));
  19278. }
  19279. // is node, lets find in children
  19280. return findNodeList(needle, getNodeChildren(haystack));
  19281. };
  19282. //#region markup
  19283. const propertyMap = {
  19284. borderColor: 'strokeColor',
  19285. borderWidth: 'strokeWidth',
  19286. lineWidth: 'strokeWidth',
  19287. fontColor: 'color',
  19288. lineColor: 'strokeColor',
  19289. src: 'backgroundImage',
  19290. fit: 'backgroundSize',
  19291. };
  19292. const convertValue = (value) => {
  19293. if (value === 0)
  19294. return 0;
  19295. if (value === '0%')
  19296. return 0;
  19297. if (value === '0px')
  19298. return 0;
  19299. if (/px$/.test(value))
  19300. return parseInt(value, 10);
  19301. if (/\%$/.test(value))
  19302. return value;
  19303. if (value <= 1)
  19304. return `${value * 100}%`;
  19305. };
  19306. const addValues = (a, b) => {
  19307. let _a, _b;
  19308. if (/%$/.test(a)) {
  19309. _a = parseFloat(a);
  19310. _b = parseFloat(b);
  19311. return `${_a + _b}%`;
  19312. }
  19313. if (/px$/.test(a)) {
  19314. _a = parseInt(a, 10);
  19315. _b = parseInt(b, 10);
  19316. return `${_a + _b}px`;
  19317. }
  19318. };
  19319. const shapeFromLegacyMarkup = (crop, type, style) => {
  19320. const shape = Object.keys(style).reduce((res, prop) => {
  19321. let value = style[prop];
  19322. // rename prop
  19323. prop = propertyMap[prop] || prop;
  19324. // if is px value
  19325. if (/px$/.test(value)) {
  19326. value = convertValue(value);
  19327. }
  19328. // if is number convert to percentage
  19329. else if (/^(?:x|y|left|right|top|bottom|width|height|fontSize|strokeWidth)$/.test(prop) &&
  19330. typeof value === 'number') {
  19331. if (/strokeWidth/.test(prop))
  19332. value *= 2;
  19333. value = convertValue(value);
  19334. }
  19335. // if is color value
  19336. if (/color/i.test(prop)) {
  19337. value = colorStringToColorArray(value);
  19338. }
  19339. if (value === null)
  19340. value = undefined;
  19341. res[prop] = value;
  19342. return res;
  19343. }, {});
  19344. if (type === 'line') {
  19345. if (shape.lineDecoration.length === 1)
  19346. shape.lineEnd = 'arrow';
  19347. if (shape.lineDecoration.length === 2)
  19348. shape.lineStart = 'arrow';
  19349. shape.x1 = shape.x;
  19350. shape.y1 = shape.y;
  19351. shape.x2 = addValues(shape.x, shape.width);
  19352. shape.y2 = addValues(shape.y, shape.height);
  19353. delete shape.x;
  19354. delete shape.y;
  19355. delete shape.width;
  19356. delete shape.height;
  19357. delete shape.lineDecoration;
  19358. delete shape.lineStyle;
  19359. }
  19360. if (type === 'text') {
  19361. shape.y = addValues(shape.y, '-' + shape.fontSize);
  19362. delete shape.width;
  19363. delete shape.height;
  19364. delete shape.borderStyle;
  19365. }
  19366. if (type === 'ellipse') {
  19367. let w, h;
  19368. // calculate `rx` and `ry` based on `width` and `h`eight`
  19369. if (/%$/.test(shape.width)) {
  19370. w = parseFloat(shape.width) / 100;
  19371. h = parseFloat(shape.height) / 100;
  19372. const widthAbsolute = w * crop.width;
  19373. const heightAbsolute = h * crop.height;
  19374. w = (widthAbsolute / crop.width) * 100;
  19375. h = (heightAbsolute / crop.height) * 100;
  19376. }
  19377. else {
  19378. w = shape.width;
  19379. h = shape.height;
  19380. }
  19381. shape.rx = w * 0.5;
  19382. shape.ry = h * 0.5;
  19383. if (/%$/.test(shape.width)) {
  19384. shape.rx += '%';
  19385. shape.ry += '%';
  19386. }
  19387. shape.x = addValues(shape.x, shape.rx);
  19388. shape.y = addValues(shape.y, shape.ry);
  19389. delete shape.width;
  19390. delete shape.height;
  19391. delete shape.borderStyle;
  19392. }
  19393. if (type === 'rect') {
  19394. delete shape.borderStyle;
  19395. }
  19396. if (type === 'path') {
  19397. shape.points = shape.points.map((point) => {
  19398. return {
  19399. x: convertValue(point.x),
  19400. y: convertValue(point.y),
  19401. };
  19402. });
  19403. }
  19404. return shape;
  19405. };
  19406. //#endregion
  19407. //#region crop
  19408. const getOffsetPointOnEdge = (length, rotation) => {
  19409. const a = length;
  19410. const A = 1.5707963267948966;
  19411. const B = rotation;
  19412. const C = 1.5707963267948966 - rotation;
  19413. const sinA = Math.sin(A);
  19414. const sinB = Math.sin(B);
  19415. const sinC = Math.sin(C);
  19416. const cosC = Math.cos(C);
  19417. const ratio = a / sinA;
  19418. const b = ratio * sinB;
  19419. const c = ratio * sinC;
  19420. return vectorCreate(cosC * b, cosC * c);
  19421. };
  19422. const getRotatedRectSize = (rect, rotation) => {
  19423. const w = rect.width;
  19424. const h = rect.height;
  19425. const hor = getOffsetPointOnEdge(w, rotation);
  19426. const ver = getOffsetPointOnEdge(h, rotation);
  19427. const tl = vectorCreate(rect.x + Math.abs(hor.x), rect.y - Math.abs(hor.y));
  19428. const tr = vectorCreate(rect.x + rect.width + Math.abs(ver.y), rect.y + Math.abs(ver.x));
  19429. const bl = vectorCreate(rect.x - Math.abs(ver.y), rect.y + rect.height - Math.abs(ver.x));
  19430. return {
  19431. width: vectorDistance(tl, tr),
  19432. height: vectorDistance(tl, bl),
  19433. };
  19434. };
  19435. const getBoundsAroundCenter = (imageSize, center) => {
  19436. const cx = center.x > 0.5 ? 1 - center.x : center.x;
  19437. const cy = center.y > 0.5 ? 1 - center.y : center.y;
  19438. return sizeCreate(cx * 2 * imageSize.width, cy * 2 * imageSize.height);
  19439. };
  19440. const getCanvasSize = (imageSize, canvasAspectRatio, zoom = 1) => {
  19441. const imageAspectRatio = imageSize.height / imageSize.width;
  19442. // determine actual pixels on x and y axis
  19443. let canvasWidth = 1;
  19444. let canvasHeight = canvasAspectRatio;
  19445. let imgWidth = 1;
  19446. let imgHeight = imageAspectRatio;
  19447. if (imgHeight > canvasHeight) {
  19448. imgHeight = canvasHeight;
  19449. imgWidth = imgHeight / imageAspectRatio;
  19450. }
  19451. const scalar = Math.max(canvasWidth / imgWidth, canvasHeight / imgHeight);
  19452. const width = imageSize.width / (zoom * scalar * imgWidth);
  19453. const height = width * canvasAspectRatio;
  19454. return {
  19455. width: width,
  19456. height: height,
  19457. };
  19458. };
  19459. const getCenteredCropRect = (imageSize, aspectRatio) => {
  19460. let width = imageSize.width;
  19461. let height = width * aspectRatio;
  19462. if (height > imageSize.height) {
  19463. height = imageSize.height;
  19464. width = height / aspectRatio;
  19465. }
  19466. const x = (imageSize.width - width) * 0.5;
  19467. const y = (imageSize.height - height) * 0.5;
  19468. return rectCreate(x, y, width, height);
  19469. };
  19470. const getCorrectedLegacyAspectRatio = (imageSize, aspectRatio) => aspectRatio != null
  19471. ? // fox the aspect ratio
  19472. 1 / aspectRatio
  19473. : // set image aspect ratio
  19474. imageSize.width / imageSize.height;
  19475. const imagePropertiesFromLegacyCrop = (imageSize, { flip, aspectRatio, rotation, center, zoom, scaleToFit }) => {
  19476. const res = {};
  19477. // is centered crop
  19478. const isCenteredCrop = !center || (center && center.x === 0.5 && center.y === 0.5);
  19479. // handle basic props
  19480. if (flip && flip.horizontal)
  19481. res.flipHorizontal = flip.horizontal;
  19482. if (flip && flip.vertical)
  19483. res.flipVertical = flip.vertical;
  19484. // fix aspect ratio, in FilePond and editor v6 it's height/width instead of width/height
  19485. const correctedAspectRatio = getCorrectedLegacyAspectRatio(imageSize, aspectRatio);
  19486. // image bounds
  19487. const cropLimit = !(scaleToFit === false);
  19488. const canvasSize = getCanvasSize(imageSize, aspectRatio, zoom);
  19489. const cropSize = isCenteredCrop
  19490. ? imageSize
  19491. : getBoundsAroundCenter(imageSize, cropLimit ? center : { x: 0.5, y: 0.5 });
  19492. const cropCentered = getCenteredCropRect(imageSize, aspectRatio);
  19493. // has different aspect ratio than image
  19494. if (aspectRatio || !isCenteredCrop || zoom) {
  19495. res.crop = rectContainRect(rectCreateFromSize(cropSize), correctedAspectRatio);
  19496. }
  19497. if (typeof rotation === 'number' && rotation !== null) {
  19498. if (rotation != null)
  19499. res.rotation = rotation;
  19500. const rotatedCropSize = getRotatedRectSize(cropCentered, rotation);
  19501. const scalar = Math.max(rotatedCropSize.width / cropSize.width, rotatedCropSize.height / cropSize.height);
  19502. // crop position in non-rotated image
  19503. const cropCenter = vectorCreate(center.x * imageSize.width, center.y * imageSize.height);
  19504. // const imageCenter = sizeCenter(imageSize);
  19505. // const imageCenterToCropCenter = vectorCreate(
  19506. // imageCenter.x - cropCenter.x,
  19507. // imageCenter.y - cropCenter.y
  19508. // );
  19509. // get rotated image center
  19510. const rotatedImageSize = getImageTransformedRect(imageSize, rotation);
  19511. const rotatedImageCenter = sizeCenter(rotatedImageSize);
  19512. const rotatedImageOffset = vectorCreate((rotatedImageSize.width - imageSize.width) * 0.5, (rotatedImageSize.height - imageSize.height) * 0.5);
  19513. // window.draw(rotatedImageCenter, 'red');
  19514. // window.draw(rotatedImageSize, 'red');
  19515. // window.draw(
  19516. // {
  19517. // x: rotatedImageOffset.x,
  19518. // y: rotatedImageOffset.y,
  19519. // width: imageSize.width,
  19520. // height: imageSize.height,
  19521. // },
  19522. // 'cyan'
  19523. // );
  19524. // const imagePoints = rectRotate(
  19525. // rectCreate(
  19526. // rotatedImageOffset.x,
  19527. // rotatedImageOffset.y,
  19528. // imageSize.width,
  19529. // imageSize.height
  19530. // ),
  19531. // rotation
  19532. // );
  19533. // window.draw(imagePoints, 'orange');
  19534. const cropPoints = rectRotate({
  19535. x: rotatedImageOffset.x + cropCenter.x - (canvasSize.width / scalar) * 0.5,
  19536. y: rotatedImageOffset.y + cropCenter.y - (canvasSize.height / scalar) * 0.5,
  19537. width: canvasSize.width / scalar,
  19538. height: canvasSize.height / scalar,
  19539. }, rotation);
  19540. // window.draw(cropPoints, 'cyan');
  19541. const cropBoundsPoints = vectorsRotate(cropPoints.map(vectorClone), rotation, rotatedImageCenter.x, rotatedImageCenter.y);
  19542. // window.draw(cropBoundsPoints, 'orange');
  19543. const cropBoundsPointsCenter = rectCenter(rectCreateFromPoints(cropBoundsPoints));
  19544. // window.draw(cropBoundsPointsCenter, 'green');
  19545. const deRotatedCropBoundsPoints = vectorsRotate(cropBoundsPoints.map(vectorClone), -(rotation * 2), cropBoundsPointsCenter.x, cropBoundsPointsCenter.y);
  19546. // window.draw(deRotatedCropBoundsPoints, 'green');
  19547. res.crop = rectCreateFromPoints(deRotatedCropBoundsPoints);
  19548. }
  19549. else if (zoom != null) {
  19550. rectScale(res.crop, 1 / zoom);
  19551. }
  19552. if (!cropLimit) {
  19553. res.cropLimitToImage = false;
  19554. }
  19555. return res;
  19556. };
  19557. //#endregion
  19558. const isLegacyData = (data = {}) => {
  19559. if ('markup' in data || 'color' in data || 'filter' in data)
  19560. return true;
  19561. const { crop } = data;
  19562. if (crop && ('flip' in crop || 'center' in crop || 'aspectRatio' in crop || 'rotation' in crop))
  19563. return true;
  19564. return false;
  19565. };
  19566. var legacyDataToImageState = (editor, imageSize, data = {}) => {
  19567. const res = {};
  19568. // test if isn't legacy data
  19569. if (!isLegacyData(data))
  19570. return data;
  19571. if (data.crop) {
  19572. Object.assign(res, imagePropertiesFromLegacyCrop(imageSize, data.crop));
  19573. }
  19574. if (data.markup) {
  19575. const markup = Array.isArray(data.markup) ? data.markup : Object.values(data.markup);
  19576. res.decoration = markup.map((markup) => shapeFromLegacyMarkup(res.crop || imageSize, markup[0], markup[1]));
  19577. }
  19578. if (data.color) {
  19579. Object.keys(data.color)
  19580. .filter((key) => data.color[key])
  19581. .map((key) => [
  19582. key,
  19583. Array.isArray(data.color[key].matrix)
  19584. ? data.color[key].matrix
  19585. : Object.values(data.color[key].matrix),
  19586. ])
  19587. .forEach(([key, value]) => {
  19588. if (!res.colorMatrix)
  19589. res.colorMatrix = {};
  19590. res.colorMatrix[key] = value;
  19591. });
  19592. }
  19593. if (data.filter) {
  19594. if (!res.colorMatrix)
  19595. res.colorMatrix = {};
  19596. res.colorMatrix.filter =
  19597. typeof data.filter === 'string' && editor['filterFunctions'][data.filter]
  19598. ? editor['filterFunctions'][data.filter]()
  19599. : data.filter.matrix;
  19600. }
  19601. return res;
  19602. };
  19603. const isOperaMini = () => Object.prototype.toString.call(window['operamini']) === '[object OperaMini]';
  19604. const hasPromises = () => 'Promise' in window;
  19605. const hasCreateObjectURL = () => 'URL' in window && 'createObjectURL' in window.URL;
  19606. const hasVisibility = () => 'visibilityState' in document;
  19607. const hasTiming = () => 'performance' in window; // iOS 8.x
  19608. const hasFileConstructor = () => 'File' in window; // excludes IE11
  19609. let result$3 = null;
  19610. var isModernBrowser = () => {
  19611. if (result$3 === null)
  19612. result$3 =
  19613. isBrowser() &&
  19614. // Can't run on Opera Mini due to lack of everything
  19615. !isOperaMini() &&
  19616. // Require these APIs to feature detect a modern browser
  19617. hasVisibility() &&
  19618. hasPromises() &&
  19619. hasFileConstructor() &&
  19620. hasCreateObjectURL() &&
  19621. hasTiming();
  19622. return result$3;
  19623. };
  19624. var toPercentageNumber = (v) => Math.round(v * 100);
  19625. const brightness = {
  19626. base: 0,
  19627. min: -0.25,
  19628. max: 0.25,
  19629. getLabel: (value) => toPercentageNumber(value / 0.25),
  19630. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19631. getValue: (store) => {
  19632. if (!store.brightness)
  19633. return;
  19634. return store.brightness[4];
  19635. },
  19636. setValue: (store, v) => store.update((matrices) => ({
  19637. // clone existing matrices
  19638. ...matrices,
  19639. // prettier-ignore
  19640. brightness: [
  19641. 1, 0, 0, 0, v,
  19642. 0, 1, 0, 0, v,
  19643. 0, 0, 1, 0, v,
  19644. 0, 0, 0, 1, 0
  19645. ],
  19646. })),
  19647. };
  19648. const contrast = {
  19649. base: 1,
  19650. min: 0.5,
  19651. max: 1.5,
  19652. getLabel: (value) => toPercentageNumber(-1 + (value - 0.5) * 2),
  19653. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19654. getValue: (store) => {
  19655. if (!store.contrast)
  19656. return;
  19657. return store.contrast[0];
  19658. },
  19659. setValue: (store, v) => store.update((matrices) => ({
  19660. // clone existing matrices
  19661. ...matrices,
  19662. // prettier-ignore
  19663. contrast: [
  19664. v, 0, 0, 0, .5 * (1 - v),
  19665. 0, v, 0, 0, .5 * (1 - v),
  19666. 0, 0, v, 0, .5 * (1 - v),
  19667. 0, 0, 0, 1, 0
  19668. ],
  19669. })),
  19670. };
  19671. const saturation = {
  19672. base: 1,
  19673. min: 0,
  19674. max: 2,
  19675. getLabel: (value) => toPercentageNumber(value - 1),
  19676. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19677. getValue: (store) => {
  19678. if (!store.saturation)
  19679. return;
  19680. return (store.saturation[0] - 0.213) / 0.787;
  19681. },
  19682. setValue: (store, v) => store.update((matrices) => ({
  19683. ...matrices,
  19684. // prettier-ignore
  19685. saturation: [
  19686. .213 + .787 * v, .715 - .715 * v, .072 - .072 * v, 0, 0,
  19687. .213 - .213 * v, .715 + .285 * v, .072 - .072 * v, 0, 0,
  19688. .213 - .213 * v, .715 - .715 * v, .072 + .928 * v, 0, 0,
  19689. 0, 0, 0, 1, 0
  19690. ],
  19691. })),
  19692. };
  19693. const exposure = {
  19694. base: 1,
  19695. min: 0.5,
  19696. max: 1.5,
  19697. getLabel: (value) => toPercentageNumber(-1 + (value - 0.5) * 2),
  19698. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19699. getValue: (store) => {
  19700. if (!store.exposure)
  19701. return;
  19702. return store.exposure[0];
  19703. },
  19704. setValue: (store, v) => store.update((matrices) => ({
  19705. ...matrices,
  19706. // prettier-ignore
  19707. exposure: [
  19708. v, 0, 0, 0, 0,
  19709. 0, v, 0, 0, 0,
  19710. 0, 0, v, 0, 0,
  19711. 0, 0, 0, 1, 0
  19712. ],
  19713. })),
  19714. };
  19715. const gamma = {
  19716. base: 1,
  19717. min: 0.15,
  19718. max: 4,
  19719. getLabel: (value) => {
  19720. if (value < 1) {
  19721. return toPercentageNumber((value - 0.15) / 0.85 - 1);
  19722. }
  19723. return toPercentageNumber((value - 1) / 3);
  19724. },
  19725. getStore: ({ imageGamma }) => imageGamma,
  19726. };
  19727. const vignette = {
  19728. base: 0,
  19729. min: -1,
  19730. max: 1,
  19731. getStore: ({ imageVignette }) => imageVignette,
  19732. };
  19733. const clarity = {
  19734. base: 0,
  19735. min: -1,
  19736. max: 1,
  19737. getStore: ({ imageConvolutionMatrix }) => imageConvolutionMatrix,
  19738. getValue: (store) => {
  19739. if (!store.clarity)
  19740. return;
  19741. if (store.clarity[0] === 0) {
  19742. return store.clarity[1] / -1;
  19743. }
  19744. else {
  19745. return store.clarity[1] / -2;
  19746. }
  19747. },
  19748. setValue: (store, v) => {
  19749. store.update((matrices) => ({
  19750. ...matrices,
  19751. // prettier-ignore
  19752. clarity: v >= 0
  19753. ? [0, -1 * v, 0,
  19754. -1 * v, 1 + 4 * v, -1 * v,
  19755. 0, -1 * v, 0
  19756. ]
  19757. : [-1 * v, -2 * v, -1 * v,
  19758. -2 * v, 1 + -3 * v, -2 * v,
  19759. -1 * v, -2 * v, -1 * v
  19760. ],
  19761. }));
  19762. },
  19763. };
  19764. const temperature = {
  19765. base: 0,
  19766. min: -1,
  19767. max: 1,
  19768. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19769. getValue: (store) => {
  19770. if (!store.temperature)
  19771. return;
  19772. const v = store.temperature[0];
  19773. if (v >= 1) {
  19774. return (v - 1) / 0.1;
  19775. }
  19776. return (1 - v) / -0.15;
  19777. },
  19778. setValue: (store, v) => store.update((matrices) => ({
  19779. ...matrices,
  19780. // prettier-ignore
  19781. temperature: v > 0 ? [
  19782. 1 + (v * .1), 0, 0, 0, 0,
  19783. 0, 1, 0, 0, 0,
  19784. 0, 0, 1 + (-v * .1), 0, 0,
  19785. 0, 0, 0, 1, 0
  19786. ] : [
  19787. 1 + (v * .15), 0, 0, 0, 0,
  19788. 0, 1 + (v * .05), 0, 0, 0,
  19789. 0, 0, 1 + (-v * .15), 0, 0,
  19790. 0, 0, 0, 1, 0
  19791. ],
  19792. })),
  19793. };
  19794. const finetuneControlConfigurationDefault = {
  19795. gamma,
  19796. brightness,
  19797. contrast,
  19798. saturation,
  19799. exposure,
  19800. temperature,
  19801. clarity,
  19802. vignette,
  19803. };
  19804. const finetuneOptionsDefault = [
  19805. ['brightness', (locale) => locale.finetuneLabelBrightness],
  19806. ['contrast', (locale) => locale.finetuneLabelContrast],
  19807. ['saturation', (locale) => locale.finetuneLabelSaturation],
  19808. ['exposure', (locale) => locale.finetuneLabelExposure],
  19809. ['temperature', (locale) => locale.finetuneLabelTemperature],
  19810. ['gamma', (locale) => locale.finetuneLabelGamma],
  19811. !isSoftwareRendering() && ['clarity', (locale) => locale.finetuneLabelClarity],
  19812. ['vignette', (locale) => locale.finetuneLabelVignette],
  19813. ].filter(Boolean);
  19814. var _plugin_finetune_defaults = {
  19815. finetuneControlConfiguration: finetuneControlConfigurationDefault,
  19816. finetuneOptions: finetuneOptionsDefault,
  19817. };
  19818. /*
  19819. TODO: fix inverse fn in getValue
  19820. export const hue = {
  19821. base: 0,
  19822. min: 0,
  19823. max: Math.PI,
  19824. getStore: ({ imageColorMatrix }) => imageColorMatrix,
  19825. getValue: (store) => {
  19826. if (!store.hue) return;
  19827. const v = store.hue[1];
  19828. const o = -(Math.acos((0.715 - v) / Math.sqrt(2) / 0.715) - Math.PI / 4);
  19829. return o;
  19830. },
  19831. setValue: (store, v: number) => {
  19832. store.update((matrices) => {
  19833. // const value = v * (Math.PI);
  19834. const cos = Math.cos(v);
  19835. const sin = Math.sin(v);
  19836. const a00 = 0.213 + cos * 0.787 - sin * 0.213;
  19837. const a01 = 0.715 - cos * 0.715 - sin * 0.715;
  19838. const a02 = 0.072 - cos * 0.072 + sin * 0.928;
  19839. const a10 = 0.213 - cos * 0.213 + sin * 0.143;
  19840. const a11 = 0.715 + cos * 0.285 + sin * 0.14;
  19841. const a12 = 0.072 - cos * 0.072 - sin * 0.283;
  19842. const a20 = 0.213 - cos * 0.213 - sin * 0.787;
  19843. const a21 = 0.715 - cos * 0.715 + sin * 0.715;
  19844. const a22 = 0.072 + cos * 0.928 + sin * 0.072;
  19845. return {
  19846. ...matrices,
  19847. // prettier-ignore
  19848. hue: [
  19849. a00, a01, a02, 0, 0,
  19850. a10, a11, a12, 0, 0,
  19851. a20, a21, a22, 0, 0,
  19852. 0, 0, 0, 1, 0,
  19853. ]
  19854. };
  19855. });
  19856. },
  19857. };
  19858. */
  19859. const pastel = () =>
  19860. // prettier-ignore
  19861. [
  19862. 0.75, 0.25, 0.25, 0, 0,
  19863. 0.25, 0.75, 0.25, 0, 0,
  19864. 0.25, 0.25, 0.75, 0, 0,
  19865. 0, 0, 0, 1, 0
  19866. ];
  19867. const chrome = () =>
  19868. // prettier-ignore
  19869. [
  19870. 1.398, -0.316, 0.065, -0.273, 0.201,
  19871. -0.051, 1.278, -0.080, -0.273, 0.201,
  19872. -0.051, 0.119, 1.151, -0.290, 0.215,
  19873. 0, 0, 0, 1, 0
  19874. ];
  19875. const fade = () =>
  19876. // prettier-ignore
  19877. [
  19878. 1.073, -0.015, 0.092, -0.115, -0.017,
  19879. 0.107, 0.859, 0.184, -0.115, -0.017,
  19880. 0.015, 0.077, 1.104, -0.115, -0.017,
  19881. 0, 0, 0, 1, 0
  19882. ];
  19883. const warm = () =>
  19884. // prettier-ignore
  19885. [
  19886. 1.06, 0, 0, 0, 0,
  19887. 0, 1.01, 0, 0, 0,
  19888. 0, 0, 0.93, 0, 0,
  19889. 0, 0, 0, 1, 0,
  19890. ];
  19891. const cold = () =>
  19892. // prettier-ignore
  19893. [
  19894. 1.1, 0, 0, 0, -.1,
  19895. 0, 1.1, 0, 0, -.1,
  19896. 0, 0, 1.2, 0, -.1,
  19897. 0, 0, 0, 1, 0,
  19898. ];
  19899. const invert = () =>
  19900. // prettier-ignore
  19901. [
  19902. -1, 0, 0, 1, 0,
  19903. 0, -1, 0, 1, 0,
  19904. 0, 0, -1, 1, 0,
  19905. 0, 0, 0, 1, 0,
  19906. ];
  19907. const monoDefault = () =>
  19908. // prettier-ignore
  19909. [
  19910. 0.212, 0.715, 0.114, 0, 0,
  19911. 0.212, 0.715, 0.114, 0, 0,
  19912. 0.212, 0.715, 0.114, 0, 0,
  19913. 0, 0, 0, 1, 0
  19914. ];
  19915. const monoNoir = () =>
  19916. // prettier-ignore
  19917. [
  19918. 0.15, 1.3, -0.25, 0.1, -0.2,
  19919. 0.15, 1.3, -0.25, 0.1, -0.2,
  19920. 0.15, 1.3, -0.25, 0.1, -0.2,
  19921. 0, 0, 0, 1, 0
  19922. ];
  19923. const monoWash = () =>
  19924. // prettier-ignore
  19925. [
  19926. 0.163, 0.518, 0.084, -0.010, 0.208,
  19927. 0.163, 0.529, 0.082, -0.020, 0.210,
  19928. 0.171, 0.529, 0.084, 0.000, 0.214,
  19929. 0.000, 0.000, 0.000, 1.000, 0.000,
  19930. ];
  19931. const monoStark = () =>
  19932. // prettier-ignore
  19933. [
  19934. 0.338, 0.991, 0.117, 0.093, -0.196,
  19935. 0.302, 1.049, 0.096, 0.078, -0.196,
  19936. 0.286, 1.016, 0.146, 0.101, -0.196,
  19937. 0.000, 0.000, 0.000, 1.000, 0.000,
  19938. ];
  19939. const sepiaDefault = () =>
  19940. // prettier-ignore
  19941. [
  19942. 0.393, 0.768, 0.188, 0, 0,
  19943. 0.349, 0.685, 0.167, 0, 0,
  19944. 0.272, 0.533, 0.130, 0, 0,
  19945. 0, 0, 0, 1, 0,
  19946. ];
  19947. const sepiaBlues = () =>
  19948. // prettier-ignore
  19949. [
  19950. 0.289, 0.620, 0.185, 0.000, 0.077,
  19951. 0.257, 0.566, 0.163, 0.000, 0.115,
  19952. 0.200, 0.430, 0.128, 0.000, 0.188,
  19953. 0.000, 0.000, 0.000, 1.000, 0.000,
  19954. ];
  19955. const sepiaRust = () =>
  19956. // prettier-ignore
  19957. [
  19958. 0.269, 0.764, 0.172, 0.050, 0.100,
  19959. 0.239, 0.527, 0.152, 0.000, 0.176,
  19960. 0.186, 0.400, 0.119, 0.000, 0.159,
  19961. 0.000, 0.000, 0.000, 1.000, 0.000,
  19962. ];
  19963. const sepiaColor = () =>
  19964. // prettier-ignore
  19965. [
  19966. 0.547, 0.764, 0.134, 0.000, -0.147,
  19967. 0.281, 0.925, 0.120, 0.000, -0.135,
  19968. 0.225, 0.558, 0.330, 0.000, -0.113,
  19969. 0.000, 0.000, 0.000, 1.000, 0.000,
  19970. ];
  19971. //
  19972. // default filter set
  19973. //
  19974. const filterFunctionsDefault = {
  19975. chrome,
  19976. fade,
  19977. pastel,
  19978. cold,
  19979. warm,
  19980. monoDefault,
  19981. monoWash,
  19982. monoNoir,
  19983. monoStark,
  19984. sepiaDefault,
  19985. sepiaRust,
  19986. sepiaBlues,
  19987. sepiaColor,
  19988. };
  19989. const filterOptionsDefault = [
  19990. ['Default', [[undefined, (locale) => locale.labelDefault]]],
  19991. [
  19992. 'Classic',
  19993. [
  19994. ['chrome', (locale) => locale.filterLabelChrome],
  19995. ['fade', (locale) => locale.filterLabelFade],
  19996. ['cold', (locale) => locale.filterLabelCold],
  19997. ['warm', (locale) => locale.filterLabelWarm],
  19998. ['pastel', (locale) => locale.filterLabelPastel],
  19999. ],
  20000. ],
  20001. [
  20002. 'Monochrome',
  20003. [
  20004. ['monoDefault', (locale) => locale.filterLabelMonoDefault],
  20005. ['monoNoir', (locale) => locale.filterLabelMonoNoir],
  20006. ['monoStark', (locale) => locale.filterLabelMonoStark],
  20007. ['monoWash', (locale) => locale.filterLabelMonoWash],
  20008. ],
  20009. ],
  20010. [
  20011. 'Sepia',
  20012. [
  20013. ['sepiaDefault', (locale) => locale.filterLabelSepiaDefault],
  20014. ['sepiaRust', (locale) => locale.filterLabelSepiaRust],
  20015. ['sepiaBlues', (locale) => locale.filterLabelSepiaBlues],
  20016. ['sepiaColor', (locale) => locale.filterLabelSepiaColor],
  20017. ],
  20018. ],
  20019. ];
  20020. var _plugin_filter_defaults = {
  20021. filterFunctions: filterFunctionsDefault,
  20022. filterOptions: filterOptionsDefault,
  20023. };
  20024. const solidSharp = {
  20025. shape: {
  20026. frameStyle: 'solid',
  20027. frameSize: '2.5%',
  20028. },
  20029. thumb: '<rect stroke-width="5" x="0" y="0" width="100%" height="100%"/>',
  20030. };
  20031. const solidRound = {
  20032. shape: {
  20033. frameStyle: 'solid',
  20034. frameSize: '2.5%',
  20035. frameRound: true,
  20036. },
  20037. thumb: '<rect stroke-width="5" x="0" y="0" width="100%" height="100%" rx="12%"/>',
  20038. };
  20039. const lineSingle = {
  20040. shape: {
  20041. frameStyle: 'line',
  20042. frameInset: '2.5%',
  20043. frameSize: '.3125%',
  20044. frameRadius: 0,
  20045. },
  20046. thumb: '<div style="top:.5em;left:.5em;right:.5em;bottom:.5em;box-shadow:inset 0 0 0 1px currentColor"></div>',
  20047. };
  20048. const lineMultiple = {
  20049. shape: {
  20050. frameStyle: 'line',
  20051. frameAmount: 2,
  20052. frameInset: '2.5%',
  20053. frameSize: '.3125%',
  20054. frameOffset: '1.25%',
  20055. frameRadius: 0,
  20056. },
  20057. thumb: '<div style="top:.75em;left:.75em;right:.75em;bottom:.75em; outline: 3px double"></div>',
  20058. };
  20059. const edgeSeparate = {
  20060. shape: {
  20061. frameStyle: 'edge',
  20062. frameInset: '2.5%',
  20063. frameOffset: '5%',
  20064. frameSize: '.3125%',
  20065. },
  20066. thumb: '<div style="top:.75em;left:.5em;bottom:.75em;border-left:1px solid"></div><div style="top:.75em;right:.5em;bottom:.75em;border-right:1px solid"></div><div style="top:.5em;left:.75em;right:.75em;border-top:1px solid"></div><div style="bottom:.5em;left:.75em;right:.75em;border-bottom:1px solid"></div>',
  20067. };
  20068. const edgeCross = {
  20069. shape: {
  20070. frameStyle: 'edge',
  20071. frameInset: '2.5%',
  20072. frameSize: '.3125%',
  20073. },
  20074. thumb: '<div style="top:-.5em;left:.5em;right:.5em;bottom:-.5em; box-shadow: inset 0 0 0 1px currentColor"></div><div style="top:.5em;left:-.5em;right:-.5em;bottom:.5em;box-shadow:inset 0 0 0 1px currentColor"></div>',
  20075. };
  20076. const edgeOverlap = {
  20077. shape: {
  20078. frameStyle: 'edge',
  20079. frameOffset: '1.5%',
  20080. frameSize: '.3125%',
  20081. },
  20082. thumb: '<div style="top:.3125em;left:.5em;bottom:.3125em;border-left:1px solid"></div><div style="top:.3125em;right:.5em;bottom:.3125em;border-right:1px solid"></div><div style="top:.5em;left:.3125em;right:.3125em;border-top:1px solid"></div><div style="bottom:.5em;left:.3125em;right:.3125em;border-bottom:1px solid"></div>',
  20083. };
  20084. const hook = {
  20085. shape: {
  20086. frameStyle: 'hook',
  20087. frameInset: '2.5%',
  20088. frameSize: '.3125%',
  20089. frameLength: '5%',
  20090. },
  20091. thumb: '<div style="top:.5em;left:.5em;width:.75em;height:.75em; border-left: 1px solid;border-top: 1px solid;"></div><div style="top:.5em;right:.5em;width:.75em;height:.75em; border-right: 1px solid;border-top: 1px solid;"></div><div style="bottom:.5em;left:.5em;width:.75em;height:.75em; border-left: 1px solid;border-bottom: 1px solid;"></div><div style="bottom:.5em;right:.5em;width:.75em;height:.75em; border-right: 1px solid;border-bottom: 1px solid;"></div>',
  20092. };
  20093. const polaroid = {
  20094. shape: {
  20095. frameStyle: 'polaroid',
  20096. },
  20097. thumb: '<rect stroke-width="20%" x="-5%" y="-5%" width="110%" height="96%"/>',
  20098. };
  20099. const frameStylesDefault = {
  20100. solidSharp,
  20101. solidRound,
  20102. lineSingle,
  20103. lineMultiple,
  20104. edgeSeparate,
  20105. edgeCross,
  20106. edgeOverlap,
  20107. hook,
  20108. polaroid,
  20109. };
  20110. const frameOptionsDefault = [
  20111. [undefined, (locale) => locale.labelNone],
  20112. ['solidSharp', (locale) => locale.frameLabelMatSharp],
  20113. ['solidRound', (locale) => locale.frameLabelMatRound],
  20114. ['lineSingle', (locale) => locale.frameLabelLineSingle],
  20115. ['lineMultiple', (locale) => locale.frameLabelLineMultiple],
  20116. ['edgeCross', (locale) => locale.frameLabelEdgeCross],
  20117. ['edgeSeparate', (locale) => locale.frameLabelEdgeSeparate],
  20118. ['edgeOverlap', (locale) => locale.frameLabelEdgeOverlap],
  20119. ['hook', (locale) => locale.frameLabelCornerHooks],
  20120. ['polaroid', (locale) => locale.frameLabelPolaroid],
  20121. ];
  20122. var _plugin_frame_defaults = {
  20123. frameStyles: frameStylesDefault,
  20124. frameOptions: frameOptionsDefault,
  20125. };
  20126. var RGBToHSV = (r, g, b) => {
  20127. let v = Math.max(r, g, b), n = v - Math.min(r, g, b);
  20128. let h = n && (v == r ? (g - b) / n : v == g ? 2 + (b - r) / n : 4 + (r - g) / n);
  20129. return [(60 * (h < 0 ? h + 6 : h)) / 360, v && n / v, v];
  20130. };
  20131. var HSVToRGB = (h, s, v) => {
  20132. let r, g, b;
  20133. const i = Math.floor(h * 6);
  20134. const f = h * 6 - i;
  20135. const p = v * (1 - s);
  20136. const q = v * (1 - f * s);
  20137. const t = v * (1 - (1 - f) * s);
  20138. switch (i % 6) {
  20139. case 0:
  20140. (r = v), (g = t), (b = p);
  20141. break;
  20142. case 1:
  20143. (r = q), (g = v), (b = p);
  20144. break;
  20145. case 2:
  20146. (r = p), (g = v), (b = t);
  20147. break;
  20148. case 3:
  20149. (r = p), (g = q), (b = v);
  20150. break;
  20151. case 4:
  20152. (r = t), (g = p), (b = v);
  20153. break;
  20154. case 5:
  20155. (r = v), (g = p), (b = q);
  20156. break;
  20157. }
  20158. return [r, g, b];
  20159. };
  20160. /* src/core/ui/components/ColorPreview.svelte generated by Svelte v3.37.0 */
  20161. function create_fragment$t(ctx) {
  20162. let div;
  20163. let span;
  20164. let div_style_value;
  20165. return {
  20166. c() {
  20167. div = element("div");
  20168. span = element("span");
  20169. attr(div, "class", "PinturaColorPreview");
  20170. attr(div, "title", /*title*/ ctx[0]);
  20171. attr(div, "style", div_style_value = `--color:${/*colorValue*/ ctx[1]}`);
  20172. },
  20173. m(target, anchor) {
  20174. insert(target, div, anchor);
  20175. append(div, span);
  20176. },
  20177. p(ctx, [dirty]) {
  20178. if (dirty & /*title*/ 1) {
  20179. attr(div, "title", /*title*/ ctx[0]);
  20180. }
  20181. if (dirty & /*colorValue*/ 2 && div_style_value !== (div_style_value = `--color:${/*colorValue*/ ctx[1]}`)) {
  20182. attr(div, "style", div_style_value);
  20183. }
  20184. },
  20185. i: noop,
  20186. o: noop,
  20187. d(detaching) {
  20188. if (detaching) detach(div);
  20189. }
  20190. };
  20191. }
  20192. function instance$t($$self, $$props, $$invalidate) {
  20193. let colorValue;
  20194. let { color = undefined } = $$props;
  20195. let { title = undefined } = $$props;
  20196. $$self.$$set = $$props => {
  20197. if ("color" in $$props) $$invalidate(2, color = $$props.color);
  20198. if ("title" in $$props) $$invalidate(0, title = $$props.title);
  20199. };
  20200. $$self.$$.update = () => {
  20201. if ($$self.$$.dirty & /*color*/ 4) {
  20202. $$invalidate(1, colorValue = color ? colorArrayToRGBA(color) : "transparent");
  20203. }
  20204. };
  20205. return [title, colorValue, color];
  20206. }
  20207. class ColorPreview extends SvelteComponent {
  20208. constructor(options) {
  20209. super();
  20210. init(this, options, instance$t, create_fragment$t, safe_not_equal, { color: 2, title: 0 });
  20211. }
  20212. }
  20213. /* src/core/ui/components/ColorPicker.svelte generated by Svelte v3.37.0 */
  20214. function create_if_block_4$3(ctx) {
  20215. let span;
  20216. let t;
  20217. return {
  20218. c() {
  20219. span = element("span");
  20220. t = text(/*label*/ ctx[0]);
  20221. },
  20222. m(target, anchor) {
  20223. insert(target, span, anchor);
  20224. append(span, t);
  20225. },
  20226. p(ctx, dirty) {
  20227. if (dirty[0] & /*label*/ 1) set_data(t, /*label*/ ctx[0]);
  20228. },
  20229. d(detaching) {
  20230. if (detaching) detach(span);
  20231. }
  20232. };
  20233. }
  20234. // (160:4)
  20235. function create_label_slot(ctx) {
  20236. let span;
  20237. let colorpreview;
  20238. let t;
  20239. let current;
  20240. colorpreview = new ColorPreview({
  20241. props: {
  20242. color: /*value*/ ctx[4],
  20243. title: localize(/*title*/ ctx[8], /*locale*/ ctx[10])
  20244. }
  20245. });
  20246. let if_block = !/*hidePresetLabel*/ ctx[9] && create_if_block_4$3(ctx);
  20247. return {
  20248. c() {
  20249. span = element("span");
  20250. create_component(colorpreview.$$.fragment);
  20251. t = space();
  20252. if (if_block) if_block.c();
  20253. attr(span, "slot", "label");
  20254. attr(span, "class", "PinturaButtonLabel");
  20255. },
  20256. m(target, anchor) {
  20257. insert(target, span, anchor);
  20258. mount_component(colorpreview, span, null);
  20259. append(span, t);
  20260. if (if_block) if_block.m(span, null);
  20261. current = true;
  20262. },
  20263. p(ctx, dirty) {
  20264. const colorpreview_changes = {};
  20265. if (dirty[0] & /*value*/ 16) colorpreview_changes.color = /*value*/ ctx[4];
  20266. if (dirty[0] & /*title, locale*/ 1280) colorpreview_changes.title = localize(/*title*/ ctx[8], /*locale*/ ctx[10]);
  20267. colorpreview.$set(colorpreview_changes);
  20268. if (!/*hidePresetLabel*/ ctx[9]) {
  20269. if (if_block) {
  20270. if_block.p(ctx, dirty);
  20271. } else {
  20272. if_block = create_if_block_4$3(ctx);
  20273. if_block.c();
  20274. if_block.m(span, null);
  20275. }
  20276. } else if (if_block) {
  20277. if_block.d(1);
  20278. if_block = null;
  20279. }
  20280. },
  20281. i(local) {
  20282. if (current) return;
  20283. transition_in(colorpreview.$$.fragment, local);
  20284. current = true;
  20285. },
  20286. o(local) {
  20287. transition_out(colorpreview.$$.fragment, local);
  20288. current = false;
  20289. },
  20290. d(detaching) {
  20291. if (detaching) detach(span);
  20292. destroy_component(colorpreview);
  20293. if (if_block) if_block.d();
  20294. }
  20295. };
  20296. }
  20297. // (171:8) {#if enablePicker}
  20298. function create_if_block_2$5(ctx) {
  20299. let div3;
  20300. let div2;
  20301. let div1;
  20302. let div0;
  20303. let div0_style_value;
  20304. let div1_style_value;
  20305. let div2_style_value;
  20306. let t0;
  20307. let slider;
  20308. let t1;
  20309. let current;
  20310. let mounted;
  20311. let dispose;
  20312. slider = new Slider({
  20313. props: {
  20314. class: "PinturaHuePicker",
  20315. knobStyle: `background-color:${/*valueAsRGBAFullySaturated*/ ctx[19]}`,
  20316. onchange: /*updateHue*/ ctx[24],
  20317. value: /*hue*/ ctx[14],
  20318. min: 0,
  20319. max: 1,
  20320. step: 0.01
  20321. }
  20322. });
  20323. let if_block = /*enableOpacity*/ ctx[11] && create_if_block_3$3(ctx);
  20324. return {
  20325. c() {
  20326. div3 = element("div");
  20327. div2 = element("div");
  20328. div1 = element("div");
  20329. div0 = element("div");
  20330. t0 = space();
  20331. create_component(slider.$$.fragment);
  20332. t1 = space();
  20333. if (if_block) if_block.c();
  20334. attr(div0, "role", "button");
  20335. attr(div0, "aria-label", "Saturation slider");
  20336. attr(div0, "class", "PinturaPickerKnob");
  20337. attr(div0, "tabindex", "0");
  20338. attr(div0, "style", div0_style_value = `background-color:${/*valueAsRGBAFullyOpaque*/ ctx[18]};`);
  20339. attr(div1, "class", "PinturaPickerKnobController");
  20340. attr(div1, "style", div1_style_value = `transform:translate(${/*sx*/ ctx[21]}%,${/*sy*/ ctx[22]}%)`);
  20341. attr(div2, "class", "PinturaSaturationPicker");
  20342. attr(div2, "style", div2_style_value = `background-color: ${/*valueAsRGBAFullySaturated*/ ctx[19]}`);
  20343. attr(div3, "class", "PinturaPicker");
  20344. },
  20345. m(target, anchor) {
  20346. insert(target, div3, anchor);
  20347. append(div3, div2);
  20348. append(div2, div1);
  20349. append(div1, div0);
  20350. /*div2_binding*/ ctx[31](div2);
  20351. append(div3, t0);
  20352. mount_component(slider, div3, null);
  20353. append(div3, t1);
  20354. if (if_block) if_block.m(div3, null);
  20355. current = true;
  20356. if (!mounted) {
  20357. dispose = [
  20358. listen(div0, "nudge", /*handleNudge*/ ctx[27]),
  20359. action_destroyer(nudgeable.call(null, div0)),
  20360. listen(div2, "pointerdown", /*handlePointerDown*/ ctx[26])
  20361. ];
  20362. mounted = true;
  20363. }
  20364. },
  20365. p(ctx, dirty) {
  20366. if (!current || dirty[0] & /*valueAsRGBAFullyOpaque*/ 262144 && div0_style_value !== (div0_style_value = `background-color:${/*valueAsRGBAFullyOpaque*/ ctx[18]};`)) {
  20367. attr(div0, "style", div0_style_value);
  20368. }
  20369. if (!current || dirty[0] & /*sx, sy*/ 6291456 && div1_style_value !== (div1_style_value = `transform:translate(${/*sx*/ ctx[21]}%,${/*sy*/ ctx[22]}%)`)) {
  20370. attr(div1, "style", div1_style_value);
  20371. }
  20372. if (!current || dirty[0] & /*valueAsRGBAFullySaturated*/ 524288 && div2_style_value !== (div2_style_value = `background-color: ${/*valueAsRGBAFullySaturated*/ ctx[19]}`)) {
  20373. attr(div2, "style", div2_style_value);
  20374. }
  20375. const slider_changes = {};
  20376. if (dirty[0] & /*valueAsRGBAFullySaturated*/ 524288) slider_changes.knobStyle = `background-color:${/*valueAsRGBAFullySaturated*/ ctx[19]}`;
  20377. if (dirty[0] & /*hue*/ 16384) slider_changes.value = /*hue*/ ctx[14];
  20378. slider.$set(slider_changes);
  20379. if (/*enableOpacity*/ ctx[11]) {
  20380. if (if_block) {
  20381. if_block.p(ctx, dirty);
  20382. if (dirty[0] & /*enableOpacity*/ 2048) {
  20383. transition_in(if_block, 1);
  20384. }
  20385. } else {
  20386. if_block = create_if_block_3$3(ctx);
  20387. if_block.c();
  20388. transition_in(if_block, 1);
  20389. if_block.m(div3, null);
  20390. }
  20391. } else if (if_block) {
  20392. group_outros();
  20393. transition_out(if_block, 1, 1, () => {
  20394. if_block = null;
  20395. });
  20396. check_outros();
  20397. }
  20398. },
  20399. i(local) {
  20400. if (current) return;
  20401. transition_in(slider.$$.fragment, local);
  20402. transition_in(if_block);
  20403. current = true;
  20404. },
  20405. o(local) {
  20406. transition_out(slider.$$.fragment, local);
  20407. transition_out(if_block);
  20408. current = false;
  20409. },
  20410. d(detaching) {
  20411. if (detaching) detach(div3);
  20412. /*div2_binding*/ ctx[31](null);
  20413. destroy_component(slider);
  20414. if (if_block) if_block.d();
  20415. mounted = false;
  20416. run_all(dispose);
  20417. }
  20418. };
  20419. }
  20420. // (205:16) {#if enableOpacity}
  20421. function create_if_block_3$3(ctx) {
  20422. let slider;
  20423. let current;
  20424. slider = new Slider({
  20425. props: {
  20426. class: "PinturaOpacityPicker",
  20427. knobStyle: `background-color: ${/*valueAsRGBA*/ ctx[16]}`,
  20428. trackStyle: `background-image: linear-gradient(to right, ${/*valueAsRGBAFullyTransparent*/ ctx[17]}, ${/*valueAsRGBAFullyOpaque*/ ctx[18]})`,
  20429. onchange: /*updateOpacity*/ ctx[25],
  20430. value: /*opacity*/ ctx[15],
  20431. min: 0,
  20432. max: 1,
  20433. step: 0.01
  20434. }
  20435. });
  20436. return {
  20437. c() {
  20438. create_component(slider.$$.fragment);
  20439. },
  20440. m(target, anchor) {
  20441. mount_component(slider, target, anchor);
  20442. current = true;
  20443. },
  20444. p(ctx, dirty) {
  20445. const slider_changes = {};
  20446. if (dirty[0] & /*valueAsRGBA*/ 65536) slider_changes.knobStyle = `background-color: ${/*valueAsRGBA*/ ctx[16]}`;
  20447. if (dirty[0] & /*valueAsRGBAFullyTransparent, valueAsRGBAFullyOpaque*/ 393216) slider_changes.trackStyle = `background-image: linear-gradient(to right, ${/*valueAsRGBAFullyTransparent*/ ctx[17]}, ${/*valueAsRGBAFullyOpaque*/ ctx[18]})`;
  20448. if (dirty[0] & /*opacity*/ 32768) slider_changes.value = /*opacity*/ ctx[15];
  20449. slider.$set(slider_changes);
  20450. },
  20451. i(local) {
  20452. if (current) return;
  20453. transition_in(slider.$$.fragment, local);
  20454. current = true;
  20455. },
  20456. o(local) {
  20457. transition_out(slider.$$.fragment, local);
  20458. current = false;
  20459. },
  20460. d(detaching) {
  20461. destroy_component(slider, detaching);
  20462. }
  20463. };
  20464. }
  20465. // (221:8) {#if enablePresets}
  20466. function create_if_block$6(ctx) {
  20467. let radiogroup;
  20468. let current;
  20469. radiogroup = new RadioGroup({
  20470. props: {
  20471. label: "Presets",
  20472. class: arrayJoin([
  20473. "PinturaColorPresets",
  20474. /*hidePresetLabel*/ ctx[9]
  20475. ? "PinturaColorPresetsGrid"
  20476. : "PinturaColorPresetsList"
  20477. ]),
  20478. hideLabel: false,
  20479. name: /*name*/ ctx[1],
  20480. value: /*value*/ ctx[4],
  20481. optionGroupClass: "PinturaDropdownOptionGroup",
  20482. optionClass: "PinturaDropdownOption",
  20483. options: /*options*/ ctx[2].map(/*func*/ ctx[32]),
  20484. selectedIndex: /*selectedIndex*/ ctx[3],
  20485. optionMapper: /*optionMapper*/ ctx[7],
  20486. optionLabelClass: /*optionLabelClass*/ ctx[6],
  20487. onchange: /*func_1*/ ctx[33],
  20488. $$slots: {
  20489. option: [
  20490. create_option_slot$3,
  20491. ({ option }) => ({ 44: option }),
  20492. ({ option }) => [0, option ? 8192 : 0]
  20493. ],
  20494. group: [
  20495. create_group_slot,
  20496. ({ option }) => ({ 44: option }),
  20497. ({ option }) => [0, option ? 8192 : 0]
  20498. ]
  20499. },
  20500. $$scope: { ctx }
  20501. }
  20502. });
  20503. return {
  20504. c() {
  20505. create_component(radiogroup.$$.fragment);
  20506. },
  20507. m(target, anchor) {
  20508. mount_component(radiogroup, target, anchor);
  20509. current = true;
  20510. },
  20511. p(ctx, dirty) {
  20512. const radiogroup_changes = {};
  20513. if (dirty[0] & /*hidePresetLabel*/ 512) radiogroup_changes.class = arrayJoin([
  20514. "PinturaColorPresets",
  20515. /*hidePresetLabel*/ ctx[9]
  20516. ? "PinturaColorPresetsGrid"
  20517. : "PinturaColorPresetsList"
  20518. ]);
  20519. if (dirty[0] & /*name*/ 2) radiogroup_changes.name = /*name*/ ctx[1];
  20520. if (dirty[0] & /*value*/ 16) radiogroup_changes.value = /*value*/ ctx[4];
  20521. if (dirty[0] & /*options, locale*/ 1028) radiogroup_changes.options = /*options*/ ctx[2].map(/*func*/ ctx[32]);
  20522. if (dirty[0] & /*selectedIndex*/ 8) radiogroup_changes.selectedIndex = /*selectedIndex*/ ctx[3];
  20523. if (dirty[0] & /*optionMapper*/ 128) radiogroup_changes.optionMapper = /*optionMapper*/ ctx[7];
  20524. if (dirty[0] & /*optionLabelClass*/ 64) radiogroup_changes.optionLabelClass = /*optionLabelClass*/ ctx[6];
  20525. if (dirty[0] & /*hidePresetLabel*/ 512 | dirty[1] & /*$$scope, option*/ 24576) {
  20526. radiogroup_changes.$$scope = { dirty, ctx };
  20527. }
  20528. radiogroup.$set(radiogroup_changes);
  20529. },
  20530. i(local) {
  20531. if (current) return;
  20532. transition_in(radiogroup.$$.fragment, local);
  20533. current = true;
  20534. },
  20535. o(local) {
  20536. transition_out(radiogroup.$$.fragment, local);
  20537. current = false;
  20538. },
  20539. d(detaching) {
  20540. destroy_component(radiogroup, detaching);
  20541. }
  20542. };
  20543. }
  20544. // (243:16)
  20545. function create_group_slot(ctx) {
  20546. let span;
  20547. let t_value = /*option*/ ctx[44].label + "";
  20548. let t;
  20549. return {
  20550. c() {
  20551. span = element("span");
  20552. t = text(t_value);
  20553. attr(span, "slot", "group");
  20554. },
  20555. m(target, anchor) {
  20556. insert(target, span, anchor);
  20557. append(span, t);
  20558. },
  20559. p(ctx, dirty) {
  20560. if (dirty[1] & /*option*/ 8192 && t_value !== (t_value = /*option*/ ctx[44].label + "")) set_data(t, t_value);
  20561. },
  20562. d(detaching) {
  20563. if (detaching) detach(span);
  20564. }
  20565. };
  20566. }
  20567. // (248:20) {#if !hidePresetLabel}
  20568. function create_if_block_1$6(ctx) {
  20569. let span;
  20570. let t_value = /*option*/ ctx[44].label + "";
  20571. let t;
  20572. return {
  20573. c() {
  20574. span = element("span");
  20575. t = text(t_value);
  20576. attr(span, "class", "PinturaButtonLabel");
  20577. },
  20578. m(target, anchor) {
  20579. insert(target, span, anchor);
  20580. append(span, t);
  20581. },
  20582. p(ctx, dirty) {
  20583. if (dirty[1] & /*option*/ 8192 && t_value !== (t_value = /*option*/ ctx[44].label + "")) set_data(t, t_value);
  20584. },
  20585. d(detaching) {
  20586. if (detaching) detach(span);
  20587. }
  20588. };
  20589. }
  20590. // (246:16)
  20591. function create_option_slot$3(ctx) {
  20592. let span;
  20593. let colorpreview;
  20594. let t;
  20595. let current;
  20596. colorpreview = new ColorPreview({
  20597. props: {
  20598. title: /*option*/ ctx[44].label,
  20599. color: /*option*/ ctx[44].value
  20600. }
  20601. });
  20602. let if_block = !/*hidePresetLabel*/ ctx[9] && create_if_block_1$6(ctx);
  20603. return {
  20604. c() {
  20605. span = element("span");
  20606. create_component(colorpreview.$$.fragment);
  20607. t = space();
  20608. if (if_block) if_block.c();
  20609. attr(span, "slot", "option");
  20610. },
  20611. m(target, anchor) {
  20612. insert(target, span, anchor);
  20613. mount_component(colorpreview, span, null);
  20614. append(span, t);
  20615. if (if_block) if_block.m(span, null);
  20616. current = true;
  20617. },
  20618. p(ctx, dirty) {
  20619. const colorpreview_changes = {};
  20620. if (dirty[1] & /*option*/ 8192) colorpreview_changes.title = /*option*/ ctx[44].label;
  20621. if (dirty[1] & /*option*/ 8192) colorpreview_changes.color = /*option*/ ctx[44].value;
  20622. colorpreview.$set(colorpreview_changes);
  20623. if (!/*hidePresetLabel*/ ctx[9]) {
  20624. if (if_block) {
  20625. if_block.p(ctx, dirty);
  20626. } else {
  20627. if_block = create_if_block_1$6(ctx);
  20628. if_block.c();
  20629. if_block.m(span, null);
  20630. }
  20631. } else if (if_block) {
  20632. if_block.d(1);
  20633. if_block = null;
  20634. }
  20635. },
  20636. i(local) {
  20637. if (current) return;
  20638. transition_in(colorpreview.$$.fragment, local);
  20639. current = true;
  20640. },
  20641. o(local) {
  20642. transition_out(colorpreview.$$.fragment, local);
  20643. current = false;
  20644. },
  20645. d(detaching) {
  20646. if (detaching) detach(span);
  20647. destroy_component(colorpreview);
  20648. if (if_block) if_block.d();
  20649. }
  20650. };
  20651. }
  20652. // (169:4)
  20653. function create_details_slot(ctx) {
  20654. let div;
  20655. let t;
  20656. let current;
  20657. let if_block0 = /*enablePicker*/ ctx[13] && create_if_block_2$5(ctx);
  20658. let if_block1 = /*enablePresets*/ ctx[12] && create_if_block$6(ctx);
  20659. return {
  20660. c() {
  20661. div = element("div");
  20662. if (if_block0) if_block0.c();
  20663. t = space();
  20664. if (if_block1) if_block1.c();
  20665. attr(div, "slot", "details");
  20666. attr(div, "class", "PinturaColorPickerPanel");
  20667. },
  20668. m(target, anchor) {
  20669. insert(target, div, anchor);
  20670. if (if_block0) if_block0.m(div, null);
  20671. append(div, t);
  20672. if (if_block1) if_block1.m(div, null);
  20673. current = true;
  20674. },
  20675. p(ctx, dirty) {
  20676. if (/*enablePicker*/ ctx[13]) {
  20677. if (if_block0) {
  20678. if_block0.p(ctx, dirty);
  20679. if (dirty[0] & /*enablePicker*/ 8192) {
  20680. transition_in(if_block0, 1);
  20681. }
  20682. } else {
  20683. if_block0 = create_if_block_2$5(ctx);
  20684. if_block0.c();
  20685. transition_in(if_block0, 1);
  20686. if_block0.m(div, t);
  20687. }
  20688. } else if (if_block0) {
  20689. group_outros();
  20690. transition_out(if_block0, 1, 1, () => {
  20691. if_block0 = null;
  20692. });
  20693. check_outros();
  20694. }
  20695. if (/*enablePresets*/ ctx[12]) {
  20696. if (if_block1) {
  20697. if_block1.p(ctx, dirty);
  20698. if (dirty[0] & /*enablePresets*/ 4096) {
  20699. transition_in(if_block1, 1);
  20700. }
  20701. } else {
  20702. if_block1 = create_if_block$6(ctx);
  20703. if_block1.c();
  20704. transition_in(if_block1, 1);
  20705. if_block1.m(div, null);
  20706. }
  20707. } else if (if_block1) {
  20708. group_outros();
  20709. transition_out(if_block1, 1, 1, () => {
  20710. if_block1 = null;
  20711. });
  20712. check_outros();
  20713. }
  20714. },
  20715. i(local) {
  20716. if (current) return;
  20717. transition_in(if_block0);
  20718. transition_in(if_block1);
  20719. current = true;
  20720. },
  20721. o(local) {
  20722. transition_out(if_block0);
  20723. transition_out(if_block1);
  20724. current = false;
  20725. },
  20726. d(detaching) {
  20727. if (detaching) detach(div);
  20728. if (if_block0) if_block0.d();
  20729. if (if_block1) if_block1.d();
  20730. }
  20731. };
  20732. }
  20733. function create_fragment$s(ctx) {
  20734. let details;
  20735. let current;
  20736. details = new Details({
  20737. props: {
  20738. buttonClass: arrayJoin(["PinturaColorPickerButton", /*buttonClass*/ ctx[5]]),
  20739. $$slots: {
  20740. details: [create_details_slot],
  20741. label: [create_label_slot]
  20742. },
  20743. $$scope: { ctx }
  20744. }
  20745. });
  20746. return {
  20747. c() {
  20748. create_component(details.$$.fragment);
  20749. },
  20750. m(target, anchor) {
  20751. mount_component(details, target, anchor);
  20752. current = true;
  20753. },
  20754. p(ctx, dirty) {
  20755. const details_changes = {};
  20756. if (dirty[0] & /*buttonClass*/ 32) details_changes.buttonClass = arrayJoin(["PinturaColorPickerButton", /*buttonClass*/ ctx[5]]);
  20757. if (dirty[0] & /*hidePresetLabel, name, value, options, locale, selectedIndex, optionMapper, optionLabelClass, enablePresets, valueAsRGBA, valueAsRGBAFullyTransparent, valueAsRGBAFullyOpaque, opacity, enableOpacity, valueAsRGBAFullySaturated, hue, input, sx, sy, enablePicker, label, title*/ 8388575 | dirty[1] & /*$$scope*/ 16384) {
  20758. details_changes.$$scope = { dirty, ctx };
  20759. }
  20760. details.$set(details_changes);
  20761. },
  20762. i(local) {
  20763. if (current) return;
  20764. transition_in(details.$$.fragment, local);
  20765. current = true;
  20766. },
  20767. o(local) {
  20768. transition_out(details.$$.fragment, local);
  20769. current = false;
  20770. },
  20771. d(detaching) {
  20772. destroy_component(details, detaching);
  20773. }
  20774. };
  20775. }
  20776. function instance$s($$self, $$props, $$invalidate) {
  20777. let sx;
  20778. let sy;
  20779. let { label = undefined } = $$props;
  20780. let { name = undefined } = $$props;
  20781. let { options = [] } = $$props;
  20782. let { selectedIndex = -1 } = $$props;
  20783. let { value = undefined } = $$props;
  20784. let { buttonClass = undefined } = $$props;
  20785. let { optionLabelClass = undefined } = $$props;
  20786. let { optionMapper = undefined } = $$props;
  20787. let { onchange = undefined } = $$props;
  20788. let { title = undefined } = $$props;
  20789. let { hidePresetLabel = true } = $$props;
  20790. let { locale = undefined } = $$props;
  20791. let { enableOpacity = true } = $$props;
  20792. let { enablePresets = true } = $$props;
  20793. let { enablePicker = true } = $$props;
  20794. // inputs
  20795. let hue;
  20796. let saturation;
  20797. let brightness;
  20798. let opacity;
  20799. // shortcuts
  20800. let valueAsRGB;
  20801. let valueAsRGBA;
  20802. let valueAsRGBAFullyTransparent;
  20803. let valueAsRGBAFullyOpaque;
  20804. let valueAsRGBAFullySaturated;
  20805. const updateProps = (color, syncControls) => {
  20806. valueAsRGB = [color[0], color[1], color[2]];
  20807. if (syncControls) {
  20808. let valueAsHSV = RGBToHSV(...valueAsRGB);
  20809. $$invalidate(14, hue = valueAsHSV[0]);
  20810. $$invalidate(29, saturation = valueAsHSV[1]);
  20811. $$invalidate(30, brightness = valueAsHSV[2]);
  20812. $$invalidate(15, opacity = isNumber(color[3]) ? color[3] : 1);
  20813. }
  20814. $$invalidate(16, valueAsRGBA = colorArrayToRGBA(color));
  20815. $$invalidate(17, valueAsRGBAFullyTransparent = colorArrayToRGBA([...valueAsRGB, 0]));
  20816. $$invalidate(18, valueAsRGBAFullyOpaque = colorArrayToRGBA([...valueAsRGB, 1]));
  20817. $$invalidate(19, valueAsRGBAFullySaturated = colorArrayToRGBA(HSVToRGB(hue, 1, 1)));
  20818. };
  20819. value && updateProps(value, true);
  20820. const update = () => {
  20821. const rgb = HSVToRGB(hue, saturation, brightness);
  20822. const rgba = [...rgb, opacity];
  20823. updateProps(rgba);
  20824. onchange(rgba);
  20825. };
  20826. const updateColorArray = arr => {
  20827. const rgba = arr.length === 3 ? [...arr, 1] : arr;
  20828. updateProps(rgba, true);
  20829. onchange(rgba);
  20830. };
  20831. const updateHue = h => {
  20832. $$invalidate(14, hue = h);
  20833. if (opacity === 0) $$invalidate(15, opacity = 1);
  20834. update();
  20835. };
  20836. const updateSaturationAndBrightness = (s, b) => {
  20837. $$invalidate(29, saturation = s);
  20838. $$invalidate(30, brightness = b);
  20839. if (opacity === 0) $$invalidate(15, opacity = 1);
  20840. update();
  20841. };
  20842. const updateOpacity = o => {
  20843. $$invalidate(15, opacity = o);
  20844. update();
  20845. };
  20846. const setValueByOffset = (offset, inputSize) => {
  20847. const x = clamp(offset.x / inputSize.width, 0, 1);
  20848. const y = clamp(offset.y / inputSize.height, 0, 1);
  20849. updateSaturationAndBrightness(x, 1 - y);
  20850. };
  20851. let input;
  20852. let inputSize;
  20853. let inputOffset;
  20854. let inputPageOffset;
  20855. const handlePointerDown = e => {
  20856. e.stopPropagation();
  20857. inputSize = sizeCreate(input.offsetWidth, input.offsetHeight);
  20858. inputOffset = vectorCreateFromPointerEventOffset(e);
  20859. inputPageOffset = vectorCreateFromPointerEvent(e);
  20860. setValueByOffset(inputOffset, inputSize);
  20861. document.documentElement.addEventListener("pointermove", handlePointerMove);
  20862. document.documentElement.addEventListener("pointerup", handlePointerUp);
  20863. };
  20864. const handlePointerMove = e => {
  20865. const d = vectorSubtract(vectorCreateFromPointerEvent(e), inputPageOffset);
  20866. setValueByOffset(vectorAdd(vectorClone(inputOffset), d), inputSize);
  20867. };
  20868. const handlePointerUp = e => {
  20869. inputSize = undefined;
  20870. document.documentElement.removeEventListener("pointermove", handlePointerMove);
  20871. document.documentElement.removeEventListener("pointerup", handlePointerUp);
  20872. };
  20873. const handleNudge = e => {
  20874. inputSize = sizeCreate(input.offsetWidth, input.offsetHeight);
  20875. const x = sx / 100 * inputSize.width;
  20876. const y = sy / 100 * inputSize.height;
  20877. setValueByOffset({ x: x + e.detail.x, y: y + e.detail.y }, inputSize);
  20878. };
  20879. function div2_binding($$value) {
  20880. binding_callbacks[$$value ? "unshift" : "push"](() => {
  20881. input = $$value;
  20882. $$invalidate(20, input);
  20883. });
  20884. }
  20885. const func = ([color, label]) => [color, isFunction(label) ? label(locale) : label];
  20886. const func_1 = detail => updateColorArray(detail.value);
  20887. $$self.$$set = $$props => {
  20888. if ("label" in $$props) $$invalidate(0, label = $$props.label);
  20889. if ("name" in $$props) $$invalidate(1, name = $$props.name);
  20890. if ("options" in $$props) $$invalidate(2, options = $$props.options);
  20891. if ("selectedIndex" in $$props) $$invalidate(3, selectedIndex = $$props.selectedIndex);
  20892. if ("value" in $$props) $$invalidate(4, value = $$props.value);
  20893. if ("buttonClass" in $$props) $$invalidate(5, buttonClass = $$props.buttonClass);
  20894. if ("optionLabelClass" in $$props) $$invalidate(6, optionLabelClass = $$props.optionLabelClass);
  20895. if ("optionMapper" in $$props) $$invalidate(7, optionMapper = $$props.optionMapper);
  20896. if ("onchange" in $$props) $$invalidate(28, onchange = $$props.onchange);
  20897. if ("title" in $$props) $$invalidate(8, title = $$props.title);
  20898. if ("hidePresetLabel" in $$props) $$invalidate(9, hidePresetLabel = $$props.hidePresetLabel);
  20899. if ("locale" in $$props) $$invalidate(10, locale = $$props.locale);
  20900. if ("enableOpacity" in $$props) $$invalidate(11, enableOpacity = $$props.enableOpacity);
  20901. if ("enablePresets" in $$props) $$invalidate(12, enablePresets = $$props.enablePresets);
  20902. if ("enablePicker" in $$props) $$invalidate(13, enablePicker = $$props.enablePicker);
  20903. };
  20904. $$self.$$.update = () => {
  20905. if ($$self.$$.dirty[0] & /*saturation*/ 536870912) {
  20906. $$invalidate(21, sx = saturation * 100);
  20907. }
  20908. if ($$self.$$.dirty[0] & /*brightness*/ 1073741824) {
  20909. $$invalidate(22, sy = 100 - brightness * 100);
  20910. }
  20911. };
  20912. return [
  20913. label,
  20914. name,
  20915. options,
  20916. selectedIndex,
  20917. value,
  20918. buttonClass,
  20919. optionLabelClass,
  20920. optionMapper,
  20921. title,
  20922. hidePresetLabel,
  20923. locale,
  20924. enableOpacity,
  20925. enablePresets,
  20926. enablePicker,
  20927. hue,
  20928. opacity,
  20929. valueAsRGBA,
  20930. valueAsRGBAFullyTransparent,
  20931. valueAsRGBAFullyOpaque,
  20932. valueAsRGBAFullySaturated,
  20933. input,
  20934. sx,
  20935. sy,
  20936. updateColorArray,
  20937. updateHue,
  20938. updateOpacity,
  20939. handlePointerDown,
  20940. handleNudge,
  20941. onchange,
  20942. saturation,
  20943. brightness,
  20944. div2_binding,
  20945. func,
  20946. func_1
  20947. ];
  20948. }
  20949. class ColorPicker extends SvelteComponent {
  20950. constructor(options) {
  20951. super();
  20952. init(
  20953. this,
  20954. options,
  20955. instance$s,
  20956. create_fragment$s,
  20957. safe_not_equal,
  20958. {
  20959. label: 0,
  20960. name: 1,
  20961. options: 2,
  20962. selectedIndex: 3,
  20963. value: 4,
  20964. buttonClass: 5,
  20965. optionLabelClass: 6,
  20966. optionMapper: 7,
  20967. onchange: 28,
  20968. title: 8,
  20969. hidePresetLabel: 9,
  20970. locale: 10,
  20971. enableOpacity: 11,
  20972. enablePresets: 12,
  20973. enablePicker: 13
  20974. },
  20975. [-1, -1]
  20976. );
  20977. }
  20978. }
  20979. var upperCaseFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
  20980. let result$2 = null;
  20981. var canCheckFontAvailability = () => {
  20982. if (result$2 === null) {
  20983. if (!isBrowser())
  20984. result$2 = false;
  20985. else {
  20986. try {
  20987. // if browser can detect font as non existend then it supports font checking (only chrome)
  20988. // @ts-ignore
  20989. result$2 = document.fonts.check('16px TestNonExistingFont') === false;
  20990. }
  20991. catch (err) {
  20992. // if throws assume can't check
  20993. result$2 = false;
  20994. }
  20995. }
  20996. }
  20997. return result$2;
  20998. };
  20999. // @ts-ignore
  21000. const toLocaleFn = (key, localePrefix) => (locale) => locale[localePrefix ? `${localePrefix}${upperCaseFirstLetter(key)}` : key];
  21001. const mapToSizeOption = (v) => [v, `${v}`];
  21002. const createLocaleMapper = (options, localePrefix) => (key) => [
  21003. options[key],
  21004. toLocaleFn(key, localePrefix),
  21005. ];
  21006. const toolColorDefault = [1, 0.2549, 0.2118];
  21007. const toolStrokeColorDefault = [1, 1, 1, 0];
  21008. //#region tools
  21009. const toolShapeDefaults = {
  21010. path: () => ({
  21011. points: [],
  21012. disableErase: false,
  21013. }),
  21014. eraser: () => ({
  21015. eraseRadius: 0,
  21016. }),
  21017. line: () => ({
  21018. x1: 0,
  21019. y1: 0,
  21020. x2: 0,
  21021. y2: 0,
  21022. disableErase: false,
  21023. }),
  21024. rectangle: () => ({
  21025. x: 0,
  21026. y: 0,
  21027. width: 0,
  21028. height: 0,
  21029. }),
  21030. ellipse: () => ({
  21031. x: 0,
  21032. y: 0,
  21033. rx: 0,
  21034. ry: 0,
  21035. }),
  21036. text: () => ({
  21037. x: 0,
  21038. y: 0,
  21039. text: 'Text',
  21040. }),
  21041. };
  21042. const createToolStyle = (type, shape = {}, options = { position: 'relative' }) => {
  21043. if (!toolShapeDefaults[type])
  21044. return;
  21045. const shapeDef = {
  21046. ...toolShapeDefaults[type](),
  21047. ...shape,
  21048. };
  21049. return [shapeDef, options];
  21050. };
  21051. const createToolStyles = (tools) => ({
  21052. sharpie: createToolStyle('path', {
  21053. strokeWidth: '0.5%',
  21054. strokeColor: [...toolColorDefault],
  21055. disableMove: true,
  21056. }),
  21057. eraser: createToolStyle('eraser'),
  21058. line: createToolStyle('line', {
  21059. strokeColor: [...toolColorDefault],
  21060. strokeWidth: '0.5%',
  21061. }),
  21062. arrow: createToolStyle('line', {
  21063. lineStart: 'none',
  21064. lineEnd: 'arrow-solid',
  21065. strokeColor: [...toolColorDefault],
  21066. strokeWidth: '0.5%',
  21067. }),
  21068. rectangle: createToolStyle('rectangle', {
  21069. strokeColor: [...toolStrokeColorDefault],
  21070. backgroundColor: [...toolColorDefault],
  21071. }),
  21072. ellipse: createToolStyle('ellipse', {
  21073. strokeColor: [...toolStrokeColorDefault],
  21074. backgroundColor: [...toolColorDefault],
  21075. }),
  21076. text: createToolStyle('text', {
  21077. color: [...toolColorDefault],
  21078. fontSize: '2%',
  21079. }),
  21080. ...tools,
  21081. });
  21082. //#endregion
  21083. //#region toolbar
  21084. const createToolbarItem = (tool, label, props) => [
  21085. tool,
  21086. label || toLocaleFn(tool, 'shapeLabelTool'),
  21087. {
  21088. icon: toLocaleFn(tool, 'shapeIconTool'),
  21089. ...props,
  21090. },
  21091. ];
  21092. const createToolbar = (tools = ['sharpie', 'eraser', 'line', 'arrow', 'rectangle', 'ellipse', 'text', 'preset']) => tools
  21093. .map((tool) => {
  21094. // default tool definition, assume locale in
  21095. if (isString(tool))
  21096. return createToolbarItem(tool);
  21097. // tool def with propery
  21098. if (Array.isArray(tool)) {
  21099. // state update of tool with key in locale object
  21100. if (isObject(tool[1]))
  21101. return createToolbarItem(tool[0], undefined, tool[1]);
  21102. // should be string, string
  21103. return createToolbarItem(tool[0], tool[1], tool[2]);
  21104. }
  21105. })
  21106. .filter(Boolean);
  21107. //#endregion
  21108. //#region style option defaults
  21109. const createDefaultColorOptions = () => ({
  21110. transparent: [1, 1, 1, 0],
  21111. white: [1, 1, 1],
  21112. silver: [0.8667, 0.8667, 0.8667],
  21113. gray: [0.6667, 0.6667, 0.6667],
  21114. black: [0, 0, 0],
  21115. navy: [0, 0.1216, 0.2471],
  21116. blue: [0, 0.4549, 0.851],
  21117. aqua: [0.498, 0.8588, 1],
  21118. teal: [0.2235, 0.8, 0.8],
  21119. olive: [0.2392, 0.6, 0.4392],
  21120. green: [0.1804, 0.8, 0.251],
  21121. yellow: [1, 0.8627, 0],
  21122. orange: [1, 0.5216, 0.1059],
  21123. red: [1, 0.2549, 0.2118],
  21124. maroon: [0.5216, 0.0784, 0.2941],
  21125. fuchsia: [0.9412, 0.0706, 0.7451],
  21126. purple: [0.6941, 0.051, 0.7882],
  21127. });
  21128. const createDefaultFontSizeOptions = () => [16, 18, 20, 24, 30, 36, 48, 64, 72, 96, 144];
  21129. const createDefaultFontScaleOptions = () => ({
  21130. extraSmall: '2%',
  21131. small: '4%',
  21132. mediumSmall: '8%',
  21133. medium: '10%',
  21134. mediumLarge: '15%',
  21135. large: '20%',
  21136. extraLarge: '25%',
  21137. });
  21138. const createDefaultStrokeWidthOptions = () => [1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 48, 64];
  21139. const createDefaultStrokeScaleOptions = () => ({
  21140. extraSmall: '0.25%',
  21141. small: '0.5%',
  21142. mediumSmall: '1%',
  21143. medium: '1.75%',
  21144. mediumLarge: '2.5%',
  21145. large: '3.5%',
  21146. extraLarge: '5%',
  21147. });
  21148. const createDefaultLineEndStyleOptions = () => [
  21149. 'bar',
  21150. 'arrow',
  21151. 'arrowSolid',
  21152. 'circle',
  21153. 'circleSolid',
  21154. 'square',
  21155. 'squareSolid',
  21156. ];
  21157. const createDefaultFontFamilyOptions = () => [
  21158. [`Helvetica, Arial, Verdana, 'Droid Sans', sans-serif`, 'Sans Serif'],
  21159. [`'Arial Black', 'Avenir-Black', 'Arial Bold'`, 'Black'],
  21160. [`'Arial Narrow', 'Futura-CondensedMedium'`, 'Narrow'],
  21161. [`'Trebuchet MS'`, 'Humanist'],
  21162. [`Georgia, 'Avenir-Black', 'Times New Roman', 'Droid Serif', serif`, 'Serif'],
  21163. [`Palatino`, 'Old-Style'],
  21164. [`'Times New Roman', 'TimesNewRomanPSMT'`, 'Transitional'],
  21165. [`Menlo, Monaco, 'Lucida Console', monospace`, 'Monospaced'],
  21166. [`'Courier New', monospace`, 'Slab Serif'],
  21167. ];
  21168. const createDefaultTextAlignOptions = () => ['left', 'center', 'right'];
  21169. const createDefaultFontStyleOptions = () => [
  21170. ['normal', 'bold'],
  21171. ['italic', 'normal'],
  21172. ['italic', 'bold'],
  21173. ];
  21174. //#endregion
  21175. //#region style options
  21176. const createColorOptions = (colors) => Object.keys(colors).map(createLocaleMapper(colors, 'shapeTitleColor'));
  21177. const createFontSizeOptions = (sizes) => sizes.map(mapToSizeOption);
  21178. const createFontScaleOptions = (scales) => Object.keys(scales).map(createLocaleMapper(scales, 'labelSize'));
  21179. const createStrokeWidthOptions = (sizes) => sizes.map(mapToSizeOption);
  21180. const createStrokeScaleOptions = (scales) => Object.keys(scales).map(createLocaleMapper(scales, 'labelSize'));
  21181. const createFontFamilyOptions = (fonts) => [...fonts];
  21182. const createFontStyleOptions = (styles) => styles.map((style) => [
  21183. style,
  21184. (locale) => locale[`shapeLabelFontStyle${style
  21185. .filter((v) => v !== 'normal')
  21186. .map(upperCaseFirstLetter)
  21187. .join('')}`],
  21188. ]);
  21189. const createLineEndStyleOptions = (styles) => styles.map((style) => [
  21190. toKebabCase(style),
  21191. (locale) => locale[`shapeTitleLineDecoration${upperCaseFirstLetter(style)}`],
  21192. { icon: (locale) => locale[`shapeIconLineDecoration${upperCaseFirstLetter(style)}`] },
  21193. ]);
  21194. const createTextAlignOptions = (options) => options.map((align) => [
  21195. align,
  21196. (locale) => locale[`shapeTitleTextAlign${upperCaseFirstLetter(align)}`],
  21197. {
  21198. hideLabel: true,
  21199. icon: (locale) => locale[`shapeIconTextAlign${upperCaseFirstLetter(align)}`],
  21200. },
  21201. ]);
  21202. const createControlOptions = (items, options) => {
  21203. const { defaultKey, defaultOptions } = options || {};
  21204. let arr = [];
  21205. if (defaultKey)
  21206. arr[0] = [undefined, (locale) => locale[defaultKey], { ...defaultOptions }];
  21207. return [...arr, ...items];
  21208. };
  21209. //#endregion
  21210. //#region shape style controls
  21211. const someFontsAvailableInStack = (stack) => stack
  21212. .split(',')
  21213. .map((name) => name.trim())
  21214. .some((name) => {
  21215. // @ts-ignore
  21216. return document.fonts.check(`16px ${name}`);
  21217. });
  21218. const createColorControl = (items) => [
  21219. ColorPicker,
  21220. {
  21221. title: (locale) => locale.labelColor,
  21222. options: createControlOptions(items),
  21223. },
  21224. ];
  21225. const createSliderControl = (options = {}) => [
  21226. ToggleSlider,
  21227. {
  21228. ...options,
  21229. },
  21230. ];
  21231. const createFontFamilyControl = (fontFamilies) => [
  21232. Dropdown,
  21233. {
  21234. title: (locale) => locale.shapeTitleFontFamily,
  21235. onload: ({ options = [] }) => {
  21236. // can't check for font availability so don't
  21237. if (!canCheckFontAvailability())
  21238. return;
  21239. options
  21240. // map to font stack (option value)
  21241. .map(([stack]) => stack)
  21242. // filter out undefined
  21243. .filter(Boolean)
  21244. // filter out fonts that are available
  21245. .filter((stack) => !someFontsAvailableInStack(stack))
  21246. // remaining fonts should have dom elements for future check
  21247. .forEach((stack) => {
  21248. // get as id
  21249. const testId = `PinturaFontTest-${stack
  21250. .replace(/[^a-zA-Z0-9]+/g, '')
  21251. .toLowerCase()}`;
  21252. // already added this tester
  21253. if (document.getElementById(testId))
  21254. return;
  21255. // add font tester
  21256. document.body.appendChild(h('span', {
  21257. textContent: ' ',
  21258. id: testId,
  21259. style: `font-family:${stack};font-size:0;color:transparent;`,
  21260. }));
  21261. });
  21262. },
  21263. ondestroy: () => {
  21264. // can't check for font availability so no need to clean up
  21265. if (!canCheckFontAvailability())
  21266. return;
  21267. // clean up testers
  21268. const testers = document.querySelectorAll('.PinturaFontTest');
  21269. testers.forEach((tester) => tester.remove());
  21270. },
  21271. optionLabelStyle: (value) => `font-family: ${value}`,
  21272. options: createControlOptions(fontFamilies, { defaultKey: 'labelDefault' }),
  21273. optionFilter: (fontFamilyOption) => {
  21274. // don't filter if not in browser context
  21275. if (!canCheckFontAvailability())
  21276. return true;
  21277. // get font stack
  21278. const [stack] = fontFamilyOption;
  21279. // allow if undefined
  21280. if (!stack)
  21281. return true;
  21282. // filter out fonts that aren't available
  21283. const res = someFontsAvailableInStack(stack);
  21284. return res;
  21285. },
  21286. },
  21287. ];
  21288. const createBackgroundColorControl = (items) => [
  21289. ColorPicker,
  21290. {
  21291. title: (locale) => locale.shapeTitleBackgroundColor,
  21292. options: createControlOptions(items),
  21293. },
  21294. ];
  21295. const createStrokeColorControl = (items, options = {}) => [
  21296. ColorPicker,
  21297. {
  21298. title: (locale) => locale.shapeTitleStrokeColor,
  21299. options: createControlOptions(items),
  21300. buttonClass: 'PinturaColorPickerButtonStroke',
  21301. onchange: (value, shape) => {
  21302. // get shape strokeWidth as number
  21303. const strokeWidth = shape.strokeWidth;
  21304. const strokeWidthParsed = isNumber(strokeWidth) || isString(strokeWidth) ? parseFloat(strokeWidth) : 0;
  21305. // already has outline
  21306. if (strokeWidthParsed > 0)
  21307. return;
  21308. // set outline to first stroke width
  21309. shape.strokeWidth = (options && options.defaultStrokeWidth) || '0.5%';
  21310. },
  21311. },
  21312. ];
  21313. const createStrokeWidthControl = (items) => [
  21314. Dropdown,
  21315. {
  21316. title: (locale) => locale.shapeTitleStrokeWidth,
  21317. options: (shape) => {
  21318. if (hasProp(shape, 'backgroundColor'))
  21319. return createControlOptions(items, {
  21320. defaultKey: 'shapeLabelStrokeNone',
  21321. });
  21322. return createControlOptions(items);
  21323. },
  21324. },
  21325. ];
  21326. const createLineControl = (items, titleKey, optionIconStyle) => [
  21327. Dropdown,
  21328. {
  21329. title: (locale) => locale[titleKey],
  21330. options: createControlOptions(items, {
  21331. defaultKey: 'labelNone',
  21332. defaultOptions: {
  21333. icon: `<g stroke="currentColor" stroke-linecap="round" stroke-width=".125em"><path d="M5,12 H14"/></g>`,
  21334. },
  21335. }),
  21336. optionIconStyle,
  21337. },
  21338. ];
  21339. const createLineStartStyleControl = (items) => createLineControl(items, 'shapeTitleLineStart', `transform: scaleX(-1)`);
  21340. const createLineEndStyleControl = (items) => createLineControl(items, 'shapeTitleLineEnd');
  21341. const createFontColorControl = (items) => [
  21342. ColorPicker,
  21343. {
  21344. title: (locale) => locale.shapeTitleTextColor,
  21345. options: createControlOptions(items),
  21346. },
  21347. ];
  21348. const createFontStyleControl = (items) => [
  21349. Dropdown,
  21350. {
  21351. title: (locale) => locale.shapeTitleFontStyle,
  21352. optionLabelStyle: (value) => value && `font-style:${value[0]};font-weight:${value[1]}`,
  21353. options: createControlOptions(items, {
  21354. defaultKey: 'shapeLabelFontStyleNormal',
  21355. }),
  21356. },
  21357. ];
  21358. const createFontSizeControl = (items) => [
  21359. Dropdown,
  21360. {
  21361. title: (locale) => locale.shapeTitleFontSize,
  21362. options: createControlOptions(items, { defaultKey: 'labelDefault' }),
  21363. },
  21364. ];
  21365. const createTextAlignControl = (items) => [
  21366. RadioGroup,
  21367. {
  21368. title: (locale) => locale.shapeTitleTextAlign,
  21369. options: createControlOptions(items),
  21370. },
  21371. ];
  21372. const createLineHeightControl = (items) => [
  21373. Dropdown,
  21374. {
  21375. title: (locale) => locale.shapeTitleLineHeight,
  21376. options: createControlOptions(items, { defaultKey: 'labelAuto' }),
  21377. },
  21378. ];
  21379. const createShapeStyleControls = (options = {}) => {
  21380. const { colorOptions = createColorOptions(createDefaultColorOptions()), strokeWidthOptions = createStrokeScaleOptions(createDefaultStrokeScaleOptions()), lineEndStyleOptions = createLineEndStyleOptions(createDefaultLineEndStyleOptions()), fontFamilyOptions = createFontFamilyOptions(createDefaultFontFamilyOptions()), fontStyleOptions = createFontStyleOptions(createDefaultFontStyleOptions()), fontSizeOptions = createFontScaleOptions(createDefaultFontScaleOptions()), textAlignOptions = createTextAlignOptions(createDefaultTextAlignOptions()), } = options;
  21381. return {
  21382. // generic
  21383. defaultColor: colorOptions && createColorControl(colorOptions),
  21384. defaultNumber: createSliderControl(),
  21385. defaultPercentage: createSliderControl({
  21386. getValue: (value) => parseFloat(value),
  21387. setValue: (value) => `${value}%`,
  21388. step: 0.05,
  21389. label: (value, min, max) => `${Math.round((value / max) * 100)}%`,
  21390. labelClass: 'PinturaPercentageLabel',
  21391. }),
  21392. // shape background
  21393. backgroundColor: colorOptions && createBackgroundColorControl(colorOptions),
  21394. // line/outline
  21395. strokeColor: colorOptions && createStrokeColorControl(colorOptions),
  21396. strokeWidth: strokeWidthOptions && createStrokeWidthControl(strokeWidthOptions),
  21397. // line
  21398. lineStart: lineEndStyleOptions && createLineStartStyleControl(lineEndStyleOptions),
  21399. lineEnd: lineEndStyleOptions && createLineEndStyleControl(lineEndStyleOptions),
  21400. // text
  21401. color: colorOptions && createFontColorControl(colorOptions),
  21402. fontFamily: fontFamilyOptions && createFontFamilyControl(fontFamilyOptions),
  21403. fontStyle_fontWeight: fontStyleOptions && createFontStyleControl(fontStyleOptions),
  21404. fontSize: fontSizeOptions && createFontSizeControl(fontSizeOptions),
  21405. textAlign: textAlignOptions && createTextAlignControl(textAlignOptions),
  21406. // lineHeight: lineHeightOptions && createLineHeightControl(lineHeightOptions),
  21407. // generic options
  21408. frameColor: ['defaultColor'],
  21409. frameSize: [
  21410. 'defaultPercentage',
  21411. {
  21412. min: 0.2,
  21413. max: 10,
  21414. title: (locale) => locale.labelSize,
  21415. },
  21416. ],
  21417. frameInset: [
  21418. 'defaultPercentage',
  21419. { min: 0.5, max: 10, title: (locale) => locale.labelInset },
  21420. ],
  21421. frameOffset: [
  21422. 'defaultPercentage',
  21423. { min: 0.5, max: 10, title: (locale) => locale.labelOffset },
  21424. ],
  21425. frameRadius: [
  21426. 'defaultPercentage',
  21427. { min: 0.5, max: 10, title: (locale) => locale.labelRadius },
  21428. ],
  21429. frameAmount: [
  21430. 'defaultNumber',
  21431. { min: 1, max: 5, step: 1, title: (locale) => locale.labelAmount },
  21432. ],
  21433. };
  21434. };
  21435. //#endregion
  21436. /* src/core/ui/components/Measure.svelte generated by Svelte v3.37.0 */
  21437. function create_fragment$r(ctx) {
  21438. let div;
  21439. let current;
  21440. let mounted;
  21441. let dispose;
  21442. const default_slot_template = /*#slots*/ ctx[3].default;
  21443. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[2], null);
  21444. return {
  21445. c() {
  21446. div = element("div");
  21447. if (default_slot) default_slot.c();
  21448. attr(div, "class", /*klass*/ ctx[0]);
  21449. },
  21450. m(target, anchor) {
  21451. insert(target, div, anchor);
  21452. if (default_slot) {
  21453. default_slot.m(div, null);
  21454. }
  21455. current = true;
  21456. if (!mounted) {
  21457. dispose = [
  21458. listen(div, "measure", /*handleResize*/ ctx[1]),
  21459. action_destroyer(measurable.call(null, div))
  21460. ];
  21461. mounted = true;
  21462. }
  21463. },
  21464. p(ctx, [dirty]) {
  21465. if (default_slot) {
  21466. if (default_slot.p && dirty & /*$$scope*/ 4) {
  21467. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[2], dirty, null, null);
  21468. }
  21469. }
  21470. if (!current || dirty & /*klass*/ 1) {
  21471. attr(div, "class", /*klass*/ ctx[0]);
  21472. }
  21473. },
  21474. i(local) {
  21475. if (current) return;
  21476. transition_in(default_slot, local);
  21477. current = true;
  21478. },
  21479. o(local) {
  21480. transition_out(default_slot, local);
  21481. current = false;
  21482. },
  21483. d(detaching) {
  21484. if (detaching) detach(div);
  21485. if (default_slot) default_slot.d(detaching);
  21486. mounted = false;
  21487. run_all(dispose);
  21488. }
  21489. };
  21490. }
  21491. function instance$r($$self, $$props, $$invalidate) {
  21492. let { $$slots: slots = {}, $$scope } = $$props;
  21493. const dispatch = createEventDispatcher();
  21494. let { class: klass = null } = $$props;
  21495. const handleResize = ({ detail }) => dispatch("measure", detail);
  21496. $$self.$$set = $$props => {
  21497. if ("class" in $$props) $$invalidate(0, klass = $$props.class);
  21498. if ("$$scope" in $$props) $$invalidate(2, $$scope = $$props.$$scope);
  21499. };
  21500. return [klass, handleResize, $$scope, slots];
  21501. }
  21502. class Measure extends SvelteComponent {
  21503. constructor(options) {
  21504. super();
  21505. init(this, options, instance$r, create_fragment$r, safe_not_equal, { class: 0 });
  21506. }
  21507. }
  21508. /* src/core/ui/components/Util.svelte generated by Svelte v3.37.0 */
  21509. const get_footer_slot_changes = dirty => ({});
  21510. const get_footer_slot_context = ctx => ({});
  21511. const get_main_slot_changes = dirty => ({});
  21512. const get_main_slot_context = ctx => ({});
  21513. const get_header_slot_changes = dirty => ({});
  21514. const get_header_slot_context = ctx => ({});
  21515. // (10:0) {#if hasHeader}
  21516. function create_if_block_2$4(ctx) {
  21517. let div;
  21518. let current;
  21519. const header_slot_template = /*#slots*/ ctx[4].header;
  21520. const header_slot = create_slot(header_slot_template, ctx, /*$$scope*/ ctx[3], get_header_slot_context);
  21521. return {
  21522. c() {
  21523. div = element("div");
  21524. if (header_slot) header_slot.c();
  21525. attr(div, "class", "PinturaUtilHeader");
  21526. },
  21527. m(target, anchor) {
  21528. insert(target, div, anchor);
  21529. if (header_slot) {
  21530. header_slot.m(div, null);
  21531. }
  21532. current = true;
  21533. },
  21534. p(ctx, dirty) {
  21535. if (header_slot) {
  21536. if (header_slot.p && dirty & /*$$scope*/ 8) {
  21537. update_slot(header_slot, header_slot_template, ctx, /*$$scope*/ ctx[3], dirty, get_header_slot_changes, get_header_slot_context);
  21538. }
  21539. }
  21540. },
  21541. i(local) {
  21542. if (current) return;
  21543. transition_in(header_slot, local);
  21544. current = true;
  21545. },
  21546. o(local) {
  21547. transition_out(header_slot, local);
  21548. current = false;
  21549. },
  21550. d(detaching) {
  21551. if (detaching) detach(div);
  21552. if (header_slot) header_slot.d(detaching);
  21553. }
  21554. };
  21555. }
  21556. // (17:22) <Measure class="PinturaStage" on:measure />
  21557. function fallback_block(ctx) {
  21558. let measure;
  21559. let current;
  21560. measure = new Measure({ props: { class: "PinturaStage" } });
  21561. measure.$on("measure", /*measure_handler*/ ctx[5]);
  21562. return {
  21563. c() {
  21564. create_component(measure.$$.fragment);
  21565. },
  21566. m(target, anchor) {
  21567. mount_component(measure, target, anchor);
  21568. current = true;
  21569. },
  21570. p: noop,
  21571. i(local) {
  21572. if (current) return;
  21573. transition_in(measure.$$.fragment, local);
  21574. current = true;
  21575. },
  21576. o(local) {
  21577. transition_out(measure.$$.fragment, local);
  21578. current = false;
  21579. },
  21580. d(detaching) {
  21581. destroy_component(measure, detaching);
  21582. }
  21583. };
  21584. }
  21585. // (20:0) {#if hasFooter}
  21586. function create_if_block_1$5(ctx) {
  21587. let div;
  21588. let current;
  21589. const footer_slot_template = /*#slots*/ ctx[4].footer;
  21590. const footer_slot = create_slot(footer_slot_template, ctx, /*$$scope*/ ctx[3], get_footer_slot_context);
  21591. return {
  21592. c() {
  21593. div = element("div");
  21594. if (footer_slot) footer_slot.c();
  21595. attr(div, "class", "PinturaUtilFooter");
  21596. },
  21597. m(target, anchor) {
  21598. insert(target, div, anchor);
  21599. if (footer_slot) {
  21600. footer_slot.m(div, null);
  21601. }
  21602. current = true;
  21603. },
  21604. p(ctx, dirty) {
  21605. if (footer_slot) {
  21606. if (footer_slot.p && dirty & /*$$scope*/ 8) {
  21607. update_slot(footer_slot, footer_slot_template, ctx, /*$$scope*/ ctx[3], dirty, get_footer_slot_changes, get_footer_slot_context);
  21608. }
  21609. }
  21610. },
  21611. i(local) {
  21612. if (current) return;
  21613. transition_in(footer_slot, local);
  21614. current = true;
  21615. },
  21616. o(local) {
  21617. transition_out(footer_slot, local);
  21618. current = false;
  21619. },
  21620. d(detaching) {
  21621. if (detaching) detach(div);
  21622. if (footer_slot) footer_slot.d(detaching);
  21623. }
  21624. };
  21625. }
  21626. function create_fragment$q(ctx) {
  21627. let t0;
  21628. let div;
  21629. let t1;
  21630. let t2;
  21631. let if_block2_anchor;
  21632. let current;
  21633. let if_block0 = /*hasHeader*/ ctx[1] && create_if_block_2$4(ctx);
  21634. const main_slot_template = /*#slots*/ ctx[4].main;
  21635. const main_slot = create_slot(main_slot_template, ctx, /*$$scope*/ ctx[3], get_main_slot_context);
  21636. const main_slot_or_fallback = main_slot || fallback_block(ctx);
  21637. let if_block1 = /*hasFooter*/ ctx[2] && create_if_block_1$5(ctx);
  21638. let if_block2 = false ;
  21639. return {
  21640. c() {
  21641. if (if_block0) if_block0.c();
  21642. t0 = space();
  21643. div = element("div");
  21644. if (main_slot_or_fallback) main_slot_or_fallback.c();
  21645. t1 = space();
  21646. if (if_block1) if_block1.c();
  21647. t2 = space();
  21648. if_block2_anchor = empty();
  21649. attr(div, "class", "PinturaUtilMain");
  21650. },
  21651. m(target, anchor) {
  21652. if (if_block0) if_block0.m(target, anchor);
  21653. insert(target, t0, anchor);
  21654. insert(target, div, anchor);
  21655. if (main_slot_or_fallback) {
  21656. main_slot_or_fallback.m(div, null);
  21657. }
  21658. /*div_binding*/ ctx[6](div);
  21659. insert(target, t1, anchor);
  21660. if (if_block1) if_block1.m(target, anchor);
  21661. insert(target, t2, anchor);
  21662. insert(target, if_block2_anchor, anchor);
  21663. current = true;
  21664. },
  21665. p(ctx, [dirty]) {
  21666. if (/*hasHeader*/ ctx[1]) {
  21667. if (if_block0) {
  21668. if_block0.p(ctx, dirty);
  21669. if (dirty & /*hasHeader*/ 2) {
  21670. transition_in(if_block0, 1);
  21671. }
  21672. } else {
  21673. if_block0 = create_if_block_2$4(ctx);
  21674. if_block0.c();
  21675. transition_in(if_block0, 1);
  21676. if_block0.m(t0.parentNode, t0);
  21677. }
  21678. } else if (if_block0) {
  21679. group_outros();
  21680. transition_out(if_block0, 1, 1, () => {
  21681. if_block0 = null;
  21682. });
  21683. check_outros();
  21684. }
  21685. if (main_slot) {
  21686. if (main_slot.p && dirty & /*$$scope*/ 8) {
  21687. update_slot(main_slot, main_slot_template, ctx, /*$$scope*/ ctx[3], dirty, get_main_slot_changes, get_main_slot_context);
  21688. }
  21689. }
  21690. if (/*hasFooter*/ ctx[2]) {
  21691. if (if_block1) {
  21692. if_block1.p(ctx, dirty);
  21693. if (dirty & /*hasFooter*/ 4) {
  21694. transition_in(if_block1, 1);
  21695. }
  21696. } else {
  21697. if_block1 = create_if_block_1$5(ctx);
  21698. if_block1.c();
  21699. transition_in(if_block1, 1);
  21700. if_block1.m(t2.parentNode, t2);
  21701. }
  21702. } else if (if_block1) {
  21703. group_outros();
  21704. transition_out(if_block1, 1, 1, () => {
  21705. if_block1 = null;
  21706. });
  21707. check_outros();
  21708. }
  21709. },
  21710. i(local) {
  21711. if (current) return;
  21712. transition_in(if_block0);
  21713. transition_in(main_slot_or_fallback, local);
  21714. transition_in(if_block1);
  21715. transition_in(if_block2);
  21716. current = true;
  21717. },
  21718. o(local) {
  21719. transition_out(if_block0);
  21720. transition_out(main_slot_or_fallback, local);
  21721. transition_out(if_block1);
  21722. transition_out(if_block2);
  21723. current = false;
  21724. },
  21725. d(detaching) {
  21726. if (if_block0) if_block0.d(detaching);
  21727. if (detaching) detach(t0);
  21728. if (detaching) detach(div);
  21729. if (main_slot_or_fallback) main_slot_or_fallback.d(detaching);
  21730. /*div_binding*/ ctx[6](null);
  21731. if (detaching) detach(t1);
  21732. if (if_block1) if_block1.d(detaching);
  21733. if (detaching) detach(t2);
  21734. if (detaching) detach(if_block2_anchor);
  21735. }
  21736. };
  21737. }
  21738. function instance$q($$self, $$props, $$invalidate) {
  21739. let { $$slots: slots = {}, $$scope } = $$props;
  21740. let { hasHeader = !!$$props.$$slots.header } = $$props;
  21741. let { hasFooter = !!$$props.$$slots.footer } = $$props;
  21742. let { root = undefined } = $$props;
  21743. function measure_handler(event) {
  21744. bubble($$self, event);
  21745. }
  21746. function div_binding($$value) {
  21747. binding_callbacks[$$value ? "unshift" : "push"](() => {
  21748. root = $$value;
  21749. $$invalidate(0, root);
  21750. });
  21751. }
  21752. $$self.$$set = $$new_props => {
  21753. $$invalidate(7, $$props = assign(assign({}, $$props), exclude_internal_props($$new_props)));
  21754. if ("hasHeader" in $$new_props) $$invalidate(1, hasHeader = $$new_props.hasHeader);
  21755. if ("hasFooter" in $$new_props) $$invalidate(2, hasFooter = $$new_props.hasFooter);
  21756. if ("root" in $$new_props) $$invalidate(0, root = $$new_props.root);
  21757. if ("$$scope" in $$new_props) $$invalidate(3, $$scope = $$new_props.$$scope);
  21758. };
  21759. $$props = exclude_internal_props($$props);
  21760. return [root, hasHeader, hasFooter, $$scope, slots, measure_handler, div_binding];
  21761. }
  21762. class Util extends SvelteComponent {
  21763. constructor(options) {
  21764. super();
  21765. init(this, options, instance$q, create_fragment$q, safe_not_equal, { hasHeader: 1, hasFooter: 2, root: 0 });
  21766. }
  21767. }
  21768. /* src/core/ui/components/RangeInput.svelte generated by Svelte v3.37.0 */
  21769. function create_if_block$5(ctx) {
  21770. let div;
  21771. let div_style_value;
  21772. return {
  21773. c() {
  21774. div = element("div");
  21775. attr(div, "class", "PinturaRangeInputMeter");
  21776. attr(div, "style", div_style_value = `transform: translateX(${/*$position*/ ctx[8].x - /*svgPadding*/ ctx[9].x}px) translateY(${/*$position*/ ctx[8].y - /*svgPadding*/ ctx[9].y}px)`);
  21777. },
  21778. m(target, anchor) {
  21779. insert(target, div, anchor);
  21780. div.innerHTML = /*svg*/ ctx[6];
  21781. },
  21782. p(ctx, dirty) {
  21783. if (dirty[0] & /*svg*/ 64) div.innerHTML = /*svg*/ ctx[6];
  21784. if (dirty[0] & /*$position*/ 256 && div_style_value !== (div_style_value = `transform: translateX(${/*$position*/ ctx[8].x - /*svgPadding*/ ctx[9].x}px) translateY(${/*$position*/ ctx[8].y - /*svgPadding*/ ctx[9].y}px)`)) {
  21785. attr(div, "style", div_style_value);
  21786. }
  21787. },
  21788. d(detaching) {
  21789. if (detaching) detach(div);
  21790. }
  21791. };
  21792. }
  21793. function create_fragment$p(ctx) {
  21794. let div1;
  21795. let span;
  21796. let t0;
  21797. let t1;
  21798. let button;
  21799. let t2;
  21800. let button_disabled_value;
  21801. let t3;
  21802. let div0;
  21803. let mounted;
  21804. let dispose;
  21805. let if_block = /*$position*/ ctx[8] && create_if_block$5(ctx);
  21806. return {
  21807. c() {
  21808. div1 = element("div");
  21809. span = element("span");
  21810. t0 = text(/*valueLabel*/ ctx[3]);
  21811. t1 = space();
  21812. button = element("button");
  21813. t2 = text(/*labelReset*/ ctx[1]);
  21814. t3 = space();
  21815. div0 = element("div");
  21816. if (if_block) if_block.c();
  21817. attr(span, "class", "PinturaRangeInputValue");
  21818. attr(button, "class", "PinturaRangeInputReset");
  21819. attr(button, "type", "button");
  21820. button.disabled = button_disabled_value = /*value*/ ctx[0] === /*base*/ ctx[2];
  21821. attr(div0, "class", "PinturaRangeInputInner");
  21822. attr(div0, "style", /*rangeMask*/ ctx[7]);
  21823. attr(div0, "data-value-limited", /*isLimited*/ ctx[5]);
  21824. attr(div1, "class", "PinturaRangeInput");
  21825. attr(div1, "tabindex", "0");
  21826. },
  21827. m(target, anchor) {
  21828. insert(target, div1, anchor);
  21829. append(div1, span);
  21830. append(span, t0);
  21831. append(div1, t1);
  21832. append(div1, button);
  21833. append(button, t2);
  21834. append(div1, t3);
  21835. append(div1, div0);
  21836. if (if_block) if_block.m(div0, null);
  21837. if (!mounted) {
  21838. dispose = [
  21839. listen(button, "click", /*handleReset*/ ctx[14]),
  21840. listen(div0, "interactionstart", /*handleDragStart*/ ctx[10]),
  21841. listen(div0, "interactionupdate", /*handleDragMove*/ ctx[12]),
  21842. listen(div0, "interactionend", /*handleDragEnd*/ ctx[13]),
  21843. listen(div0, "interactionrelease", /*handleDragRelease*/ ctx[11]),
  21844. action_destroyer(interactable.call(null, div0, { inertia: true })),
  21845. listen(div0, "measure", /*measure_handler*/ ctx[32]),
  21846. action_destroyer(measurable.call(null, div0)),
  21847. listen(div1, "wheel", /*handleWheel*/ ctx[16], { passive: false }),
  21848. listen(div1, "nudge", /*handleNudge*/ ctx[17]),
  21849. action_destroyer(nudgeable.call(null, div1, { direction: "horizontal" }))
  21850. ];
  21851. mounted = true;
  21852. }
  21853. },
  21854. p(ctx, dirty) {
  21855. if (dirty[0] & /*valueLabel*/ 8) set_data(t0, /*valueLabel*/ ctx[3]);
  21856. if (dirty[0] & /*labelReset*/ 2) set_data(t2, /*labelReset*/ ctx[1]);
  21857. if (dirty[0] & /*value, base*/ 5 && button_disabled_value !== (button_disabled_value = /*value*/ ctx[0] === /*base*/ ctx[2])) {
  21858. button.disabled = button_disabled_value;
  21859. }
  21860. if (/*$position*/ ctx[8]) {
  21861. if (if_block) {
  21862. if_block.p(ctx, dirty);
  21863. } else {
  21864. if_block = create_if_block$5(ctx);
  21865. if_block.c();
  21866. if_block.m(div0, null);
  21867. }
  21868. } else if (if_block) {
  21869. if_block.d(1);
  21870. if_block = null;
  21871. }
  21872. if (dirty[0] & /*rangeMask*/ 128) {
  21873. attr(div0, "style", /*rangeMask*/ ctx[7]);
  21874. }
  21875. if (dirty[0] & /*isLimited*/ 32) {
  21876. attr(div0, "data-value-limited", /*isLimited*/ ctx[5]);
  21877. }
  21878. },
  21879. i: noop,
  21880. o: noop,
  21881. d(detaching) {
  21882. if (detaching) detach(div1);
  21883. if (if_block) if_block.d();
  21884. mounted = false;
  21885. run_all(dispose);
  21886. }
  21887. };
  21888. }
  21889. const radiusBig = 2; // 2
  21890. const radiusSmall = 0.75; // .75
  21891. const indicatorSpacing = 10;
  21892. const indicatorInterval = 5;
  21893. const indicatorCount = 40; // must be even
  21894. function instance$p($$self, $$props, $$invalidate) {
  21895. let range;
  21896. let valueMinLimited;
  21897. let valueMaxLimited;
  21898. let barSize;
  21899. let baseFraction;
  21900. let isLimited;
  21901. let rangeMask;
  21902. let $position;
  21903. let { labelReset = "Reset" } = $$props;
  21904. let { direction = "x" } = $$props;
  21905. let { min = 0 } = $$props;
  21906. let { max = 1 } = $$props;
  21907. let { base = min } = $$props;
  21908. let { value = 0 } = $$props;
  21909. let { valueLabel = 0 } = $$props;
  21910. let { valueMin = undefined } = $$props;
  21911. let { valueMax = undefined } = $$props;
  21912. let { oninputstart = noop$1 } = $$props;
  21913. let { oninputmove = noop$1 } = $$props;
  21914. let { oninputend = noop$1 } = $$props;
  21915. let { elasticity = 0 } = $$props;
  21916. const round = (number, increment, offset) => Math.ceil((number - offset) / increment) * increment + offset;
  21917. let size;
  21918. let svg;
  21919. let svgSize;
  21920. const svgPadding = { x: 2, y: 0 };
  21921. const createPathCircle = (cx, cy, r) => `M ${cx - r} ${cy} a ${r} ${r} 0 1 0 0 -1`;
  21922. function getMask(limitedMin, limitedMax) {
  21923. const step = 1 / indicatorCount;
  21924. const from = toFraction(limitedMin, min, max);
  21925. const to = toFraction(limitedMax, min, max);
  21926. const fromSnapped = fixPrecision(round(from, step, 0) - step * 0.5);
  21927. const toSnapped = fixPrecision(round(to, step, 0) - step * 0.5);
  21928. return `--range-mask-from:${fromSnapped * 100}%;--range-mask-to:${toSnapped * 100}%`;
  21929. }
  21930. //
  21931. // Dragging related
  21932. //
  21933. let interactionOrigin = undefined;
  21934. let interactionReleased = false;
  21935. let interactionRange;
  21936. let interactionOptions = { snap: false, elastic: false };
  21937. const handleDragStart = () => {
  21938. interactionReleased = false;
  21939. interactionOrigin = get_store_value(position);
  21940. interactionRange = [
  21941. valueToPosition(valueMin != null ? valueMin : min, direction),
  21942. valueToPosition(valueMax != null ? valueMax : max, direction)
  21943. ];
  21944. oninputstart();
  21945. };
  21946. const handleDragRelease = () => {
  21947. interactionReleased = true;
  21948. };
  21949. const handleDragMove = ({ detail }) => {
  21950. interactionOptions.snap = !interactionReleased;
  21951. interactionOptions.elastic = !interactionReleased;
  21952. translatePosition(interactionOrigin, detail.translation, interactionOptions);
  21953. };
  21954. const handleDragEnd = ({ detail }) => {
  21955. interactionOptions.snap = false;
  21956. interactionOptions.elastic = false;
  21957. const valueAtPosition = translatePosition(interactionOrigin, detail.translation, interactionOptions);
  21958. interactionOrigin = undefined;
  21959. interactionRange = undefined;
  21960. // if is near base position, set to base
  21961. if (Math.abs(valueAtPosition - base) < 0.01) return oninputend(base);
  21962. oninputend(valueAtPosition);
  21963. };
  21964. const translatePosition = (origin, translation, options) => {
  21965. const target = origin[direction] + translation[direction];
  21966. const targetLimited = clamp(target, interactionRange[1][direction], interactionRange[0][direction]);
  21967. const targetElastic = elasticity
  21968. ? targetLimited + elastify(target - targetLimited, elasticity)
  21969. : targetLimited;
  21970. const targetVisual = options.elastic ? targetElastic : targetLimited;
  21971. // set position
  21972. const targetValid = vectorCreate(0, 0);
  21973. targetValid[direction] = targetVisual;
  21974. position.set(targetValid, { hard: options.snap });
  21975. return clamp(positionToValue(targetValid, direction), min, max);
  21976. };
  21977. const handleReset = () => {
  21978. $$invalidate(0, value = clamp(base, valueMinLimited, valueMaxLimited));
  21979. oninputstart();
  21980. oninputend(value);
  21981. };
  21982. //
  21983. // Meter position and value updates
  21984. //
  21985. const position = spring();
  21986. component_subscribe($$self, position, value => $$invalidate(8, $position = value));
  21987. const valueToPosition = (value, axis) => {
  21988. const offset = (size[axis] - barSize[axis]) * 0.5;
  21989. const fraction = toFraction(value, min, max);
  21990. const v = fraction * barSize[axis] - barSize[axis] * 0.5;
  21991. const pos = offset - v;
  21992. return {
  21993. x: axis === "x" ? pos : 0,
  21994. y: axis === "y" ? pos : 0
  21995. };
  21996. };
  21997. const positionToValue = (position, axis) => {
  21998. const dist = position[axis] - size[axis] * 0.5;
  21999. const fraction = -(dist / barSize[axis]);
  22000. return min + fraction * range;
  22001. };
  22002. position.subscribe(currentPosition => {
  22003. // if not positioned yet or is not interacting we're not interested in this event
  22004. if (!currentPosition || !interactionOrigin) return;
  22005. oninputmove(clamp(positionToValue(currentPosition, direction), min, max));
  22006. });
  22007. const updatePosition = value => {
  22008. const interactionRange = [
  22009. valueToPosition(valueMin != null ? valueMin : min, direction),
  22010. valueToPosition(valueMax != null ? valueMax : max, direction)
  22011. ];
  22012. const target = {
  22013. x: direction === "x" ? $position.x + value : 0,
  22014. y: direction === "y" ? $position.y + value : 0
  22015. };
  22016. const targetLimited = clamp(target[direction], interactionRange[1][direction], interactionRange[0][direction]);
  22017. const positionTarget = { ...$position, [direction]: targetLimited };
  22018. set_store_value(position, $position = positionTarget, $position);
  22019. const result = clamp(positionToValue(positionTarget, direction), min, max);
  22020. oninputstart();
  22021. oninputmove(result);
  22022. oninputend(result);
  22023. };
  22024. const handleWheel = e => {
  22025. // don't run default actions, prevent other actions from running
  22026. e.preventDefault();
  22027. e.stopPropagation();
  22028. // apply wheel delta to offset
  22029. const step = 8;
  22030. const delta = getWheelDelta(e) * step;
  22031. updatePosition(delta);
  22032. };
  22033. const handleNudge = ({ detail }) => {
  22034. updatePosition(detail[direction] * 8);
  22035. };
  22036. const measure_handler = e => $$invalidate(4, size = vectorCreateFromSize(e.detail));
  22037. $$self.$$set = $$props => {
  22038. if ("labelReset" in $$props) $$invalidate(1, labelReset = $$props.labelReset);
  22039. if ("direction" in $$props) $$invalidate(18, direction = $$props.direction);
  22040. if ("min" in $$props) $$invalidate(19, min = $$props.min);
  22041. if ("max" in $$props) $$invalidate(20, max = $$props.max);
  22042. if ("base" in $$props) $$invalidate(2, base = $$props.base);
  22043. if ("value" in $$props) $$invalidate(0, value = $$props.value);
  22044. if ("valueLabel" in $$props) $$invalidate(3, valueLabel = $$props.valueLabel);
  22045. if ("valueMin" in $$props) $$invalidate(21, valueMin = $$props.valueMin);
  22046. if ("valueMax" in $$props) $$invalidate(22, valueMax = $$props.valueMax);
  22047. if ("oninputstart" in $$props) $$invalidate(23, oninputstart = $$props.oninputstart);
  22048. if ("oninputmove" in $$props) $$invalidate(24, oninputmove = $$props.oninputmove);
  22049. if ("oninputend" in $$props) $$invalidate(25, oninputend = $$props.oninputend);
  22050. if ("elasticity" in $$props) $$invalidate(26, elasticity = $$props.elasticity);
  22051. };
  22052. $$self.$$.update = () => {
  22053. if ($$self.$$.dirty[0] & /*max, min*/ 1572864) {
  22054. //
  22055. // derived
  22056. //
  22057. $$invalidate(28, range = max - min);
  22058. }
  22059. if ($$self.$$.dirty[0] & /*valueMin, min*/ 2621440) {
  22060. $$invalidate(29, valueMinLimited = valueMin != null ? Math.max(valueMin, min) : min);
  22061. }
  22062. if ($$self.$$.dirty[0] & /*valueMax, max*/ 5242880) {
  22063. $$invalidate(30, valueMaxLimited = valueMax != null ? Math.min(valueMax, max) : max);
  22064. }
  22065. if ($$self.$$.dirty[0] & /*base, min, max*/ 1572868) {
  22066. $$invalidate(31, baseFraction = toFraction(base, min, max));
  22067. }
  22068. if ($$self.$$.dirty[0] & /*size*/ 16 | $$self.$$.dirty[1] & /*baseFraction*/ 1) {
  22069. if (size) {
  22070. const centerY = size.y * 0.5;
  22071. let indicatorCenter = indicatorCount * baseFraction;
  22072. let d = "";
  22073. let svgWidth;
  22074. let svgHeight = size.y;
  22075. let centerShape = "";
  22076. for (let i = 0; i <= indicatorCount; i++) {
  22077. const x = svgPadding.x + i * indicatorSpacing;
  22078. const y = centerY;
  22079. const r = i % indicatorInterval === 0 ? radiusBig : radiusSmall;
  22080. d += createPathCircle(x, y, r) + " ";
  22081. svgWidth = x + svgPadding.x;
  22082. if (i === indicatorCenter) {
  22083. centerShape = `<path d="M${x} ${y - 4} l2 3 l-2 -1 l-2 1 z"/>`;
  22084. }
  22085. }
  22086. $$invalidate(6, svg = `<svg width="${svgWidth}" height="${svgHeight}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${svgWidth} ${svgHeight}" aria-hidden="true" focusable="false">
  22087. ${centerShape}
  22088. <rect rx="4" ry="4" y="${centerY - 4}"" height="8"/>
  22089. <path fill-rule="evenodd" d="${d.trim()}"/></svg>`);
  22090. $$invalidate(27, svgSize = {
  22091. x: svgWidth - svgPadding.x * 2,
  22092. y: svgHeight
  22093. });
  22094. }
  22095. }
  22096. if ($$self.$$.dirty[0] & /*size, svgSize*/ 134217744) {
  22097. barSize = size && svgSize;
  22098. }
  22099. if ($$self.$$.dirty[0] & /*valueMinLimited, min, valueMaxLimited, max*/ 1612185600) {
  22100. $$invalidate(5, isLimited = valueMinLimited !== min || valueMaxLimited !== max);
  22101. }
  22102. if ($$self.$$.dirty[0] & /*isLimited, valueMinLimited, valueMaxLimited*/ 1610612768) {
  22103. $$invalidate(7, rangeMask = isLimited
  22104. ? getMask(valueMinLimited, valueMaxLimited)
  22105. : "");
  22106. }
  22107. if ($$self.$$.dirty[0] & /*range, size, value, direction*/ 268697617) {
  22108. // if has size (range is in here so the position is updated if the range is changed)
  22109. if (range && size && size.x && size.y) {
  22110. position.set(valueToPosition(value, direction));
  22111. }
  22112. }
  22113. };
  22114. return [
  22115. value,
  22116. labelReset,
  22117. base,
  22118. valueLabel,
  22119. size,
  22120. isLimited,
  22121. svg,
  22122. rangeMask,
  22123. $position,
  22124. svgPadding,
  22125. handleDragStart,
  22126. handleDragRelease,
  22127. handleDragMove,
  22128. handleDragEnd,
  22129. handleReset,
  22130. position,
  22131. handleWheel,
  22132. handleNudge,
  22133. direction,
  22134. min,
  22135. max,
  22136. valueMin,
  22137. valueMax,
  22138. oninputstart,
  22139. oninputmove,
  22140. oninputend,
  22141. elasticity,
  22142. svgSize,
  22143. range,
  22144. valueMinLimited,
  22145. valueMaxLimited,
  22146. baseFraction,
  22147. measure_handler
  22148. ];
  22149. }
  22150. class RangeInput extends SvelteComponent {
  22151. constructor(options) {
  22152. super();
  22153. init(
  22154. this,
  22155. options,
  22156. instance$p,
  22157. create_fragment$p,
  22158. safe_not_equal,
  22159. {
  22160. labelReset: 1,
  22161. direction: 18,
  22162. min: 19,
  22163. max: 20,
  22164. base: 2,
  22165. value: 0,
  22166. valueLabel: 3,
  22167. valueMin: 21,
  22168. valueMax: 22,
  22169. oninputstart: 23,
  22170. oninputmove: 24,
  22171. oninputend: 25,
  22172. elasticity: 26
  22173. },
  22174. [-1, -1]
  22175. );
  22176. }
  22177. }
  22178. /* src/core/ui/components/Toolbar.svelte generated by Svelte v3.37.0 */
  22179. function create_fragment$o(ctx) {
  22180. let div1;
  22181. let div0;
  22182. let current;
  22183. let mounted;
  22184. let dispose;
  22185. const default_slot_template = /*#slots*/ ctx[7].default;
  22186. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[6], null);
  22187. return {
  22188. c() {
  22189. div1 = element("div");
  22190. div0 = element("div");
  22191. if (default_slot) default_slot.c();
  22192. attr(div0, "class", "PinturaToolbarInner");
  22193. attr(div1, "class", "PinturaToolbar");
  22194. attr(div1, "data-layout", /*layout*/ ctx[1]);
  22195. attr(div1, "data-overflow", /*overflow*/ ctx[0]);
  22196. },
  22197. m(target, anchor) {
  22198. insert(target, div1, anchor);
  22199. append(div1, div0);
  22200. if (default_slot) {
  22201. default_slot.m(div0, null);
  22202. }
  22203. current = true;
  22204. if (!mounted) {
  22205. dispose = [
  22206. listen(div0, "measure", /*handleChildResizeEvent*/ ctx[3]),
  22207. action_destroyer(measurable.call(null, div0)),
  22208. listen(div1, "measure", /*handleParentResizeEvent*/ ctx[2]),
  22209. action_destroyer(measurable.call(null, div1))
  22210. ];
  22211. mounted = true;
  22212. }
  22213. },
  22214. p(ctx, [dirty]) {
  22215. if (default_slot) {
  22216. if (default_slot.p && dirty & /*$$scope*/ 64) {
  22217. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[6], dirty, null, null);
  22218. }
  22219. }
  22220. if (!current || dirty & /*layout*/ 2) {
  22221. attr(div1, "data-layout", /*layout*/ ctx[1]);
  22222. }
  22223. if (!current || dirty & /*overflow*/ 1) {
  22224. attr(div1, "data-overflow", /*overflow*/ ctx[0]);
  22225. }
  22226. },
  22227. i(local) {
  22228. if (current) return;
  22229. transition_in(default_slot, local);
  22230. current = true;
  22231. },
  22232. o(local) {
  22233. transition_out(default_slot, local);
  22234. current = false;
  22235. },
  22236. d(detaching) {
  22237. if (detaching) detach(div1);
  22238. if (default_slot) default_slot.d(detaching);
  22239. mounted = false;
  22240. run_all(dispose);
  22241. }
  22242. };
  22243. }
  22244. function instance$o($$self, $$props, $$invalidate) {
  22245. let layout;
  22246. let { $$slots: slots = {}, $$scope } = $$props;
  22247. let childWidth = 0;
  22248. let childMaxWidth = 0;
  22249. let parentWidth = 0;
  22250. let overflow;
  22251. const testOverflow = () => {
  22252. $$invalidate(0, overflow = layout === "compact" && childWidth > parentWidth
  22253. ? "overflow"
  22254. : undefined);
  22255. };
  22256. const handleParentResizeEvent = ({ detail }) => {
  22257. const { width } = detail;
  22258. $$invalidate(5, parentWidth = width);
  22259. testOverflow();
  22260. };
  22261. const handleChildResizeEvent = ({ detail }) => {
  22262. const { width } = detail;
  22263. if (width > childMaxWidth) {
  22264. $$invalidate(4, childMaxWidth = width);
  22265. }
  22266. childWidth = width;
  22267. if (!overflow) testOverflow();
  22268. };
  22269. $$self.$$set = $$props => {
  22270. if ("$$scope" in $$props) $$invalidate(6, $$scope = $$props.$$scope);
  22271. };
  22272. $$self.$$.update = () => {
  22273. if ($$self.$$.dirty & /*childMaxWidth, parentWidth*/ 48) {
  22274. $$invalidate(1, layout = childMaxWidth > parentWidth ? "compact" : "default");
  22275. }
  22276. };
  22277. return [
  22278. overflow,
  22279. layout,
  22280. handleParentResizeEvent,
  22281. handleChildResizeEvent,
  22282. childMaxWidth,
  22283. parentWidth,
  22284. $$scope,
  22285. slots
  22286. ];
  22287. }
  22288. class Toolbar extends SvelteComponent {
  22289. constructor(options) {
  22290. super();
  22291. init(this, options, instance$o, create_fragment$o, safe_not_equal, {});
  22292. }
  22293. }
  22294. // enum Direction {
  22295. // Top = 't',
  22296. // Right = 'r',
  22297. // Bottom = 'b',
  22298. // Left = 'l',
  22299. // TopLeft = 'tl',
  22300. // TopRight = 'tr',
  22301. // BottomRight = 'br',
  22302. // BottomLeft = 'bl',
  22303. // }
  22304. // export const { Top, Right, Bottom, Left, TopLeft, TopRight, BottomRight, BottomLeft } = Direction;
  22305. // export default Direction;
  22306. const Direction = {
  22307. Top: 't',
  22308. Right: 'r',
  22309. Bottom: 'b',
  22310. Left: 'l',
  22311. TopLeft: 'tl',
  22312. TopRight: 'tr',
  22313. BottomRight: 'br',
  22314. BottomLeft: 'bl',
  22315. };
  22316. const { Top, Right, Bottom, Left, TopLeft, TopRight, BottomRight, BottomLeft } = Direction;
  22317. var DirectionRectMap = {
  22318. [Top]: (rect) => ({ x: rect.x, y: rect.y }),
  22319. [TopRight]: (rect) => ({ x: rect.x + rect.width, y: rect.y }),
  22320. [Right]: (rect) => ({ x: rect.x + rect.width, y: rect.y }),
  22321. [BottomRight]: (rect) => ({ x: rect.x + rect.width, y: rect.y + rect.height }),
  22322. [Bottom]: (rect) => ({ x: rect.x, y: rect.y + rect.height }),
  22323. [BottomLeft]: (rect) => ({ x: rect.x, y: rect.y + rect.height }),
  22324. [Left]: (rect) => ({ x: rect.x, y: rect.y }),
  22325. [TopLeft]: (rect) => ({ x: rect.x, y: rect.y }),
  22326. };
  22327. /* src/core/ui/components/RectManipulator.svelte generated by Svelte v3.37.0 */
  22328. function get_each_context$5(ctx, list, i) {
  22329. const child_ctx = ctx.slice();
  22330. child_ctx[12] = list[i].key;
  22331. child_ctx[13] = list[i].translate;
  22332. child_ctx[14] = list[i].scale;
  22333. child_ctx[15] = list[i].type;
  22334. child_ctx[16] = list[i].opacity;
  22335. return child_ctx;
  22336. }
  22337. // (107:0) {#each mappedDirections as { key, translate, scale, type, opacity }
  22338. function create_each_block$5(key_1, ctx) {
  22339. let div;
  22340. let div_aria_label_value;
  22341. let div_tabindex_value;
  22342. let div_data_direction_value;
  22343. let div_data_shape_value;
  22344. let div_style_value;
  22345. let mounted;
  22346. let dispose;
  22347. return {
  22348. key: key_1,
  22349. first: null,
  22350. c() {
  22351. div = element("div");
  22352. attr(div, "role", "button");
  22353. attr(div, "aria-label", div_aria_label_value = `Drag ${/*type*/ ctx[15]} ${/*key*/ ctx[12]}`);
  22354. attr(div, "tabindex", div_tabindex_value = /*type*/ ctx[15] === "edge" ? -1 : 0);
  22355. attr(div, "class", "PinturaRectManipulator");
  22356. attr(div, "data-direction", div_data_direction_value = /*key*/ ctx[12]);
  22357. attr(div, "data-shape", div_data_shape_value = `${/*type*/ ctx[15] === "edge"
  22358. ? "edge"
  22359. : `${/*style*/ ctx[0]}`}`);
  22360. attr(div, "style", div_style_value = `transform: translate3d(${/*translate*/ ctx[13].x}px, ${/*translate*/ ctx[13].y}px, 0) scale(${/*scale*/ ctx[14].x}, ${/*scale*/ ctx[14].y}); opacity: ${/*opacity*/ ctx[16]}`);
  22361. this.first = div;
  22362. },
  22363. m(target, anchor) {
  22364. insert(target, div, anchor);
  22365. if (!mounted) {
  22366. dispose = [
  22367. listen(div, "nudge", function () {
  22368. if (is_function(/*nudge*/ ctx[5](/*key*/ ctx[12]))) /*nudge*/ ctx[5](/*key*/ ctx[12]).apply(this, arguments);
  22369. }),
  22370. action_destroyer(nudgeable.call(null, div)),
  22371. listen(div, "interactionstart", function () {
  22372. if (is_function(/*route*/ ctx[4]("resizestart", /*key*/ ctx[12]))) /*route*/ ctx[4]("resizestart", /*key*/ ctx[12]).apply(this, arguments);
  22373. }),
  22374. listen(div, "interactionupdate", function () {
  22375. if (is_function(/*route*/ ctx[4]("resizemove", /*key*/ ctx[12]))) /*route*/ ctx[4]("resizemove", /*key*/ ctx[12]).apply(this, arguments);
  22376. }),
  22377. listen(div, "interactionend", function () {
  22378. if (is_function(/*route*/ ctx[4]("resizeend", /*key*/ ctx[12]))) /*route*/ ctx[4]("resizeend", /*key*/ ctx[12]).apply(this, arguments);
  22379. }),
  22380. action_destroyer(interactable.call(null, div))
  22381. ];
  22382. mounted = true;
  22383. }
  22384. },
  22385. p(new_ctx, dirty) {
  22386. ctx = new_ctx;
  22387. if (dirty & /*mappedDirections*/ 2 && div_aria_label_value !== (div_aria_label_value = `Drag ${/*type*/ ctx[15]} ${/*key*/ ctx[12]}`)) {
  22388. attr(div, "aria-label", div_aria_label_value);
  22389. }
  22390. if (dirty & /*mappedDirections*/ 2 && div_tabindex_value !== (div_tabindex_value = /*type*/ ctx[15] === "edge" ? -1 : 0)) {
  22391. attr(div, "tabindex", div_tabindex_value);
  22392. }
  22393. if (dirty & /*mappedDirections*/ 2 && div_data_direction_value !== (div_data_direction_value = /*key*/ ctx[12])) {
  22394. attr(div, "data-direction", div_data_direction_value);
  22395. }
  22396. if (dirty & /*mappedDirections, style*/ 3 && div_data_shape_value !== (div_data_shape_value = `${/*type*/ ctx[15] === "edge"
  22397. ? "edge"
  22398. : `${/*style*/ ctx[0]}`}`)) {
  22399. attr(div, "data-shape", div_data_shape_value);
  22400. }
  22401. if (dirty & /*mappedDirections*/ 2 && div_style_value !== (div_style_value = `transform: translate3d(${/*translate*/ ctx[13].x}px, ${/*translate*/ ctx[13].y}px, 0) scale(${/*scale*/ ctx[14].x}, ${/*scale*/ ctx[14].y}); opacity: ${/*opacity*/ ctx[16]}`)) {
  22402. attr(div, "style", div_style_value);
  22403. }
  22404. },
  22405. d(detaching) {
  22406. if (detaching) detach(div);
  22407. mounted = false;
  22408. run_all(dispose);
  22409. }
  22410. };
  22411. }
  22412. function create_fragment$n(ctx) {
  22413. let each_blocks = [];
  22414. let each_1_lookup = new Map();
  22415. let each_1_anchor;
  22416. let each_value = /*mappedDirections*/ ctx[1];
  22417. const get_key = ctx => /*key*/ ctx[12];
  22418. for (let i = 0; i < each_value.length; i += 1) {
  22419. let child_ctx = get_each_context$5(ctx, each_value, i);
  22420. let key = get_key(child_ctx);
  22421. each_1_lookup.set(key, each_blocks[i] = create_each_block$5(key, child_ctx));
  22422. }
  22423. return {
  22424. c() {
  22425. for (let i = 0; i < each_blocks.length; i += 1) {
  22426. each_blocks[i].c();
  22427. }
  22428. each_1_anchor = empty();
  22429. },
  22430. m(target, anchor) {
  22431. for (let i = 0; i < each_blocks.length; i += 1) {
  22432. each_blocks[i].m(target, anchor);
  22433. }
  22434. insert(target, each_1_anchor, anchor);
  22435. },
  22436. p(ctx, [dirty]) {
  22437. if (dirty & /*mappedDirections, style, nudge, route*/ 51) {
  22438. each_value = /*mappedDirections*/ ctx[1];
  22439. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, destroy_block, create_each_block$5, each_1_anchor, get_each_context$5);
  22440. }
  22441. },
  22442. i: noop,
  22443. o: noop,
  22444. d(detaching) {
  22445. for (let i = 0; i < each_blocks.length; i += 1) {
  22446. each_blocks[i].d(detaching);
  22447. }
  22448. if (detaching) detach(each_1_anchor);
  22449. }
  22450. };
  22451. }
  22452. function instance$n($$self, $$props, $$invalidate) {
  22453. let mappedDirections;
  22454. let $selectionScale;
  22455. let $selectionOpacity;
  22456. let { rect = null } = $$props;
  22457. let { visible = false } = $$props;
  22458. let { style = undefined } = $$props;
  22459. // is `undefined` to prevent bounce when first rendering view
  22460. const selectionScale = spring(undefined, {
  22461. precision: 0.0001,
  22462. stiffness: 0.2,
  22463. damping: 0.4
  22464. });
  22465. component_subscribe($$self, selectionScale, value => $$invalidate(8, $selectionScale = value));
  22466. const selectionOpacity = spring(0, { precision: 0.001 });
  22467. component_subscribe($$self, selectionOpacity, value => $$invalidate(9, $selectionOpacity = value));
  22468. //
  22469. // dragging
  22470. //
  22471. let currentDirection;
  22472. const dispatch = createEventDispatcher();
  22473. const route = (type, direction) => ({ detail }) => {
  22474. // don't handle other interactions while manipulating on axis
  22475. if (currentDirection && direction !== currentDirection) return;
  22476. // ignore move and end events if no direction has been set
  22477. if (type !== "resizestart" && currentDirection === undefined) return;
  22478. // set new direction
  22479. if (type === "resizestart") currentDirection = direction;
  22480. // release direction
  22481. if (type === "resizeend") currentDirection = undefined;
  22482. dispatch(type, {
  22483. direction,
  22484. translation: detail && detail.translation
  22485. });
  22486. };
  22487. const nudge = direction => ({ detail }) => {
  22488. dispatch(`resizestart`, { direction, translation: { x: 0, y: 0 } });
  22489. dispatch(`resizemove`, { direction, translation: detail });
  22490. dispatch(`resizeend`, { direction, translation: { x: 0, y: 0 } });
  22491. };
  22492. $$self.$$set = $$props => {
  22493. if ("rect" in $$props) $$invalidate(6, rect = $$props.rect);
  22494. if ("visible" in $$props) $$invalidate(7, visible = $$props.visible);
  22495. if ("style" in $$props) $$invalidate(0, style = $$props.style);
  22496. };
  22497. $$self.$$.update = () => {
  22498. if ($$self.$$.dirty & /*visible*/ 128) {
  22499. selectionScale.set(visible ? 1 : 0.5);
  22500. }
  22501. if ($$self.$$.dirty & /*visible*/ 128) {
  22502. selectionOpacity.set(visible ? 1 : 0);
  22503. }
  22504. if ($$self.$$.dirty & /*rect, $selectionScale, $selectionOpacity*/ 832) {
  22505. //
  22506. // rendering
  22507. //
  22508. $$invalidate(1, mappedDirections = Object.keys(Direction).map((key, i) => {
  22509. // get direction enum
  22510. const direction = Direction[key];
  22511. // get position from direction
  22512. const position = DirectionRectMap[direction](rect);
  22513. // corner or edge
  22514. const type = direction.length === 1 ? "edge" : "corner";
  22515. const isCorner = type === "corner";
  22516. return {
  22517. key: direction,
  22518. type,
  22519. scale: {
  22520. x: (/^(t|b)$/).test(direction)
  22521. ? rect.width
  22522. : isCorner ? clamp($selectionScale, 0.5, 1.25) : 1,
  22523. y: (/^(r|l)$/).test(direction)
  22524. ? rect.height
  22525. : isCorner ? clamp($selectionScale, 0.5, 1.25) : 1
  22526. },
  22527. translate: { x: position.x, y: position.y },
  22528. opacity: $selectionOpacity
  22529. };
  22530. }));
  22531. }
  22532. };
  22533. return [
  22534. style,
  22535. mappedDirections,
  22536. selectionScale,
  22537. selectionOpacity,
  22538. route,
  22539. nudge,
  22540. rect,
  22541. visible,
  22542. $selectionScale,
  22543. $selectionOpacity
  22544. ];
  22545. }
  22546. class RectManipulator extends SvelteComponent {
  22547. constructor(options) {
  22548. super();
  22549. init(this, options, instance$n, create_fragment$n, safe_not_equal, { rect: 6, visible: 7, style: 0 });
  22550. }
  22551. }
  22552. var gesturable = (element) => {
  22553. function dispatch(type, detail) {
  22554. element.dispatchEvent(new CustomEvent(type, { detail }));
  22555. }
  22556. const handleGestureStart = (e) => {
  22557. e.preventDefault();
  22558. element.addEventListener('gesturechange', handleGestureChange);
  22559. element.addEventListener('gestureend', handleGestureEnd);
  22560. dispatch('gesturedown');
  22561. };
  22562. const handleGestureChange = (e) => {
  22563. e.preventDefault();
  22564. dispatch('gestureupdate', e.scale);
  22565. };
  22566. const handleGestureEnd = (e) => {
  22567. dispatch('gestureup', e.scale);
  22568. e.preventDefault();
  22569. clean();
  22570. };
  22571. const clean = () => {
  22572. element.removeEventListener('gesturechange', handleGestureChange);
  22573. element.removeEventListener('gestureend', handleGestureEnd);
  22574. };
  22575. element.addEventListener('gesturestart', handleGestureStart);
  22576. return {
  22577. destroy: () => {
  22578. clean();
  22579. element.removeEventListener('gesturestart', handleGestureStart);
  22580. },
  22581. };
  22582. };
  22583. var getEventPositionInViewport = (e) => vectorCreate(e.clientX, e.clientY);
  22584. var getEventPositionInStage = (e, viewOffset, stageOffset) => {
  22585. const positionInViewport = getEventPositionInViewport(e);
  22586. return vectorSubtract(vectorSubtract(positionInViewport, viewOffset), stageOffset);
  22587. };
  22588. var DirectionInversionTable = {
  22589. [Top]: Bottom,
  22590. [Right]: Left,
  22591. [Bottom]: Top,
  22592. [Left]: Right,
  22593. [TopLeft]: BottomRight,
  22594. [TopRight]: BottomLeft,
  22595. [BottomRight]: TopLeft,
  22596. [BottomLeft]: TopRight,
  22597. };
  22598. var DirectionCoordinateTable = {
  22599. [Top]: [0.5, 0],
  22600. [Right]: [1, 0.5],
  22601. [Bottom]: [0.5, 1],
  22602. [Left]: [0, 0.5],
  22603. [TopLeft]: [0, 0],
  22604. [TopRight]: [1, 0],
  22605. [BottomRight]: [1, 1],
  22606. [BottomLeft]: [0, 1],
  22607. };
  22608. var getTranslationInfo = (target) => {
  22609. const translateToRight = target === Right || target === TopRight || target === BottomRight;
  22610. const translateToLeft = target === Left || target === BottomLeft || target === TopLeft;
  22611. const translateToTop = target === Top || target === TopRight || target === TopLeft;
  22612. const translateToBottom = target === Bottom || target === BottomRight || target === BottomLeft;
  22613. const translateHorizontally = target === Left || target === Right;
  22614. const translateVertically = target === Top || target === Bottom;
  22615. const translateAxis = translateHorizontally || translateVertically;
  22616. return [
  22617. translateToRight,
  22618. translateToLeft,
  22619. translateToTop,
  22620. translateToBottom,
  22621. translateHorizontally,
  22622. translateVertically,
  22623. translateAxis,
  22624. ];
  22625. };
  22626. var limitRectDirectionTranslation = (rect, transform, bounds, options = {}) => {
  22627. // the transforms to apply
  22628. const { target, translate } = transform;
  22629. // the transform requirements
  22630. const { aspectRatio, minSize, maxSize } = options;
  22631. // get anchor coordinates and x,y position we need this for relative scaling of the view rectangle
  22632. const anchor = DirectionInversionTable[target];
  22633. const anchorDirectionCoordinates = DirectionCoordinateTable[anchor];
  22634. const anchorPosition = vectorAdd(vectorCreate(rect.x, rect.y), vectorCreate(anchorDirectionCoordinates[0] * rect.width, anchorDirectionCoordinates[1] * rect.height));
  22635. // get coordinate of direction
  22636. const targetDirectionCoordinates = DirectionCoordinateTable[target];
  22637. const targetPosition = vectorAdd(rectClone(rect), vectorCreate(targetDirectionCoordinates[0] * rect.width, targetDirectionCoordinates[1] * rect.height));
  22638. // bools to determine which direction the interaction is moving in
  22639. const [translateToRight, translateToLeft, translateToTop, translateToBottom, translateHorizontally, translateVertically, translateAxis,] = getTranslationInfo(target);
  22640. let tx = translate.x;
  22641. let ty = translate.y;
  22642. if (translateHorizontally)
  22643. ty = 0;
  22644. else if (translateVertically)
  22645. tx = 0;
  22646. const interactionBounds = getInteractionBounds(anchorPosition, target, bounds, {
  22647. aspectRatio,
  22648. minSize,
  22649. maxSize,
  22650. });
  22651. // current bounds
  22652. let [t, r, b, l] = rectToBounds(rect);
  22653. // update view bounds with anchor based on translation direction (one side is always locked)
  22654. if (translateToRight)
  22655. l = anchorPosition.x;
  22656. else if (translateToLeft)
  22657. r = anchorPosition.x;
  22658. if (translateToBottom)
  22659. t = anchorPosition.y;
  22660. else if (translateToTop)
  22661. b = anchorPosition.y;
  22662. // update view bounds with interaction limits
  22663. if (translateToRight) {
  22664. const innerR = interactionBounds.inner.x + interactionBounds.inner.width;
  22665. const outerR = interactionBounds.outer.x + interactionBounds.outer.width;
  22666. r = clamp(targetPosition.x + tx, innerR, outerR);
  22667. }
  22668. else if (translateToLeft) {
  22669. const innerL = interactionBounds.outer.x;
  22670. const outerL = interactionBounds.inner.x;
  22671. l = clamp(targetPosition.x + tx, innerL, outerL);
  22672. }
  22673. if (translateToBottom) {
  22674. const innerB = interactionBounds.inner.y + interactionBounds.inner.height;
  22675. const outerB = interactionBounds.outer.y + interactionBounds.outer.height;
  22676. b = clamp(targetPosition.y + ty, innerB, outerB);
  22677. }
  22678. else if (translateToTop) {
  22679. const innerT = interactionBounds.outer.y;
  22680. const outerT = interactionBounds.inner.y;
  22681. t = clamp(targetPosition.y + ty, innerT, outerT);
  22682. }
  22683. // if aspect ratio is set we need to scale both axis
  22684. if (aspectRatio) {
  22685. // if translating over horizontal or vertical axis we need to update the other axis based on the aspect ratio as well
  22686. if (translateAxis) {
  22687. let dx = r - l;
  22688. let dy = b - t;
  22689. if (translateHorizontally) {
  22690. dy = dx / aspectRatio;
  22691. t = anchorPosition.y - dy * 0.5;
  22692. b = anchorPosition.y + dy * 0.5;
  22693. }
  22694. else if (translateVertically) {
  22695. dx = dy * aspectRatio;
  22696. l = anchorPosition.x - dx * 0.5;
  22697. r = anchorPosition.x + dx * 0.5;
  22698. }
  22699. }
  22700. // we're translating one of the corners in both the x and y direction, need to make sure it conforms to aspect ratio
  22701. else {
  22702. const pointer = vectorCreate(targetPosition.x + tx - anchorPosition.x, targetPosition.y + ty - anchorPosition.y);
  22703. // translations cannot be inverted, limited by anchor position
  22704. if (target === TopRight) {
  22705. pointer.x = Math.max(0, pointer.x);
  22706. pointer.y = Math.min(0, pointer.y);
  22707. }
  22708. else if (target === BottomRight) {
  22709. pointer.x = Math.max(0, pointer.x);
  22710. pointer.y = Math.max(0, pointer.y);
  22711. }
  22712. else if (target === BottomLeft) {
  22713. pointer.x = Math.min(0, pointer.x);
  22714. pointer.y = Math.max(0, pointer.y);
  22715. }
  22716. else if (target === TopLeft) {
  22717. pointer.x = Math.min(0, pointer.x);
  22718. pointer.y = Math.min(0, pointer.y);
  22719. }
  22720. // calculate the translation pointer, then get its length, now create a new pointer based on the aspect ratio, and scale it based on the original (limited) length
  22721. const pointerLength = vectorLength(pointer);
  22722. const pointerLengthMin = vectorLength(vectorCreate(interactionBounds.inner.width, interactionBounds.inner.height));
  22723. const pointerLengthMax = vectorLength(vectorCreate(interactionBounds.outer.width, interactionBounds.outer.height));
  22724. const pointerLengthLimited = clamp(pointerLength, pointerLengthMin, pointerLengthMax);
  22725. const pointerAspectRatio = vectorCreate(aspectRatio, 1);
  22726. const pointerScaled = vectorMultiply(vectorNormalize(pointerAspectRatio), pointerLengthLimited);
  22727. if (target === TopRight) {
  22728. r = anchorPosition.x + pointerScaled.x;
  22729. t = anchorPosition.y - pointerScaled.y;
  22730. }
  22731. else if (target === BottomRight) {
  22732. r = anchorPosition.x + pointerScaled.x;
  22733. b = anchorPosition.y + pointerScaled.y;
  22734. }
  22735. else if (target === BottomLeft) {
  22736. l = anchorPosition.x - pointerScaled.x;
  22737. b = anchorPosition.y + pointerScaled.y;
  22738. }
  22739. else if (target === TopLeft) {
  22740. l = anchorPosition.x - pointerScaled.x;
  22741. t = anchorPosition.y - pointerScaled.y;
  22742. }
  22743. }
  22744. }
  22745. return rectCreate(l, t, r - l, b - t);
  22746. };
  22747. const getInteractionBounds = (anchor, dir, bounds, options) => {
  22748. const { aspectRatio, minSize, maxSize } = options;
  22749. const translateToRight = dir === Right || dir === TopRight || dir === BottomRight;
  22750. const translateToLeft = dir === Left || dir === BottomLeft || dir === TopLeft;
  22751. const translateToTop = dir === Top || dir === TopRight || dir === TopLeft;
  22752. const translateToBottom = dir === Bottom || dir === BottomRight || dir === BottomLeft;
  22753. const translateHorizontally = dir === Left || dir === Right;
  22754. const translateVertically = dir === Top || dir === Bottom;
  22755. // limit bounds based on anchor and direction
  22756. const limitedBounds = rectClone(bounds);
  22757. if (translateToRight) {
  22758. limitedBounds.x = anchor.x;
  22759. limitedBounds.width -= anchor.x;
  22760. }
  22761. else if (translateToLeft) {
  22762. limitedBounds.width = anchor.x;
  22763. }
  22764. if (translateToBottom) {
  22765. limitedBounds.y = anchor.y;
  22766. limitedBounds.height -= anchor.y;
  22767. }
  22768. else if (translateToTop) {
  22769. limitedBounds.height = anchor.y;
  22770. }
  22771. // limit max size based on bounds
  22772. const maxSizeLimitedToBounds = rectCreateFromDimensions(Math.min(limitedBounds.width, maxSize.width), Math.min(limitedBounds.height, maxSize.height));
  22773. if (aspectRatio) {
  22774. // limit height
  22775. if (translateHorizontally) {
  22776. const verticalSpace = Math.min(anchor.y, bounds.height - anchor.y);
  22777. maxSizeLimitedToBounds.height = Math.min(verticalSpace * 2, maxSizeLimitedToBounds.height);
  22778. }
  22779. // limit width
  22780. else if (translateVertically) {
  22781. const horizontalSpace = Math.min(anchor.x, bounds.width - anchor.x);
  22782. maxSizeLimitedToBounds.width = Math.min(horizontalSpace * 2, maxSizeLimitedToBounds.width);
  22783. }
  22784. }
  22785. const maxSizeLimited = aspectRatio
  22786. ? sizeCreateFromRect(rectContainRect(maxSizeLimitedToBounds, aspectRatio))
  22787. : maxSizeLimitedToBounds;
  22788. // limit min size
  22789. const minSizeLimited = aspectRatio
  22790. ? sizeCreateFromRect(rectCoverRect(rectCreateFromSize(minSize), aspectRatio))
  22791. : minSize;
  22792. let l, r, t, b;
  22793. // set bounds
  22794. if (translateToRight)
  22795. l = anchor.x;
  22796. else if (translateToLeft)
  22797. r = anchor.x;
  22798. if (translateToBottom)
  22799. t = anchor.y;
  22800. else if (translateToTop)
  22801. b = anchor.y;
  22802. // inner
  22803. if (translateToRight) {
  22804. r = l + minSizeLimited.width;
  22805. }
  22806. else if (translateToLeft) {
  22807. l = r - minSizeLimited.width;
  22808. }
  22809. if (translateToBottom) {
  22810. b = t + minSizeLimited.height;
  22811. }
  22812. else if (translateToTop) {
  22813. t = b - minSizeLimited.height;
  22814. }
  22815. if (translateHorizontally) {
  22816. t = anchor.y - minSizeLimited.height * 0.5;
  22817. b = anchor.y + minSizeLimited.height * 0.5;
  22818. }
  22819. else if (translateVertically) {
  22820. l = anchor.x - minSizeLimited.width * 0.5;
  22821. r = anchor.x + minSizeLimited.width * 0.5;
  22822. }
  22823. const inner = rectCreateFromPoints(vectorCreate(l, t), vectorCreate(r, b));
  22824. // outer
  22825. if (translateToRight) {
  22826. r = l + maxSizeLimited.width;
  22827. }
  22828. else if (translateToLeft) {
  22829. l = r - maxSizeLimited.width;
  22830. }
  22831. if (translateToBottom) {
  22832. b = t + maxSizeLimited.height;
  22833. }
  22834. else if (translateToTop) {
  22835. t = b - maxSizeLimited.height;
  22836. }
  22837. if (translateHorizontally) {
  22838. t = anchor.y - maxSizeLimited.height * 0.5;
  22839. b = anchor.y + maxSizeLimited.height * 0.5;
  22840. }
  22841. else if (translateVertically) {
  22842. l = anchor.x - maxSizeLimited.width * 0.5;
  22843. r = anchor.x + maxSizeLimited.width * 0.5;
  22844. }
  22845. const outer = rectCreateFromPoints(vectorCreate(l, t), vectorCreate(r, b));
  22846. return {
  22847. inner,
  22848. outer,
  22849. };
  22850. };
  22851. var applyRectDirectionTranslation = (rect, transform, options = {}) => {
  22852. // the transforms to apply
  22853. const { target, translate } = transform;
  22854. // the transform requirements
  22855. const { aspectRatio } = options;
  22856. // get anchor coordinates and x,y position we need this for relative scaling of the view rectangle
  22857. const anchor = DirectionInversionTable[target];
  22858. const anchorDirectionCoordinates = DirectionCoordinateTable[anchor];
  22859. const anchorPosition = vectorAdd(rectClone(rect), vectorCreate(anchorDirectionCoordinates[0] * rect.width, anchorDirectionCoordinates[1] * rect.height));
  22860. // get coordinate of direction
  22861. const targetDirectionCoordinates = DirectionCoordinateTable[target];
  22862. const targetPosition = vectorAdd(rectClone(rect), vectorCreate(targetDirectionCoordinates[0] * rect.width, targetDirectionCoordinates[1] * rect.height));
  22863. // bools to determine which direction the interaction is moving in
  22864. const [translateToRight, translateToLeft, translateToTop, translateToBottom, translateHorizontally, translateVertically, translateAxis,] = getTranslationInfo(target);
  22865. let tx = translate.x;
  22866. let ty = translate.y;
  22867. if (translateHorizontally)
  22868. ty = 0;
  22869. else if (translateVertically)
  22870. tx = 0;
  22871. // current bounds
  22872. let [t, r, b, l] = rectToBounds(rect);
  22873. // update view bounds with anchor based on translation direction (one side is always locked)
  22874. if (translateToRight)
  22875. l = anchorPosition.x;
  22876. else if (translateToLeft)
  22877. r = anchorPosition.x;
  22878. if (translateToBottom)
  22879. t = anchorPosition.y;
  22880. else if (translateToTop)
  22881. b = anchorPosition.y;
  22882. // update view bounds with interaction limits
  22883. if (translateToRight) {
  22884. r = targetPosition.x + tx;
  22885. }
  22886. else if (translateToLeft) {
  22887. l = targetPosition.x + tx;
  22888. }
  22889. if (translateToBottom) {
  22890. b = targetPosition.y + ty;
  22891. }
  22892. else if (translateToTop) {
  22893. t = targetPosition.y + ty;
  22894. }
  22895. // if aspect ratio is set we need to scale both axis
  22896. if (aspectRatio) {
  22897. // if translating over horizontal or vertical axis we need to update the other axis based on the aspect ratio as well
  22898. if (translateAxis) {
  22899. let dx = r - l;
  22900. let dy = b - t;
  22901. if (translateHorizontally) {
  22902. dy = dx / aspectRatio;
  22903. t = anchorPosition.y - dy * 0.5;
  22904. b = anchorPosition.y + dy * 0.5;
  22905. }
  22906. else if (translateVertically) {
  22907. dx = dy * aspectRatio;
  22908. l = anchorPosition.x - dx * 0.5;
  22909. r = anchorPosition.x + dx * 0.5;
  22910. }
  22911. }
  22912. // we're translating one of the corners in both the x and y direction, need to make sure it conforms to aspect ratio
  22913. else {
  22914. const pointer = vectorCreate(targetPosition.x + tx - anchorPosition.x, targetPosition.y + ty - anchorPosition.y);
  22915. // translations cannot be inverted, limited by anchor position
  22916. if (target === TopRight) {
  22917. pointer.x = Math.max(0, pointer.x);
  22918. pointer.y = Math.min(0, pointer.y);
  22919. }
  22920. else if (target === BottomRight) {
  22921. pointer.x = Math.max(0, pointer.x);
  22922. pointer.y = Math.max(0, pointer.y);
  22923. }
  22924. else if (target === BottomLeft) {
  22925. pointer.x = Math.min(0, pointer.x);
  22926. pointer.y = Math.max(0, pointer.y);
  22927. }
  22928. else if (target === TopLeft) {
  22929. pointer.x = Math.min(0, pointer.x);
  22930. pointer.y = Math.min(0, pointer.y);
  22931. }
  22932. // calculate the translation pointer, then get its length, now create a new pointer based on the aspect ratio, and scale it based on the original (limited) length
  22933. const pointerLength = vectorLength(pointer);
  22934. const pointerAspectRatio = vectorCreate(aspectRatio, 1);
  22935. const pointerScaled = vectorMultiply(vectorNormalize(pointerAspectRatio), pointerLength);
  22936. if (target === TopRight) {
  22937. r = anchorPosition.x + pointerScaled.x;
  22938. t = anchorPosition.y - pointerScaled.y;
  22939. }
  22940. else if (target === BottomRight) {
  22941. r = anchorPosition.x + pointerScaled.x;
  22942. b = anchorPosition.y + pointerScaled.y;
  22943. }
  22944. else if (target === BottomLeft) {
  22945. l = anchorPosition.x - pointerScaled.x;
  22946. b = anchorPosition.y + pointerScaled.y;
  22947. }
  22948. else if (target === TopLeft) {
  22949. l = anchorPosition.x - pointerScaled.x;
  22950. t = anchorPosition.y - pointerScaled.y;
  22951. }
  22952. }
  22953. }
  22954. return rectCreate(l, t, r - l, b - t);
  22955. };
  22956. var radToDeg = (rad) => rad * 180 / Math.PI;
  22957. /* src/core/ui/plugins/crop/components/ImageRotator.svelte generated by Svelte v3.37.0 */
  22958. function create_fragment$m(ctx) {
  22959. let div;
  22960. let rangeinput;
  22961. let current;
  22962. rangeinput = new RangeInput({
  22963. props: {
  22964. elasticity: /*elasticity*/ ctx[5],
  22965. min: /*min*/ ctx[7],
  22966. max: /*max*/ ctx[8],
  22967. value: /*value*/ ctx[12],
  22968. valueMin: /*valueMin*/ ctx[0],
  22969. valueMax: /*valueMax*/ ctx[1],
  22970. labelReset: /*labelReset*/ ctx[6],
  22971. base: /*center*/ ctx[11],
  22972. valueLabel: `${Math.round(radToDeg(/*value*/ ctx[12]))}°`,
  22973. oninputstart: /*oninputstart*/ ctx[2],
  22974. oninputmove: /*func*/ ctx[14],
  22975. oninputend: /*func_1*/ ctx[15]
  22976. }
  22977. });
  22978. return {
  22979. c() {
  22980. div = element("div");
  22981. create_component(rangeinput.$$.fragment);
  22982. attr(div, "class", "PinturaImageRotator");
  22983. },
  22984. m(target, anchor) {
  22985. insert(target, div, anchor);
  22986. mount_component(rangeinput, div, null);
  22987. current = true;
  22988. },
  22989. p(ctx, [dirty]) {
  22990. const rangeinput_changes = {};
  22991. if (dirty & /*elasticity*/ 32) rangeinput_changes.elasticity = /*elasticity*/ ctx[5];
  22992. if (dirty & /*min*/ 128) rangeinput_changes.min = /*min*/ ctx[7];
  22993. if (dirty & /*max*/ 256) rangeinput_changes.max = /*max*/ ctx[8];
  22994. if (dirty & /*value*/ 4096) rangeinput_changes.value = /*value*/ ctx[12];
  22995. if (dirty & /*valueMin*/ 1) rangeinput_changes.valueMin = /*valueMin*/ ctx[0];
  22996. if (dirty & /*valueMax*/ 2) rangeinput_changes.valueMax = /*valueMax*/ ctx[1];
  22997. if (dirty & /*labelReset*/ 64) rangeinput_changes.labelReset = /*labelReset*/ ctx[6];
  22998. if (dirty & /*center*/ 2048) rangeinput_changes.base = /*center*/ ctx[11];
  22999. if (dirty & /*value*/ 4096) rangeinput_changes.valueLabel = `${Math.round(radToDeg(/*value*/ ctx[12]))}°`;
  23000. if (dirty & /*oninputstart*/ 4) rangeinput_changes.oninputstart = /*oninputstart*/ ctx[2];
  23001. if (dirty & /*oninputmove, sign, turns*/ 1544) rangeinput_changes.oninputmove = /*func*/ ctx[14];
  23002. if (dirty & /*oninputend, sign, turns*/ 1552) rangeinput_changes.oninputend = /*func_1*/ ctx[15];
  23003. rangeinput.$set(rangeinput_changes);
  23004. },
  23005. i(local) {
  23006. if (current) return;
  23007. transition_in(rangeinput.$$.fragment, local);
  23008. current = true;
  23009. },
  23010. o(local) {
  23011. transition_out(rangeinput.$$.fragment, local);
  23012. current = false;
  23013. },
  23014. d(detaching) {
  23015. if (detaching) detach(div);
  23016. destroy_component(rangeinput);
  23017. }
  23018. };
  23019. }
  23020. const MARGIN = 1e-9;
  23021. function instance$m($$self, $$props, $$invalidate) {
  23022. let min;
  23023. let max;
  23024. let center;
  23025. let sign;
  23026. let turns;
  23027. let value;
  23028. const HALF_PI = Math.PI / 2;
  23029. const QUARTER_PI = Math.PI / 4;
  23030. let { rotation } = $$props;
  23031. let { valueMin } = $$props;
  23032. let { valueMax } = $$props;
  23033. let { oninputstart = noop$1 } = $$props;
  23034. let { oninputmove = noop$1 } = $$props;
  23035. let { oninputend = noop$1 } = $$props;
  23036. let { elasticity = 0 } = $$props;
  23037. let { labelReset = undefined } = $$props;
  23038. const func = value => oninputmove(sign * turns + value);
  23039. const func_1 = value => oninputend(sign * turns + value);
  23040. $$self.$$set = $$props => {
  23041. if ("rotation" in $$props) $$invalidate(13, rotation = $$props.rotation);
  23042. if ("valueMin" in $$props) $$invalidate(0, valueMin = $$props.valueMin);
  23043. if ("valueMax" in $$props) $$invalidate(1, valueMax = $$props.valueMax);
  23044. if ("oninputstart" in $$props) $$invalidate(2, oninputstart = $$props.oninputstart);
  23045. if ("oninputmove" in $$props) $$invalidate(3, oninputmove = $$props.oninputmove);
  23046. if ("oninputend" in $$props) $$invalidate(4, oninputend = $$props.oninputend);
  23047. if ("elasticity" in $$props) $$invalidate(5, elasticity = $$props.elasticity);
  23048. if ("labelReset" in $$props) $$invalidate(6, labelReset = $$props.labelReset);
  23049. };
  23050. $$self.$$.update = () => {
  23051. if ($$self.$$.dirty & /*min, max*/ 384) {
  23052. $$invalidate(11, center = min + (max - min) * 0.5);
  23053. }
  23054. if ($$self.$$.dirty & /*rotation*/ 8192) {
  23055. $$invalidate(9, sign = Math.sign(rotation));
  23056. }
  23057. if ($$self.$$.dirty & /*rotation*/ 8192) {
  23058. $$invalidate(10, turns = Math.round(Math.abs(rotation) / HALF_PI) * HALF_PI);
  23059. }
  23060. if ($$self.$$.dirty & /*rotation, sign, turns*/ 9728) {
  23061. $$invalidate(12, value = rotation - sign * turns);
  23062. }
  23063. };
  23064. $$invalidate(7, min = -QUARTER_PI + MARGIN);
  23065. $$invalidate(8, max = QUARTER_PI - MARGIN);
  23066. return [
  23067. valueMin,
  23068. valueMax,
  23069. oninputstart,
  23070. oninputmove,
  23071. oninputend,
  23072. elasticity,
  23073. labelReset,
  23074. min,
  23075. max,
  23076. sign,
  23077. turns,
  23078. center,
  23079. value,
  23080. rotation,
  23081. func,
  23082. func_1
  23083. ];
  23084. }
  23085. class ImageRotator extends SvelteComponent {
  23086. constructor(options) {
  23087. super();
  23088. init(this, options, instance$m, create_fragment$m, safe_not_equal, {
  23089. rotation: 13,
  23090. valueMin: 0,
  23091. valueMax: 1,
  23092. oninputstart: 2,
  23093. oninputmove: 3,
  23094. oninputend: 4,
  23095. elasticity: 5,
  23096. labelReset: 6
  23097. });
  23098. }
  23099. }
  23100. /* src/core/ui/plugins/crop/components/ImageInfo.svelte generated by Svelte v3.37.0 */
  23101. function create_fragment$l(ctx) {
  23102. let div;
  23103. let p;
  23104. let t0;
  23105. let t1;
  23106. let t2;
  23107. return {
  23108. c() {
  23109. div = element("div");
  23110. p = element("p");
  23111. t0 = text(/*width*/ ctx[0]);
  23112. t1 = text(" × ");
  23113. t2 = text(/*height*/ ctx[1]);
  23114. attr(div, "class", "PinturaImageInfo");
  23115. },
  23116. m(target, anchor) {
  23117. insert(target, div, anchor);
  23118. append(div, p);
  23119. append(p, t0);
  23120. append(p, t1);
  23121. append(p, t2);
  23122. },
  23123. p(ctx, [dirty]) {
  23124. if (dirty & /*width*/ 1) set_data(t0, /*width*/ ctx[0]);
  23125. if (dirty & /*height*/ 2) set_data(t2, /*height*/ ctx[1]);
  23126. },
  23127. i: noop,
  23128. o: noop,
  23129. d(detaching) {
  23130. if (detaching) detach(div);
  23131. }
  23132. };
  23133. }
  23134. function instance$l($$self, $$props, $$invalidate) {
  23135. let { width } = $$props;
  23136. let { height } = $$props;
  23137. $$self.$$set = $$props => {
  23138. if ("width" in $$props) $$invalidate(0, width = $$props.width);
  23139. if ("height" in $$props) $$invalidate(1, height = $$props.height);
  23140. };
  23141. return [width, height];
  23142. }
  23143. class ImageInfo extends SvelteComponent {
  23144. constructor(options) {
  23145. super();
  23146. init(this, options, instance$l, create_fragment$l, safe_not_equal, { width: 0, height: 1 });
  23147. }
  23148. }
  23149. var getSelectionPresetOptionIcon = (value, options = {}) => {
  23150. const { width = 24, height = 24, bounds = 16, radius = 3 } = options;
  23151. let aspectRatio = isArray(value) ? getAspectRatio(value[0], value[1]) : value;
  23152. let aspectRatioDefined = !!aspectRatio;
  23153. aspectRatio = aspectRatioDefined ? aspectRatio : 1;
  23154. let x;
  23155. let y;
  23156. let w;
  23157. let h;
  23158. w = aspectRatio > 1 ? bounds : aspectRatio * bounds;
  23159. h = w / aspectRatio;
  23160. x = Math.round((width - w) * 0.5);
  23161. y = Math.round((height - h) * 0.5);
  23162. const fill = aspectRatioDefined ? 'currentColor' : 'none';
  23163. const stroke = aspectRatioDefined ? 'none' : 'currentColor';
  23164. const strokeWidth = width / 16;
  23165. const strokeDashArray = [width / 12, width / 6].join(' ');
  23166. return `<rect fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}" stroke-dasharray="${strokeDashArray}" x="${x}" y="${y}" width="${w}" height="${h}" rx="${radius}"/>`;
  23167. };
  23168. /* src/core/ui/plugins/crop/index.svelte generated by Svelte v3.37.0 */
  23169. function create_default_slot_2$2(ctx) {
  23170. let dynamiccomponenttree;
  23171. let current;
  23172. dynamiccomponenttree = new DynamicComponentTree_1({ props: { items: /*tools*/ ctx[0] } });
  23173. return {
  23174. c() {
  23175. create_component(dynamiccomponenttree.$$.fragment);
  23176. },
  23177. m(target, anchor) {
  23178. mount_component(dynamiccomponenttree, target, anchor);
  23179. current = true;
  23180. },
  23181. p(ctx, dirty) {
  23182. const dynamiccomponenttree_changes = {};
  23183. if (dirty[0] & /*tools*/ 1) dynamiccomponenttree_changes.items = /*tools*/ ctx[0];
  23184. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  23185. },
  23186. i(local) {
  23187. if (current) return;
  23188. transition_in(dynamiccomponenttree.$$.fragment, local);
  23189. current = true;
  23190. },
  23191. o(local) {
  23192. transition_out(dynamiccomponenttree.$$.fragment, local);
  23193. current = false;
  23194. },
  23195. d(detaching) {
  23196. destroy_component(dynamiccomponenttree, detaching);
  23197. }
  23198. };
  23199. }
  23200. // (1423:4)
  23201. function create_header_slot(ctx) {
  23202. let div;
  23203. let toolbar;
  23204. let current;
  23205. toolbar = new Toolbar({
  23206. props: {
  23207. $$slots: { default: [create_default_slot_2$2] },
  23208. $$scope: { ctx }
  23209. }
  23210. });
  23211. return {
  23212. c() {
  23213. div = element("div");
  23214. create_component(toolbar.$$.fragment);
  23215. attr(div, "slot", "header");
  23216. },
  23217. m(target, anchor) {
  23218. insert(target, div, anchor);
  23219. mount_component(toolbar, div, null);
  23220. current = true;
  23221. },
  23222. p(ctx, dirty) {
  23223. const toolbar_changes = {};
  23224. if (dirty[0] & /*tools*/ 1 | dirty[6] & /*$$scope*/ 64) {
  23225. toolbar_changes.$$scope = { dirty, ctx };
  23226. }
  23227. toolbar.$set(toolbar_changes);
  23228. },
  23229. i(local) {
  23230. if (current) return;
  23231. transition_in(toolbar.$$.fragment, local);
  23232. current = true;
  23233. },
  23234. o(local) {
  23235. transition_out(toolbar.$$.fragment, local);
  23236. current = false;
  23237. },
  23238. d(detaching) {
  23239. if (detaching) detach(div);
  23240. destroy_component(toolbar);
  23241. }
  23242. };
  23243. }
  23244. // (1452:12) {#if shouldRenderImageSelection && shouldRenderImageSelectionRecenterButton}
  23245. function create_if_block_5$2(ctx) {
  23246. let button;
  23247. let current;
  23248. button = new Button({
  23249. props: {
  23250. onclick: /*handleRecenterAction*/ ctx[80],
  23251. label: /*locale*/ ctx[4].cropLabelButtonRecenter,
  23252. icon: /*locale*/ ctx[4].cropIconButtonRecenter,
  23253. class: "PinturaButtonCenter",
  23254. disabled: !/*canCenter*/ ctx[10],
  23255. hideLabel: true,
  23256. style: `opacity: ${/*$recenterOpacity*/ ctx[27]}; transform: translate3d(${/*$recenterOffset*/ ctx[28].x}px, ${/*$recenterOffset*/ ctx[28].y}px, 0)`
  23257. }
  23258. });
  23259. return {
  23260. c() {
  23261. create_component(button.$$.fragment);
  23262. },
  23263. m(target, anchor) {
  23264. mount_component(button, target, anchor);
  23265. current = true;
  23266. },
  23267. p(ctx, dirty) {
  23268. const button_changes = {};
  23269. if (dirty[0] & /*locale*/ 16) button_changes.label = /*locale*/ ctx[4].cropLabelButtonRecenter;
  23270. if (dirty[0] & /*locale*/ 16) button_changes.icon = /*locale*/ ctx[4].cropIconButtonRecenter;
  23271. if (dirty[0] & /*canCenter*/ 1024) button_changes.disabled = !/*canCenter*/ ctx[10];
  23272. if (dirty[0] & /*$recenterOpacity, $recenterOffset*/ 402653184) button_changes.style = `opacity: ${/*$recenterOpacity*/ ctx[27]}; transform: translate3d(${/*$recenterOffset*/ ctx[28].x}px, ${/*$recenterOffset*/ ctx[28].y}px, 0)`;
  23273. button.$set(button_changes);
  23274. },
  23275. i(local) {
  23276. if (current) return;
  23277. transition_in(button.$$.fragment, local);
  23278. current = true;
  23279. },
  23280. o(local) {
  23281. transition_out(button.$$.fragment, local);
  23282. current = false;
  23283. },
  23284. d(detaching) {
  23285. destroy_component(button, detaching);
  23286. }
  23287. };
  23288. }
  23289. // (1464:12) {#if shouldRenderImageSelection}
  23290. function create_if_block_4$2(ctx) {
  23291. let rectmanipulator;
  23292. let current;
  23293. rectmanipulator = new RectManipulator({
  23294. props: {
  23295. rect: /*imageSelectionRectOffset*/ ctx[11],
  23296. visible: /*$isActive*/ ctx[9],
  23297. style: /*cropImageSelectionCornerStyle*/ ctx[2]
  23298. }
  23299. });
  23300. rectmanipulator.$on("resizestart", /*handleSelectionGrab*/ ctx[60]);
  23301. rectmanipulator.$on("resizemove", /*handleSelectionDrag*/ ctx[61]);
  23302. rectmanipulator.$on("resizeend", /*handleSelectionRelease*/ ctx[62]);
  23303. return {
  23304. c() {
  23305. create_component(rectmanipulator.$$.fragment);
  23306. },
  23307. m(target, anchor) {
  23308. mount_component(rectmanipulator, target, anchor);
  23309. current = true;
  23310. },
  23311. p(ctx, dirty) {
  23312. const rectmanipulator_changes = {};
  23313. if (dirty[0] & /*imageSelectionRectOffset*/ 2048) rectmanipulator_changes.rect = /*imageSelectionRectOffset*/ ctx[11];
  23314. if (dirty[0] & /*$isActive*/ 512) rectmanipulator_changes.visible = /*$isActive*/ ctx[9];
  23315. if (dirty[0] & /*cropImageSelectionCornerStyle*/ 4) rectmanipulator_changes.style = /*cropImageSelectionCornerStyle*/ ctx[2];
  23316. rectmanipulator.$set(rectmanipulator_changes);
  23317. },
  23318. i(local) {
  23319. if (current) return;
  23320. transition_in(rectmanipulator.$$.fragment, local);
  23321. current = true;
  23322. },
  23323. o(local) {
  23324. transition_out(rectmanipulator.$$.fragment, local);
  23325. current = false;
  23326. },
  23327. d(detaching) {
  23328. destroy_component(rectmanipulator, detaching);
  23329. }
  23330. };
  23331. }
  23332. // (1477:8) {#if shouldRenderInfoIndicator}
  23333. function create_if_block_3$2(ctx) {
  23334. let imageinfo;
  23335. let current;
  23336. imageinfo = new ImageInfo({
  23337. props: {
  23338. width: Math.round(/*$imageCropRect*/ ctx[7].width),
  23339. height: Math.round(/*$imageCropRect*/ ctx[7].height)
  23340. }
  23341. });
  23342. return {
  23343. c() {
  23344. create_component(imageinfo.$$.fragment);
  23345. },
  23346. m(target, anchor) {
  23347. mount_component(imageinfo, target, anchor);
  23348. current = true;
  23349. },
  23350. p(ctx, dirty) {
  23351. const imageinfo_changes = {};
  23352. if (dirty[0] & /*$imageCropRect*/ 128) imageinfo_changes.width = Math.round(/*$imageCropRect*/ ctx[7].width);
  23353. if (dirty[0] & /*$imageCropRect*/ 128) imageinfo_changes.height = Math.round(/*$imageCropRect*/ ctx[7].height);
  23354. imageinfo.$set(imageinfo_changes);
  23355. },
  23356. i(local) {
  23357. if (current) return;
  23358. transition_in(imageinfo.$$.fragment, local);
  23359. current = true;
  23360. },
  23361. o(local) {
  23362. transition_out(imageinfo.$$.fragment, local);
  23363. current = false;
  23364. },
  23365. d(detaching) {
  23366. destroy_component(imageinfo, detaching);
  23367. }
  23368. };
  23369. }
  23370. // (1429:4)
  23371. function create_main_slot$1(ctx) {
  23372. let div1;
  23373. let div0;
  23374. let t0;
  23375. let interactable_action;
  23376. let t1;
  23377. let current;
  23378. let mounted;
  23379. let dispose;
  23380. let if_block0 = /*shouldRenderImageSelection*/ ctx[17] && /*shouldRenderImageSelectionRecenterButton*/ ctx[18] && create_if_block_5$2(ctx);
  23381. let if_block1 = /*shouldRenderImageSelection*/ ctx[17] && create_if_block_4$2(ctx);
  23382. let if_block2 = /*shouldRenderInfoIndicator*/ ctx[16] && create_if_block_3$2(ctx);
  23383. return {
  23384. c() {
  23385. div1 = element("div");
  23386. div0 = element("div");
  23387. if (if_block0) if_block0.c();
  23388. t0 = space();
  23389. if (if_block1) if_block1.c();
  23390. t1 = space();
  23391. if (if_block2) if_block2.c();
  23392. attr(div0, "class", "PinturaStage");
  23393. attr(div1, "slot", "main");
  23394. },
  23395. m(target, anchor) {
  23396. insert(target, div1, anchor);
  23397. append(div1, div0);
  23398. if (if_block0) if_block0.m(div0, null);
  23399. append(div0, t0);
  23400. if (if_block1) if_block1.m(div0, null);
  23401. /*div0_binding*/ ctx[145](div0);
  23402. append(div1, t1);
  23403. if (if_block2) if_block2.m(div1, null);
  23404. current = true;
  23405. if (!mounted) {
  23406. dispose = [
  23407. listen(div0, "measure", /*measure_handler_1*/ ctx[143]),
  23408. action_destroyer(measurable.call(null, div0)),
  23409. listen(
  23410. div0,
  23411. "wheel",
  23412. function () {
  23413. if (is_function(/*cropEnableZoom*/ ctx[3] && /*handleWheel*/ ctx[79])) (/*cropEnableZoom*/ ctx[3] && /*handleWheel*/ ctx[79]).apply(this, arguments);
  23414. },
  23415. { passive: false }
  23416. ),
  23417. listen(div0, "interactionstart", /*handleImageDragStart*/ ctx[66]),
  23418. listen(div0, "interactionupdate", /*handleImageDrag*/ ctx[67]),
  23419. listen(div0, "interactionrelease", /*handleImageDragRelease*/ ctx[69]),
  23420. listen(div0, "interactionend", /*handleImageDragEnd*/ ctx[68]),
  23421. action_destroyer(interactable_action = interactable.call(null, div0, {
  23422. drag: true,
  23423. pinch: /*cropEnableZoom*/ ctx[3],
  23424. inertia: true,
  23425. matchTarget: true,
  23426. getEventPosition: /*interactable_function*/ ctx[146]
  23427. })),
  23428. listen(div0, "gesturedown", /*handleGestureStart*/ ctx[76]),
  23429. listen(div0, "gestureupdate", /*handleGestureUpdate*/ ctx[77]),
  23430. listen(div0, "gestureup", /*handleGestureEnd*/ ctx[78]),
  23431. action_destroyer(gesturable.call(null, div0))
  23432. ];
  23433. mounted = true;
  23434. }
  23435. },
  23436. p(new_ctx, dirty) {
  23437. ctx = new_ctx;
  23438. if (/*shouldRenderImageSelection*/ ctx[17] && /*shouldRenderImageSelectionRecenterButton*/ ctx[18]) {
  23439. if (if_block0) {
  23440. if_block0.p(ctx, dirty);
  23441. if (dirty[0] & /*shouldRenderImageSelection, shouldRenderImageSelectionRecenterButton*/ 393216) {
  23442. transition_in(if_block0, 1);
  23443. }
  23444. } else {
  23445. if_block0 = create_if_block_5$2(ctx);
  23446. if_block0.c();
  23447. transition_in(if_block0, 1);
  23448. if_block0.m(div0, t0);
  23449. }
  23450. } else if (if_block0) {
  23451. group_outros();
  23452. transition_out(if_block0, 1, 1, () => {
  23453. if_block0 = null;
  23454. });
  23455. check_outros();
  23456. }
  23457. if (/*shouldRenderImageSelection*/ ctx[17]) {
  23458. if (if_block1) {
  23459. if_block1.p(ctx, dirty);
  23460. if (dirty[0] & /*shouldRenderImageSelection*/ 131072) {
  23461. transition_in(if_block1, 1);
  23462. }
  23463. } else {
  23464. if_block1 = create_if_block_4$2(ctx);
  23465. if_block1.c();
  23466. transition_in(if_block1, 1);
  23467. if_block1.m(div0, null);
  23468. }
  23469. } else if (if_block1) {
  23470. group_outros();
  23471. transition_out(if_block1, 1, 1, () => {
  23472. if_block1 = null;
  23473. });
  23474. check_outros();
  23475. }
  23476. if (interactable_action && is_function(interactable_action.update) && dirty[0] & /*cropEnableZoom, $rootRect*/ 32776) interactable_action.update.call(null, {
  23477. drag: true,
  23478. pinch: /*cropEnableZoom*/ ctx[3],
  23479. inertia: true,
  23480. matchTarget: true,
  23481. getEventPosition: /*interactable_function*/ ctx[146]
  23482. });
  23483. if (/*shouldRenderInfoIndicator*/ ctx[16]) {
  23484. if (if_block2) {
  23485. if_block2.p(ctx, dirty);
  23486. if (dirty[0] & /*shouldRenderInfoIndicator*/ 65536) {
  23487. transition_in(if_block2, 1);
  23488. }
  23489. } else {
  23490. if_block2 = create_if_block_3$2(ctx);
  23491. if_block2.c();
  23492. transition_in(if_block2, 1);
  23493. if_block2.m(div1, null);
  23494. }
  23495. } else if (if_block2) {
  23496. group_outros();
  23497. transition_out(if_block2, 1, 1, () => {
  23498. if_block2 = null;
  23499. });
  23500. check_outros();
  23501. }
  23502. },
  23503. i(local) {
  23504. if (current) return;
  23505. transition_in(if_block0);
  23506. transition_in(if_block1);
  23507. transition_in(if_block2);
  23508. current = true;
  23509. },
  23510. o(local) {
  23511. transition_out(if_block0);
  23512. transition_out(if_block1);
  23513. transition_out(if_block2);
  23514. current = false;
  23515. },
  23516. d(detaching) {
  23517. if (detaching) detach(div1);
  23518. if (if_block0) if_block0.d();
  23519. if (if_block1) if_block1.d();
  23520. /*div0_binding*/ ctx[145](null);
  23521. if (if_block2) if_block2.d();
  23522. mounted = false;
  23523. run_all(dispose);
  23524. }
  23525. };
  23526. }
  23527. // (1485:8) {#if shouldRenderFooter}
  23528. function create_if_block$4(ctx) {
  23529. let tablist;
  23530. let t;
  23531. let tabpanels;
  23532. let current;
  23533. const tablist_spread_levels = [
  23534. { class: "PinturaControlList" },
  23535. { tabs: /*tabs*/ ctx[12] },
  23536. /*tabsConfig*/ ctx[21]
  23537. ];
  23538. let tablist_props = {
  23539. $$slots: {
  23540. default: [
  23541. create_default_slot_1$3,
  23542. ({ tab }) => ({ 191: tab }),
  23543. ({ tab }) => [0, 0, 0, 0, 0, 0, tab ? 32 : 0]
  23544. ]
  23545. },
  23546. $$scope: { ctx }
  23547. };
  23548. for (let i = 0; i < tablist_spread_levels.length; i += 1) {
  23549. tablist_props = assign(tablist_props, tablist_spread_levels[i]);
  23550. }
  23551. tablist = new TabList({ props: tablist_props });
  23552. tablist.$on("select", /*select_handler*/ ctx[144]);
  23553. const tabpanels_spread_levels = [
  23554. { class: "PinturaControlPanels" },
  23555. { panelClass: "PinturaControlPanel" },
  23556. { panels: /*panels*/ ctx[22] },
  23557. /*tabsConfig*/ ctx[21]
  23558. ];
  23559. let tabpanels_props = {
  23560. $$slots: {
  23561. default: [
  23562. create_default_slot$9,
  23563. ({ panel }) => ({ 190: panel }),
  23564. ({ panel }) => [0, 0, 0, 0, 0, 0, panel ? 16 : 0]
  23565. ]
  23566. },
  23567. $$scope: { ctx }
  23568. };
  23569. for (let i = 0; i < tabpanels_spread_levels.length; i += 1) {
  23570. tabpanels_props = assign(tabpanels_props, tabpanels_spread_levels[i]);
  23571. }
  23572. tabpanels = new TabPanels({ props: tabpanels_props });
  23573. return {
  23574. c() {
  23575. create_component(tablist.$$.fragment);
  23576. t = space();
  23577. create_component(tabpanels.$$.fragment);
  23578. },
  23579. m(target, anchor) {
  23580. mount_component(tablist, target, anchor);
  23581. insert(target, t, anchor);
  23582. mount_component(tabpanels, target, anchor);
  23583. current = true;
  23584. },
  23585. p(ctx, dirty) {
  23586. const tablist_changes = (dirty[0] & /*tabs, tabsConfig*/ 2101248)
  23587. ? get_spread_update(tablist_spread_levels, [
  23588. tablist_spread_levels[0],
  23589. dirty[0] & /*tabs*/ 4096 && { tabs: /*tabs*/ ctx[12] },
  23590. dirty[0] & /*tabsConfig*/ 2097152 && get_spread_object(/*tabsConfig*/ ctx[21])
  23591. ])
  23592. : {};
  23593. if (dirty[6] & /*$$scope, tab*/ 96) {
  23594. tablist_changes.$$scope = { dirty, ctx };
  23595. }
  23596. tablist.$set(tablist_changes);
  23597. const tabpanels_changes = (dirty[0] & /*panels, tabsConfig*/ 6291456)
  23598. ? get_spread_update(tabpanels_spread_levels, [
  23599. tabpanels_spread_levels[0],
  23600. tabpanels_spread_levels[1],
  23601. dirty[0] & /*panels*/ 4194304 && { panels: /*panels*/ ctx[22] },
  23602. dirty[0] & /*tabsConfig*/ 2097152 && get_spread_object(/*tabsConfig*/ ctx[21])
  23603. ])
  23604. : {};
  23605. if (dirty[0] & /*$imageRotation, locale, $imageRotationRange, imageZoomLevelMin, $imageZoomLevelRange, $imageZoomLevel*/ 117457168 | dirty[6] & /*$$scope, panel*/ 80) {
  23606. tabpanels_changes.$$scope = { dirty, ctx };
  23607. }
  23608. tabpanels.$set(tabpanels_changes);
  23609. },
  23610. i(local) {
  23611. if (current) return;
  23612. transition_in(tablist.$$.fragment, local);
  23613. transition_in(tabpanels.$$.fragment, local);
  23614. current = true;
  23615. },
  23616. o(local) {
  23617. transition_out(tablist.$$.fragment, local);
  23618. transition_out(tabpanels.$$.fragment, local);
  23619. current = false;
  23620. },
  23621. d(detaching) {
  23622. destroy_component(tablist, detaching);
  23623. if (detaching) detach(t);
  23624. destroy_component(tabpanels, detaching);
  23625. }
  23626. };
  23627. }
  23628. // (1486:12) <TabList class="PinturaControlList" {tabs} {...tabsConfig} on:select={({ detail }) => (transformSelected = detail)} let:tab >
  23629. function create_default_slot_1$3(ctx) {
  23630. let span;
  23631. let t_value = /*tab*/ ctx[191].label + "";
  23632. let t;
  23633. return {
  23634. c() {
  23635. span = element("span");
  23636. t = text(t_value);
  23637. },
  23638. m(target, anchor) {
  23639. insert(target, span, anchor);
  23640. append(span, t);
  23641. },
  23642. p(ctx, dirty) {
  23643. if (dirty[6] & /*tab*/ 32 && t_value !== (t_value = /*tab*/ ctx[191].label + "")) set_data(t, t_value);
  23644. },
  23645. d(detaching) {
  23646. if (detaching) detach(span);
  23647. }
  23648. };
  23649. }
  23650. // (1514:59)
  23651. function create_if_block_2$3(ctx) {
  23652. let rangeinput;
  23653. let current;
  23654. rangeinput = new RangeInput({
  23655. props: {
  23656. elasticity: /*elasticityMultiplier*/ ctx[35] * /*rangeInputElasticity*/ ctx[36],
  23657. base: imageZoomLevelBase,
  23658. min: /*imageZoomLevelMin*/ ctx[14],
  23659. max: imageZoomLevelMax,
  23660. valueMin: /*$imageZoomLevelRange*/ ctx[25][0],
  23661. valueMax: /*$imageZoomLevelRange*/ ctx[25][1],
  23662. value: /*$imageZoomLevel*/ ctx[26],
  23663. labelReset: /*locale*/ ctx[4].labelReset,
  23664. valueLabel: `${Math.round(/*$imageZoomLevel*/ ctx[26] * 100)}%`,
  23665. oninputstart: /*handleResizeStart*/ ctx[73],
  23666. oninputmove: /*handleResizeMove*/ ctx[74],
  23667. oninputend: /*handleResizeEnd*/ ctx[75]
  23668. }
  23669. });
  23670. return {
  23671. c() {
  23672. create_component(rangeinput.$$.fragment);
  23673. },
  23674. m(target, anchor) {
  23675. mount_component(rangeinput, target, anchor);
  23676. current = true;
  23677. },
  23678. p(ctx, dirty) {
  23679. const rangeinput_changes = {};
  23680. if (dirty[0] & /*imageZoomLevelMin*/ 16384) rangeinput_changes.min = /*imageZoomLevelMin*/ ctx[14];
  23681. if (dirty[0] & /*$imageZoomLevelRange*/ 33554432) rangeinput_changes.valueMin = /*$imageZoomLevelRange*/ ctx[25][0];
  23682. if (dirty[0] & /*$imageZoomLevelRange*/ 33554432) rangeinput_changes.valueMax = /*$imageZoomLevelRange*/ ctx[25][1];
  23683. if (dirty[0] & /*$imageZoomLevel*/ 67108864) rangeinput_changes.value = /*$imageZoomLevel*/ ctx[26];
  23684. if (dirty[0] & /*locale*/ 16) rangeinput_changes.labelReset = /*locale*/ ctx[4].labelReset;
  23685. if (dirty[0] & /*$imageZoomLevel*/ 67108864) rangeinput_changes.valueLabel = `${Math.round(/*$imageZoomLevel*/ ctx[26] * 100)}%`;
  23686. rangeinput.$set(rangeinput_changes);
  23687. },
  23688. i(local) {
  23689. if (current) return;
  23690. transition_in(rangeinput.$$.fragment, local);
  23691. current = true;
  23692. },
  23693. o(local) {
  23694. transition_out(rangeinput.$$.fragment, local);
  23695. current = false;
  23696. },
  23697. d(detaching) {
  23698. destroy_component(rangeinput, detaching);
  23699. }
  23700. };
  23701. }
  23702. // (1503:16) {#if panel === cropUniqueId + '-rotation'}
  23703. function create_if_block_1$4(ctx) {
  23704. let imagerotator;
  23705. let current;
  23706. imagerotator = new ImageRotator({
  23707. props: {
  23708. elasticity: /*elasticityMultiplier*/ ctx[35] * /*rangeInputElasticity*/ ctx[36],
  23709. rotation: /*$imageRotation*/ ctx[8],
  23710. labelReset: /*locale*/ ctx[4].labelReset,
  23711. valueMin: /*$imageRotationRange*/ ctx[24][0],
  23712. valueMax: /*$imageRotationRange*/ ctx[24][1],
  23713. oninputstart: /*handleRotateStart*/ ctx[63],
  23714. oninputmove: /*handleRotateMove*/ ctx[64],
  23715. oninputend: /*handleRotateEnd*/ ctx[65]
  23716. }
  23717. });
  23718. return {
  23719. c() {
  23720. create_component(imagerotator.$$.fragment);
  23721. },
  23722. m(target, anchor) {
  23723. mount_component(imagerotator, target, anchor);
  23724. current = true;
  23725. },
  23726. p(ctx, dirty) {
  23727. const imagerotator_changes = {};
  23728. if (dirty[0] & /*$imageRotation*/ 256) imagerotator_changes.rotation = /*$imageRotation*/ ctx[8];
  23729. if (dirty[0] & /*locale*/ 16) imagerotator_changes.labelReset = /*locale*/ ctx[4].labelReset;
  23730. if (dirty[0] & /*$imageRotationRange*/ 16777216) imagerotator_changes.valueMin = /*$imageRotationRange*/ ctx[24][0];
  23731. if (dirty[0] & /*$imageRotationRange*/ 16777216) imagerotator_changes.valueMax = /*$imageRotationRange*/ ctx[24][1];
  23732. imagerotator.$set(imagerotator_changes);
  23733. },
  23734. i(local) {
  23735. if (current) return;
  23736. transition_in(imagerotator.$$.fragment, local);
  23737. current = true;
  23738. },
  23739. o(local) {
  23740. transition_out(imagerotator.$$.fragment, local);
  23741. current = false;
  23742. },
  23743. d(detaching) {
  23744. destroy_component(imagerotator, detaching);
  23745. }
  23746. };
  23747. }
  23748. // (1496:12) <TabPanels class="PinturaControlPanels" panelClass="PinturaControlPanel" {panels} {...tabsConfig} let:panel >
  23749. function create_default_slot$9(ctx) {
  23750. let current_block_type_index;
  23751. let if_block;
  23752. let if_block_anchor;
  23753. let current;
  23754. const if_block_creators = [create_if_block_1$4, create_if_block_2$3];
  23755. const if_blocks = [];
  23756. function select_block_type(ctx, dirty) {
  23757. if (/*panel*/ ctx[190] === /*cropUniqueId*/ ctx[85] + "-rotation") return 0;
  23758. if (/*panel*/ ctx[190] === /*cropUniqueId*/ ctx[85] + "-zoom") return 1;
  23759. return -1;
  23760. }
  23761. if (~(current_block_type_index = select_block_type(ctx))) {
  23762. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  23763. }
  23764. return {
  23765. c() {
  23766. if (if_block) if_block.c();
  23767. if_block_anchor = empty();
  23768. },
  23769. m(target, anchor) {
  23770. if (~current_block_type_index) {
  23771. if_blocks[current_block_type_index].m(target, anchor);
  23772. }
  23773. insert(target, if_block_anchor, anchor);
  23774. current = true;
  23775. },
  23776. p(ctx, dirty) {
  23777. let previous_block_index = current_block_type_index;
  23778. current_block_type_index = select_block_type(ctx);
  23779. if (current_block_type_index === previous_block_index) {
  23780. if (~current_block_type_index) {
  23781. if_blocks[current_block_type_index].p(ctx, dirty);
  23782. }
  23783. } else {
  23784. if (if_block) {
  23785. group_outros();
  23786. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  23787. if_blocks[previous_block_index] = null;
  23788. });
  23789. check_outros();
  23790. }
  23791. if (~current_block_type_index) {
  23792. if_block = if_blocks[current_block_type_index];
  23793. if (!if_block) {
  23794. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  23795. if_block.c();
  23796. } else {
  23797. if_block.p(ctx, dirty);
  23798. }
  23799. transition_in(if_block, 1);
  23800. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  23801. } else {
  23802. if_block = null;
  23803. }
  23804. }
  23805. },
  23806. i(local) {
  23807. if (current) return;
  23808. transition_in(if_block);
  23809. current = true;
  23810. },
  23811. o(local) {
  23812. transition_out(if_block);
  23813. current = false;
  23814. },
  23815. d(detaching) {
  23816. if (~current_block_type_index) {
  23817. if_blocks[current_block_type_index].d(detaching);
  23818. }
  23819. if (detaching) detach(if_block_anchor);
  23820. }
  23821. };
  23822. }
  23823. // (1484:4)
  23824. function create_footer_slot$5(ctx) {
  23825. let div;
  23826. let current;
  23827. let if_block = /*shouldRenderFooter*/ ctx[20] && create_if_block$4(ctx);
  23828. return {
  23829. c() {
  23830. div = element("div");
  23831. if (if_block) if_block.c();
  23832. attr(div, "slot", "footer");
  23833. attr(div, "style", /*footerStyle*/ ctx[23]);
  23834. },
  23835. m(target, anchor) {
  23836. insert(target, div, anchor);
  23837. if (if_block) if_block.m(div, null);
  23838. current = true;
  23839. },
  23840. p(ctx, dirty) {
  23841. if (/*shouldRenderFooter*/ ctx[20]) {
  23842. if (if_block) {
  23843. if_block.p(ctx, dirty);
  23844. if (dirty[0] & /*shouldRenderFooter*/ 1048576) {
  23845. transition_in(if_block, 1);
  23846. }
  23847. } else {
  23848. if_block = create_if_block$4(ctx);
  23849. if_block.c();
  23850. transition_in(if_block, 1);
  23851. if_block.m(div, null);
  23852. }
  23853. } else if (if_block) {
  23854. group_outros();
  23855. transition_out(if_block, 1, 1, () => {
  23856. if_block = null;
  23857. });
  23858. check_outros();
  23859. }
  23860. if (!current || dirty[0] & /*footerStyle*/ 8388608) {
  23861. attr(div, "style", /*footerStyle*/ ctx[23]);
  23862. }
  23863. },
  23864. i(local) {
  23865. if (current) return;
  23866. transition_in(if_block);
  23867. current = true;
  23868. },
  23869. o(local) {
  23870. transition_out(if_block);
  23871. current = false;
  23872. },
  23873. d(detaching) {
  23874. if (detaching) detach(div);
  23875. if (if_block) if_block.d();
  23876. }
  23877. };
  23878. }
  23879. function create_fragment$k(ctx) {
  23880. let util;
  23881. let updating_root;
  23882. let current;
  23883. function util_root_binding(value) {
  23884. /*util_root_binding*/ ctx[147](value);
  23885. }
  23886. let util_props = {
  23887. hasHeader: /*shouldRenderToolbar*/ ctx[19],
  23888. $$slots: {
  23889. footer: [create_footer_slot$5],
  23890. main: [create_main_slot$1],
  23891. header: [create_header_slot]
  23892. },
  23893. $$scope: { ctx }
  23894. };
  23895. if (/*root*/ ctx[13] !== void 0) {
  23896. util_props.root = /*root*/ ctx[13];
  23897. }
  23898. util = new Util({ props: util_props });
  23899. binding_callbacks.push(() => bind(util, "root", util_root_binding));
  23900. util.$on("measure", /*measure_handler*/ ctx[148]);
  23901. return {
  23902. c() {
  23903. create_component(util.$$.fragment);
  23904. },
  23905. m(target, anchor) {
  23906. mount_component(util, target, anchor);
  23907. current = true;
  23908. },
  23909. p(ctx, dirty) {
  23910. const util_changes = {};
  23911. if (dirty[0] & /*shouldRenderToolbar*/ 524288) util_changes.hasHeader = /*shouldRenderToolbar*/ ctx[19];
  23912. if (dirty[0] & /*footerStyle, panels, tabsConfig, $imageRotation, locale, $imageRotationRange, imageZoomLevelMin, $imageZoomLevelRange, $imageZoomLevel, tabs, transformSelected, shouldRenderFooter, $imageCropRect, shouldRenderInfoIndicator, stageRef, cropEnableZoom, $rootRect, imageSelectionRectOffset, $isActive, cropImageSelectionCornerStyle, shouldRenderImageSelection, canCenter, $recenterOpacity, $recenterOffset, shouldRenderImageSelectionRecenterButton, tools*/ 536338429 | dirty[6] & /*$$scope*/ 64) {
  23913. util_changes.$$scope = { dirty, ctx };
  23914. }
  23915. if (!updating_root && dirty[0] & /*root*/ 8192) {
  23916. updating_root = true;
  23917. util_changes.root = /*root*/ ctx[13];
  23918. add_flush_callback(() => updating_root = false);
  23919. }
  23920. util.$set(util_changes);
  23921. },
  23922. i(local) {
  23923. if (current) return;
  23924. transition_in(util.$$.fragment, local);
  23925. current = true;
  23926. },
  23927. o(local) {
  23928. transition_out(util.$$.fragment, local);
  23929. current = false;
  23930. },
  23931. d(detaching) {
  23932. destroy_component(util, detaching);
  23933. }
  23934. };
  23935. }
  23936. const imageZoomLevelMax = 1;
  23937. const imageZoomLevelBase = 0;
  23938. function instance$k($$self, $$props, $$invalidate) {
  23939. let imageZoomLevelMin;
  23940. let imageSelectionOffset;
  23941. let imageSelectionCenter;
  23942. let imageSelectionCenteredRect;
  23943. let isImageSelectionDisplayed;
  23944. let isImageSelectionCentered;
  23945. let isResizingSelection;
  23946. let isMaxSelectionRect;
  23947. let isOverlayMode;
  23948. let canZoomToCenter;
  23949. let canCenter;
  23950. let shouldRenderInfoIndicator;
  23951. let shouldRenderImageSelection;
  23952. let shouldRenderImageSelectionRecenterButton;
  23953. let imageSelectionRectOffset;
  23954. let hasPlentyVerticalSpace;
  23955. let shouldRenderPresetSelect;
  23956. let shouldRenderToolbar;
  23957. let couldRenderZoomInput;
  23958. let shouldRenderZoomInput;
  23959. let shouldRenderFooter;
  23960. let tabsConfig;
  23961. let tabs;
  23962. let panels;
  23963. let footerStyle;
  23964. let $imageCropAspectRatio;
  23965. let $imageCropRect;
  23966. let $imageSize;
  23967. let $imageRotation;
  23968. let $imageFlipY;
  23969. let $imageFlipX;
  23970. let $selectedPresetIndex;
  23971. let $imageOutputSize;
  23972. let $imageCropMinSize;
  23973. let $imageCropLimitToImage;
  23974. let $env;
  23975. let $isActive,
  23976. $$unsubscribe_isActive = noop,
  23977. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(9, $isActive = $$value)), isActive);
  23978. let $isInteracting;
  23979. let $imageSelectionRectSnapshot;
  23980. let $imageSelectionRect;
  23981. let $presentationScalar;
  23982. let $imageCropMaxSize;
  23983. let $imageSelectionRectIntent;
  23984. let $utilRect;
  23985. let $imageCropRectOrigin;
  23986. let $imageCropRectIntent;
  23987. let $imageCropRange;
  23988. let $rootRect;
  23989. let $stageRect;
  23990. let $imageCropRangeAspectRatio;
  23991. let $imageSelectionRectPresentation;
  23992. let $imageScalar;
  23993. let $framePadded;
  23994. let $imagePreviewModifiers;
  23995. let $imageOverlayMarkup;
  23996. let $imageSelectionGuides;
  23997. let $animation;
  23998. let $footerOffset;
  23999. let $imageRotationRange;
  24000. let $imageZoomLevelRange;
  24001. let $imageZoomLevel;
  24002. let $recenterOpacity;
  24003. let $recenterOffset;
  24004. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  24005. const name = "crop";
  24006. let { isActive } = $$props;
  24007. $$subscribe_isActive();
  24008. let { stores } = $$props;
  24009. let { cropImageSelectionCornerStyle = "circle" } = $$props; // 'circle', 'hook', 'invisible'
  24010. let { cropWillRenderImageSelectionGuides = (interaction, interactionFraction) => {
  24011. const isRotating = interaction == "rotate";
  24012. return {
  24013. rows: isRotating ? 5 : 3,
  24014. cols: isRotating ? 5 : 3,
  24015. opacity: interactionFraction * 0.25
  24016. };
  24017. } } = $$props;
  24018. let { cropAutoCenterImageSelectionTimeout = undefined } = $$props;
  24019. let { cropEnableZoomMatchImageAspectRatio = true } = $$props;
  24020. let { cropEnableRotateMatchImageAspectRatio = "never" } = $$props; // 'always' | 'custom' | 'never'
  24021. let { cropEnableRotationInput = true } = $$props;
  24022. let { cropEnableZoom = true } = $$props;
  24023. let { cropEnableZoomInput = true } = $$props;
  24024. let { cropEnableZoomAutoHide = true } = $$props;
  24025. let { cropEnableImageSelection = true } = $$props;
  24026. let { cropEnableInfoIndicator = false } = $$props;
  24027. let { cropEnableZoomTowardsWheelPosition = true } = $$props;
  24028. let { cropEnableLimitWheelInputToCropSelection = true } = $$props;
  24029. let { cropEnableCenterImageSelection = true } = $$props;
  24030. let { cropEnableButtonRotateLeft = true } = $$props;
  24031. let { cropEnableButtonRotateRight = false } = $$props;
  24032. let { cropEnableButtonFlipHorizontal = true } = $$props;
  24033. let { cropEnableButtonFlipVertical = false } = $$props;
  24034. let { cropSelectPresetOptions = undefined } = $$props;
  24035. let { cropEnableSelectPreset = true } = $$props;
  24036. let { cropEnableButtonToggleCropLimit = false } = $$props;
  24037. let { cropWillRenderTools = passthrough } = $$props;
  24038. let { locale = {} } = $$props;
  24039. let { tools = [] } = $$props;
  24040. // state
  24041. let interaction = "idle";
  24042. // helpers
  24043. const isCustomCrop = () => $imageCropAspectRatio === undefined;
  24044. const turnAspectRatio = aspectRatio => 1 / aspectRatio;
  24045. const hasValidRotatedCropAspectRatio = () => {
  24046. if ($imageCropAspectRatio === 1) return false;
  24047. const rotatedImageCropAspectRatio = turnAspectRatio($imageCropAspectRatio);
  24048. // no options available, forced crop aspect ratio
  24049. if (!cropSelectPresetOptions) return false;
  24050. // options available but no valid option in list
  24051. if (!flattenOptions(cropSelectPresetOptions).find(([aspectRatio]) => aspectRatio === rotatedImageCropAspectRatio)) return false;
  24052. return true;
  24053. };
  24054. const isCropMaxSize = (imageCropRect, imageSize, imageRotation) => isRotatedSideways(imageRotation)
  24055. ? imageSize.width === Math.round(imageCropRect.height) || imageSize.height === Math.round(imageCropRect.width)
  24056. : imageSize.width === Math.round(imageCropRect.width) || imageSize.height === Math.round(imageCropRect.height);
  24057. const isCropCentered = (imageCropRect, imageSize, imageRotation) => {
  24058. const imageSizeRotated = sizeApply(sizeRotate(sizeClone(imageSize), imageRotation), v => Math.abs(Math.round(v)));
  24059. const imageCenter = sizeCenter(imageSizeRotated);
  24060. const cropCenter = rectCenter(imageCropRect);
  24061. return vectorEqual(imageCenter, cropCenter);
  24062. };
  24063. const canMatchCropAspectRatioToRotation = () => // is custom crop mode
  24064. (isCustomCrop() || // can match preset crop and preset is available
  24065. cropEnableRotateMatchImageAspectRatio === "always" && hasValidRotatedCropAspectRatio()) && isCropCentered($imageCropRect, $imageSize, $imageRotation) && isCropMaxSize($imageCropRect, $imageSize, $imageRotation);
  24066. const applyRotation = value => {
  24067. if (cropEnableRotateMatchImageAspectRatio !== "never" && canMatchCropAspectRatioToRotation()) {
  24068. set_store_value(imageRotation, $imageRotation += value, $imageRotation);
  24069. const isRotated = isRotatedSideways($imageRotation);
  24070. const w = isRotated ? $imageSize.height : $imageSize.width;
  24071. const h = isRotated ? $imageSize.width : $imageSize.height;
  24072. set_store_value(imageCropRect, $imageCropRect = rectCreate(0, 0, w, h), $imageCropRect);
  24073. if (!isCustomCrop()) set_store_value(imageCropAspectRatio, $imageCropAspectRatio = getAspectRatio(w, h), $imageCropAspectRatio);
  24074. } else {
  24075. set_store_value(imageRotation, $imageRotation += value, $imageRotation);
  24076. }
  24077. };
  24078. const { history, env, isInteracting, isInteractingFraction, rootRect, stageRect, utilRect, rootLineColor, animation, elasticityMultiplier, rangeInputElasticity, presentationScalar, // effect filtering
  24079. imagePreviewModifiers, imageOutlineOpacity, // crop selection
  24080. imageFlipX, imageFlipY, imageRotation, imageRotationRange, imageOutputSize, imageSelectionRect, imageSelectionRectSnapshot, imageSelectionRectIntent, imageSelectionRectPresentation, imageCropRectIntent, imageCropRectOrigin, imageCropRect, imageCropMinSize, imageCropMaxSize, imageCropRange, imageCropAspectRatio, imageCropRectAspectRatio, imageCropLimitToImage, imageSize, imageScalar, imageOverlayMarkup, framePadded } = stores; // the actual limited rectangle
  24081. // used to calculate rectangle while dragging
  24082. // can be used to set set intended rectangle
  24083. // readonly
  24084. component_subscribe($$self, env, value => $$invalidate(118, $env = value));
  24085. component_subscribe($$self, isInteracting, value => $$invalidate(119, $isInteracting = value));
  24086. component_subscribe($$self, rootRect, value => $$invalidate(15, $rootRect = value));
  24087. component_subscribe($$self, stageRect, value => $$invalidate(124, $stageRect = value));
  24088. component_subscribe($$self, utilRect, value => $$invalidate(123, $utilRect = value));
  24089. component_subscribe($$self, animation, value => $$invalidate(141, $animation = value));
  24090. component_subscribe($$self, presentationScalar, value => $$invalidate(122, $presentationScalar = value));
  24091. component_subscribe($$self, imagePreviewModifiers, value => $$invalidate(136, $imagePreviewModifiers = value));
  24092. component_subscribe($$self, imageFlipX, value => $$invalidate(112, $imageFlipX = value));
  24093. component_subscribe($$self, imageFlipY, value => $$invalidate(111, $imageFlipY = value));
  24094. component_subscribe($$self, imageRotation, value => $$invalidate(8, $imageRotation = value));
  24095. component_subscribe($$self, imageRotationRange, value => $$invalidate(24, $imageRotationRange = value));
  24096. component_subscribe($$self, imageOutputSize, value => $$invalidate(159, $imageOutputSize = value));
  24097. component_subscribe($$self, imageSelectionRect, value => $$invalidate(121, $imageSelectionRect = value));
  24098. component_subscribe($$self, imageSelectionRectSnapshot, value => $$invalidate(120, $imageSelectionRectSnapshot = value));
  24099. component_subscribe($$self, imageSelectionRectIntent, value => $$invalidate(161, $imageSelectionRectIntent = value));
  24100. component_subscribe($$self, imageSelectionRectPresentation, value => $$invalidate(127, $imageSelectionRectPresentation = value));
  24101. component_subscribe($$self, imageCropRectIntent, value => $$invalidate(163, $imageCropRectIntent = value));
  24102. component_subscribe($$self, imageCropRectOrigin, value => $$invalidate(162, $imageCropRectOrigin = value));
  24103. component_subscribe($$self, imageCropRect, value => $$invalidate(7, $imageCropRect = value));
  24104. component_subscribe($$self, imageCropMinSize, value => $$invalidate(116, $imageCropMinSize = value));
  24105. component_subscribe($$self, imageCropMaxSize, value => $$invalidate(160, $imageCropMaxSize = value));
  24106. component_subscribe($$self, imageCropRange, value => $$invalidate(164, $imageCropRange = value));
  24107. component_subscribe($$self, imageCropAspectRatio, value => $$invalidate(158, $imageCropAspectRatio = value));
  24108. component_subscribe($$self, imageCropLimitToImage, value => $$invalidate(117, $imageCropLimitToImage = value));
  24109. component_subscribe($$self, imageSize, value => $$invalidate(110, $imageSize = value));
  24110. component_subscribe($$self, imageScalar, value => $$invalidate(134, $imageScalar = value));
  24111. component_subscribe($$self, imageOverlayMarkup, value => $$invalidate(166, $imageOverlayMarkup = value));
  24112. component_subscribe($$self, framePadded, value => $$invalidate(135, $framePadded = value));
  24113. //
  24114. // resizing crop
  24115. //
  24116. let presentationScalarSnapshot;
  24117. let imageSelectionRectMinSize;
  24118. let imageSelectionRectMaxSize;
  24119. const handleSelectionGrab = () => {
  24120. interaction = "select";
  24121. // now interacting
  24122. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24123. // we remember the current view rect and crop rect, because that is the crop rect we use as a starting point to transform while dragging
  24124. set_store_value(imageSelectionRectSnapshot, $imageSelectionRectSnapshot = rectClone($imageSelectionRect), $imageSelectionRectSnapshot);
  24125. // remember current scalar so we can update min and max size correctly
  24126. presentationScalarSnapshot = $presentationScalar;
  24127. imageSelectionRectMinSize = sizeScale(sizeClone($imageCropMinSize), presentationScalarSnapshot);
  24128. imageSelectionRectMaxSize = sizeScale(sizeClone($imageCropMaxSize), presentationScalarSnapshot);
  24129. };
  24130. const handleSelectionDrag = ({ detail }) => {
  24131. const { boundsLimited, boundsIntent } = translateSelection(detail.direction, detail.translation);
  24132. // update actual image selection rectangle
  24133. set_store_value(imageSelectionRectIntent, $imageSelectionRectIntent = boundsIntent, $imageSelectionRectIntent); // intent needs to be updated first because has no listeners attached
  24134. set_store_value(imageSelectionRect, $imageSelectionRect = boundsLimited, $imageSelectionRect);
  24135. };
  24136. const handleSelectionRelease = ({ detail }) => {
  24137. const { boundsLimited } = translateSelection(detail.direction, detail.translation);
  24138. // we're no longer interacting with the image selection, we need to set this here so the image selection presentation is animated when applying the new bounds below
  24139. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24140. // no more intent as we're finalizing the selection, so before setting the final selection, we set this to undefined | intent needs to be updated first because has no listeners attached
  24141. set_store_value(imageSelectionRectIntent, $imageSelectionRectIntent = undefined, $imageSelectionRectIntent);
  24142. // confirm the limited rect if actually made a change
  24143. if (vectorLength(detail.translation)) {
  24144. set_store_value(imageSelectionRect, $imageSelectionRect = boundsLimited, $imageSelectionRect);
  24145. history.write();
  24146. }
  24147. // need to set this to undefined after setting the final rect, the snapshot is used to calculate the crop rect transform
  24148. set_store_value(imageSelectionRectSnapshot, $imageSelectionRectSnapshot = undefined, $imageSelectionRectSnapshot);
  24149. // done interacting with selection
  24150. interaction = undefined;
  24151. };
  24152. const translateSelection = (target, translate) => {
  24153. // - selection may grow to max bounds (util bounds)
  24154. // - the image preview(!) is scaled to fit the selection, actual image size is not affected
  24155. // - we need to make sure the selection adheres to the aspect ratio of the min size
  24156. const directionTranslation = { target, translate };
  24157. let rectIntended = applyRectDirectionTranslation($imageSelectionRectSnapshot, directionTranslation, { aspectRatio: $imageCropAspectRatio });
  24158. let cropAspectRatioLimited;
  24159. // size in crop rect
  24160. const cropSize = sizeCreateFromRect(rectDivide(rectClone(rectIntended), $presentationScalar));
  24161. getImagePolygon($imageSize, $imageRotation);
  24162. // if one of the edges is small and not both are smaller we need to correct
  24163. if (cropSize.width < $imageCropMinSize.width || cropSize.height < $imageCropMinSize.height) {
  24164. // if moving towards the center of the crop, it can't exceed bounds
  24165. const translateUp = translate.y < 0;
  24166. const translateRight = translate.x > 0;
  24167. const translateLeft = translate.x < 0;
  24168. const translateDown = translate.y > 0;
  24169. const couldExceedBounds = target === "t" && translateUp || target === "r" && translateRight || target === "b" && translateDown || target === "l" && translateLeft || target === "tr" && (translateRight || translateUp) || target === "tl" && (translateLeft || translateUp) || target === "br" && (translateRight || translateDown) || target === "bl" && (translateLeft || translateDown);
  24170. // need the aspect ratio of the crop to determine if it violates min size
  24171. const cropAspectRatio = rectAspectRatio(cropSize);
  24172. // find the maximum size for the current aspect ratio
  24173. const cropSizeMax = getMaxSizeInRect($imageSize, $imageRotation, cropAspectRatio);
  24174. if (couldExceedBounds && (cropSizeMax.width < $imageCropMinSize.width || cropSizeMax.height < $imageCropMinSize.height)) {
  24175. if ($imageRotation !== 0) {
  24176. const sign = Math.sign($imageRotation);
  24177. const turns = Math.round(Math.abs($imageRotation) / HALF_PI) * HALF_PI;
  24178. const value = $imageRotation - sign * turns;
  24179. const imageIsRotated = turns / HALF_PI % 2 === 1;
  24180. const imageWidth = imageIsRotated ? $imageSize.height : $imageSize.width;
  24181. const imageHeight = imageIsRotated ? $imageSize.width : $imageSize.height;
  24182. const r = Math.abs(value);
  24183. const sin = Math.sin(r);
  24184. const cos = Math.cos(r);
  24185. if (cropSize.width < $imageCropMinSize.width) {
  24186. // width doesn't fit, let's limit the width to the min size
  24187. cropSize.width = $imageCropMinSize.width;
  24188. // And now calculate the height
  24189. // - rotation = .15
  24190. // - image size = 384 x 288
  24191. // - crop size width = 200
  24192. // height = 288 - (Math.sin(.15) * 200) / Math.cos(.15)
  24193. const w = cos * cropSize.width + sin * cropSize.height;
  24194. const h = sin * cropSize.width + cos * cropSize.height;
  24195. const dx = imageWidth - w;
  24196. const dy = imageHeight - h;
  24197. if (dx < dy) {
  24198. cropSize.height = (imageWidth - cos * cropSize.width) / sin;
  24199. } else if (dy < dx) {
  24200. cropSize.height = (imageHeight - sin * cropSize.width) / cos;
  24201. }
  24202. }
  24203. if (cropSize.height < $imageCropMinSize.height) {
  24204. // height doesn't fit, let's limit the height to the min size
  24205. cropSize.height = $imageCropMinSize.height;
  24206. // And now calculate the width
  24207. // - rotation = .15
  24208. // - image size = 384 x 288
  24209. // - crop size height = 200
  24210. const w = cos * cropSize.width + sin * cropSize.height;
  24211. const h = sin * cropSize.width + cos * cropSize.height;
  24212. const dx = imageWidth - w;
  24213. const dy = imageHeight - h;
  24214. if (dx < dy) {
  24215. // (384 - (Math.sin(.15) * 250)) / Math.cos(.15)
  24216. cropSize.width = (imageWidth - sin * cropSize.height) / cos;
  24217. } else if (dy < dx) {
  24218. // (288 - (Math.cos(.15) * 250)) / Math.sin(.15)
  24219. cropSize.width = (imageHeight - cos * cropSize.height) / sin;
  24220. }
  24221. }
  24222. } else {
  24223. if (cropSize.width < $imageCropMinSize.width) {
  24224. cropSize.width = $imageCropMinSize.width;
  24225. cropSize.height = $imageSize.height;
  24226. }
  24227. if (cropSize.height < $imageCropMinSize.height) {
  24228. cropSize.height = $imageCropMinSize.height;
  24229. cropSize.width = $imageSize.width;
  24230. }
  24231. }
  24232. // we now have a corrected size, let's calculate the new aspect ratio and use that to limit the translation
  24233. cropAspectRatioLimited = rectAspectRatio(cropSize);
  24234. }
  24235. }
  24236. if (cropAspectRatioLimited) {
  24237. rectIntended = applyRectDirectionTranslation($imageSelectionRectSnapshot, directionTranslation, {
  24238. aspectRatio: cropAspectRatioLimited || $imageCropAspectRatio
  24239. });
  24240. }
  24241. let rectLimited = limitRectDirectionTranslation($imageSelectionRectSnapshot, directionTranslation, $utilRect, {
  24242. aspectRatio: $imageCropAspectRatio || cropAspectRatioLimited,
  24243. minSize: imageSelectionRectMinSize,
  24244. maxSize: imageSelectionRectMaxSize
  24245. });
  24246. return {
  24247. boundsLimited: rectLimited,
  24248. boundsIntent: rectIntended
  24249. };
  24250. };
  24251. //
  24252. // rotating
  24253. //
  24254. const handleRotateStart = () => {
  24255. interaction = "rotate";
  24256. // now interacting with view
  24257. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24258. // we need to know the origin of the crop so we can "shrink" the image to fit the crop rect while rotating
  24259. set_store_value(imageCropRectOrigin, $imageCropRectOrigin = rectClone($imageCropRect), $imageCropRectOrigin);
  24260. };
  24261. const handleRotateMove = value => {
  24262. set_store_value(imageRotation, $imageRotation = value, $imageRotation); // will auto validate
  24263. };
  24264. const handleRotateEnd = value => {
  24265. // we're done interacting
  24266. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24267. // apply our final rotation value
  24268. set_store_value(imageRotation, $imageRotation = value, $imageRotation);
  24269. history.write();
  24270. // done, so we no longer need to "shrink" the image
  24271. set_store_value(imageCropRectOrigin, $imageCropRectOrigin = undefined, $imageCropRectOrigin);
  24272. };
  24273. //
  24274. // moving
  24275. //
  24276. let interactionCropRect = undefined;
  24277. let interactionCropRectForce = undefined;
  24278. const handleImageDragStart = () => {
  24279. interaction = "pan";
  24280. interactionCropRectForce = undefined;
  24281. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24282. interactionCropRect = rectClone($imageCropRect);
  24283. };
  24284. const handleImageDrag = ({ detail }) => manipulateImage(detail);
  24285. const handleImageDragEnd = ({ detail }) => {
  24286. // done interacting
  24287. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24288. // apply translation to the crop rect only if did make changes
  24289. if (vectorLength(detail.translation) > 0 || detail.scalar !== 0) {
  24290. manipulateImage(detail);
  24291. history.write();
  24292. }
  24293. // no intent (needs to be set before crop rect is updated)
  24294. set_store_value(imageCropRectIntent, $imageCropRectIntent = undefined, $imageCropRectIntent);
  24295. // now done
  24296. interactionCropRect = undefined;
  24297. };
  24298. const handleImageDragRelease = ({ detail }) => {
  24299. interactionCropRectForce = detail.translation;
  24300. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24301. };
  24302. const manipulateImage = ({ translation, scalar }) => {
  24303. const imageSelectionRectZoomFactor = Math.min($imageSelectionRect.width / $imageCropRect.width, $imageSelectionRect.height / $imageCropRect.height);
  24304. const scaledTranslation = vectorMultiply(vectorClone(translation), 1 / imageSelectionRectZoomFactor);
  24305. // while we're interacting we apply changes to the original crop rectangle, after we apply a force
  24306. let cropIntent;
  24307. if (!interactionCropRectForce) {
  24308. cropIntent = rectTranslate(rectClone(interactionCropRect), vectorInvert(vectorClone(scaledTranslation)));
  24309. if (scalar !== undefined) {
  24310. rectScale(cropIntent, 1 / scalar);
  24311. } // rectScale(cropIntent, scalar);
  24312. } else {
  24313. // we apply the force to the existing crop rect so animation is not borked
  24314. const forceTranslation = vectorSubtract(vectorClone(interactionCropRectForce), translation);
  24315. interactionCropRectForce = translation;
  24316. cropIntent = rectTranslate(rectClone($imageCropRect), forceTranslation);
  24317. }
  24318. // update crop rect
  24319. set_store_value(imageCropRectIntent, $imageCropRectIntent = cropIntent, $imageCropRectIntent); // auto calculates an elastic effect if bounds exceeded (needs to be set before crop rect is updated)
  24320. set_store_value(imageCropRect, $imageCropRect = cropIntent, $imageCropRect); // auto limits to bounds if needed
  24321. };
  24322. //
  24323. // resizing with range input
  24324. //
  24325. const calculateZoomLevel = (imageSize, size, imageRotation) => {
  24326. if (isRotatedSideways(imageRotation)) {
  24327. return 1 - 1 / Math.min(imageSize.height / size.width, imageSize.width / size.height);
  24328. }
  24329. return 1 - 1 / Math.min(imageSize.width / size.width, imageSize.height / size.height);
  24330. };
  24331. const imageCropRangeAspectRatio = derived([imageCropRange, imageCropRect], ([$imageCropRange, $imageCropRect], set) => {
  24332. if (!$imageCropRect) return;
  24333. const [minSize, maxSize] = $imageCropRange;
  24334. const aspectRatio = rectAspectRatio($imageCropRect);
  24335. set([
  24336. sizeCreateFromRect(rectApply(rectCoverRect(minSize, aspectRatio), fixPrecision)),
  24337. sizeCreateFromRect(rectApply(rectContainRect(maxSize, aspectRatio), fixPrecision))
  24338. ]);
  24339. });
  24340. component_subscribe($$self, imageCropRangeAspectRatio, value => $$invalidate(165, $imageCropRangeAspectRatio = value));
  24341. // this is the max value range that can be set (triggers white range indicator bar)
  24342. const imageZoomLevelRange = derived(
  24343. [
  24344. imageSize,
  24345. imageCropLimitToImage,
  24346. imageCropMinSize,
  24347. imageCropMaxSize,
  24348. imageCropRange,
  24349. imageRotation
  24350. ],
  24351. ([
  24352. $imageSize,
  24353. $imageCropLimitToImage,
  24354. $imageCropMinSize,
  24355. $imageCropMaxSize,
  24356. $imageCropRange,
  24357. $imageRotation
  24358. ], set) => {
  24359. if (!$imageSize) return;
  24360. const rangeMinSize = $imageCropRange[0];
  24361. const rangeMaxSize = $imageCropRange[1];
  24362. let minZoom;
  24363. let maxZoom;
  24364. // can't zoom out
  24365. if ($imageCropLimitToImage) {
  24366. minZoom = calculateZoomLevel($imageSize, rangeMaxSize, $imageRotation);
  24367. maxZoom = Math.min(rangeMinSize.width / $imageCropMinSize.width, rangeMinSize.height / $imageCropMinSize.height);
  24368. } else {
  24369. maxZoom = 1;
  24370. minZoom = -1;
  24371. }
  24372. const range = [fixPrecision(minZoom), fixPrecision(maxZoom)];
  24373. set(range);
  24374. }
  24375. );
  24376. component_subscribe($$self, imageZoomLevelRange, value => $$invalidate(25, $imageZoomLevelRange = value));
  24377. const imageZoomLevel = derived([imageSize, imageCropRect, imageCropRange, imageRotation], ([$imageSize, $imageCropRect, $imageCropRange, $imageRotation], set) => {
  24378. // need to check if this value is set, could be that it's empty while loading a new image
  24379. if (!$imageSize || !$imageCropRect) return set(0);
  24380. let z;
  24381. const rangeMinSize = $imageCropRange[0];
  24382. const rangeMaxSize = $imageCropRange[1];
  24383. const currentCropWidth = $imageCropRect.width;
  24384. const currentCropHeight = $imageCropRect.height;
  24385. const currentCropAspectRatio = rectAspectRatio($imageCropRect);
  24386. const imageRect = isRotatedSideways($imageRotation)
  24387. ? sizeCreate($imageSize.height, $imageSize.width)
  24388. : $imageSize;
  24389. const imageCropMaxRect = rectContainRect(imageRect, currentCropAspectRatio);
  24390. if (currentCropWidth <= imageCropMaxRect.width || currentCropHeight <= imageCropMaxRect.height) {
  24391. // zoomed in
  24392. const w = imageCropMaxRect.width - rangeMinSize.width;
  24393. const h = imageCropMaxRect.height - rangeMinSize.height;
  24394. // cannot zoom in
  24395. if (w === 0 || h === 0) {
  24396. z = 1;
  24397. } else {
  24398. z = 1 - Math.min((currentCropWidth - rangeMinSize.width) / w, (currentCropHeight - rangeMinSize.height) / h);
  24399. }
  24400. } else {
  24401. // zoomed out
  24402. const w = rangeMaxSize.width - imageCropMaxRect.width;
  24403. const h = rangeMaxSize.height - imageCropMaxRect.height;
  24404. const r = rectContainRect({ width: w, height: h }, currentCropAspectRatio);
  24405. z = -Math.min((currentCropWidth - imageCropMaxRect.width) / r.width, (currentCropHeight - imageCropMaxRect.height) / r.height);
  24406. }
  24407. set(z);
  24408. });
  24409. component_subscribe($$self, imageZoomLevel, value => $$invalidate(26, $imageZoomLevel = value));
  24410. const snapshotCropRect = () => {
  24411. interactionCropRect = rectClone($imageCropRect);
  24412. };
  24413. const resizeImage = zoom => {
  24414. const aspectRatio = rectAspectRatio(interactionCropRect);
  24415. let targetWidth;
  24416. let targetHeight;
  24417. let r;
  24418. const imageRect = isRotatedSideways($imageRotation)
  24419. ? sizeCreate($imageSize.height, $imageSize.width)
  24420. : $imageSize;
  24421. const imageCropMaxRect = rectContainRect(imageRect, aspectRatio);
  24422. if (zoom >= 0) {
  24423. // zoom in
  24424. const rangeWidth = imageCropMaxRect.width - $imageCropRange[0].width;
  24425. const rangeHeight = imageCropMaxRect.height - $imageCropRange[0].height;
  24426. targetWidth = imageCropMaxRect.width - rangeWidth * zoom;
  24427. targetHeight = imageCropMaxRect.height - rangeHeight * zoom;
  24428. r = rectCoverRect({ width: targetWidth, height: targetHeight }, aspectRatio);
  24429. } else {
  24430. // zoom out
  24431. const rangeWidth = $imageCropRange[1].width - imageCropMaxRect.width;
  24432. const rangeHeight = $imageCropRange[1].height - imageCropMaxRect.height;
  24433. targetWidth = imageCropMaxRect.width + rangeWidth * -zoom;
  24434. targetHeight = imageCropMaxRect.height + rangeHeight * -zoom;
  24435. r = rectContainRect({ width: targetWidth, height: targetHeight }, aspectRatio);
  24436. }
  24437. targetWidth = r.width;
  24438. targetHeight = r.height;
  24439. const targetX = interactionCropRect.x + interactionCropRect.width * 0.5 - targetWidth * 0.5;
  24440. const targetY = interactionCropRect.y + interactionCropRect.height * 0.5 - targetHeight * 0.5;
  24441. set_store_value(
  24442. imageCropRect,
  24443. $imageCropRect = {
  24444. x: targetX,
  24445. y: targetY,
  24446. width: targetWidth,
  24447. height: targetHeight
  24448. },
  24449. $imageCropRect
  24450. );
  24451. };
  24452. const handleResizeStart = () => {
  24453. interaction = "zoom";
  24454. // now interacting with view
  24455. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24456. snapshotCropRect();
  24457. };
  24458. const handleResizeMove = value => {
  24459. // value range from 0 (no zoom) to 1 (100% zoom, 1x1 pixel)
  24460. resizeImage(value);
  24461. };
  24462. const handleResizeEnd = value => {
  24463. resizeImage(value);
  24464. history.write();
  24465. // we're done interacting
  24466. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24467. // now done
  24468. interactionCropRect = undefined;
  24469. };
  24470. //
  24471. // resizing with gesture (MacBook trackpad Safari)
  24472. //
  24473. let gestureOriginCropRect;
  24474. const handleGestureStart = () => {
  24475. interaction = "zoom";
  24476. // don't handle gesture as we're already handling input with interactable
  24477. if (interactionCropRect) return;
  24478. gestureOriginCropRect = rectClone($imageCropRect);
  24479. // now interacting
  24480. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24481. };
  24482. const handleGestureUpdate = ({ detail }) => {
  24483. // don't handle gesture as we're already handling input with interactable
  24484. if (!gestureOriginCropRect) return;
  24485. handleScaleGesture(detail);
  24486. };
  24487. const handleScaleGesture = scale => {
  24488. const cropIntent = rectScale(rectClone(gestureOriginCropRect), 1 / scale);
  24489. set_store_value(imageCropRectIntent, $imageCropRectIntent = cropIntent, $imageCropRectIntent);
  24490. set_store_value(imageCropRect, $imageCropRect = cropIntent, $imageCropRect);
  24491. };
  24492. const handleGestureEnd = ({ detail }) => {
  24493. // don't handle gesture as we're already handling input with interactable
  24494. if (!gestureOriginCropRect) return;
  24495. // now interacting
  24496. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24497. handleScaleGesture(detail);
  24498. // no intent (needs to be set before crop rect is updated)
  24499. set_store_value(imageCropRectIntent, $imageCropRectIntent = undefined, $imageCropRectIntent);
  24500. gestureOriginCropRect = undefined;
  24501. history.write();
  24502. };
  24503. //
  24504. // resizing with wheel
  24505. //
  24506. let zoomHistoryTimeoutId;
  24507. const handleWheel = e => {
  24508. const stageWheelPosition = getEventPositionInStage(e, $rootRect, $stageRect);
  24509. // only block input if wheel is used within image rectangle
  24510. if (cropEnableLimitWheelInputToCropSelection && !rectContainsPoint($imageSelectionRect, stageWheelPosition)) return;
  24511. interaction = "zoom";
  24512. // now interacting
  24513. set_store_value(isInteracting, $isInteracting = true, $isInteracting);
  24514. // don't run default actions, prevent other actions from running
  24515. e.preventDefault();
  24516. e.stopPropagation();
  24517. // convert wheel delta to scalar
  24518. const delta = getWheelDelta(e);
  24519. const scalar = 1 + delta / 100;
  24520. // get current crop rect
  24521. const currentCropRect = rectClone($imageCropRect);
  24522. // if already zoomed in, block further zoom in instructions
  24523. const isMinSize = Math.min($imageCropRect.width / $imageCropMinSize.width, $imageCropRect.height / $imageCropMinSize.height) === 1;
  24524. // if is fully zoomed out and trying to zoom out more and crop shape is free, fit image aspect ratio
  24525. if (cropEnableZoomMatchImageAspectRatio && $imageCropLimitToImage) {
  24526. const isAtMaxCropSize = isCropMaxSize($imageCropRect, $imageSize, $imageRotation);
  24527. if (isCustomCrop() && isAtMaxCropSize && delta > 0 && isImageSelectionCentered) {
  24528. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24529. const newCropRect = isRotatedSideways($imageRotation)
  24530. ? rectCreateFromSize({
  24531. height: $imageSize.width,
  24532. width: $imageSize.height
  24533. })
  24534. : rectCreateFromSize($imageSize);
  24535. // no change, exit
  24536. if (rectEqual(currentCropRect, newCropRect)) return;
  24537. // if we were previously zooming in we need to clear the timeout to prevent two history entries
  24538. clearTimeout(zoomHistoryTimeoutId);
  24539. // test if crop rect in history is same as new crop rect, this is possible when zooming in and out real quick
  24540. if (rectEqual(history.state.crop, newCropRect)) return;
  24541. // store new crop rect
  24542. set_store_value(imageCropRect, $imageCropRect = newCropRect, $imageCropRect);
  24543. history.write();
  24544. return;
  24545. }
  24546. }
  24547. // by default when zooming, zoom from center of crop rectangle
  24548. let origin = rectCenter($imageCropRect);
  24549. // when zooming in, zoom in on the part of the image below the mouse cursor
  24550. if (cropEnableZoomTowardsWheelPosition && delta < 0 && !isMinSize) {
  24551. const selectionOffset = vectorSubtract(vectorClone(stageWheelPosition), $imageSelectionRect);
  24552. const imageSelectionScale = Math.min($imageSelectionRect.width / $imageCropRect.width, $imageSelectionRect.height / $imageCropRect.height);
  24553. // if wheel is inside image selection rectangle (slightly expanded version), we zoom based on position in the rectangle, if not, we use the selection center
  24554. const expandedImageSelection = rectScale(rectClone($imageSelectionRect), 1.1);
  24555. origin = rectContainsPoint(expandedImageSelection, stageWheelPosition)
  24556. ? vectorAdd(rectClone($imageCropRect), vectorMultiply(selectionOffset, 1 / imageSelectionScale))
  24557. : origin;
  24558. }
  24559. let newCropRect = rectScale(rectClone($imageCropRect), scalar, origin);
  24560. // determin if is new crop rect exceeds min or max size, if so, limit
  24561. if (!sizeContains($imageCropRangeAspectRatio[1], newCropRect)) {
  24562. // exceeds max size, limit to max size and position at new crop rect center
  24563. newCropRect = rectCreateWithCenter(rectCenter(newCropRect), $imageCropRangeAspectRatio[1]);
  24564. }
  24565. if (!sizeContains(newCropRect, $imageCropRangeAspectRatio[0])) {
  24566. // exceeds min size, limit to min size and position at new crop rect center
  24567. newCropRect = rectCreateWithCenter(rectCenter(newCropRect), $imageCropRangeAspectRatio[0]);
  24568. }
  24569. // no change, exit
  24570. if (rectEqual(currentCropRect, newCropRect, fixPrecision)) {
  24571. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24572. return;
  24573. }
  24574. // attempt to update the rectangle, we use fixPrecision so the width and height are nice integers when at max zoom (this makes sure the `isMinSize` variable is set to true at this point)
  24575. set_store_value(imageCropRect, $imageCropRect = rectApply(newCropRect, v => fixPrecision(v, 5)), $imageCropRect);
  24576. // done!
  24577. set_store_value(isInteracting, $isInteracting = false, $isInteracting);
  24578. // write history timer
  24579. clearTimeout(zoomHistoryTimeoutId);
  24580. zoomHistoryTimeoutId = setTimeout(
  24581. () => {
  24582. history.write();
  24583. },
  24584. 500
  24585. );
  24586. };
  24587. //
  24588. // recenter
  24589. //
  24590. // the 'measure' event triggers the editor to center and scale up the crop
  24591. const dispatch = createEventDispatcher();
  24592. const handleRecenterAction = () => {
  24593. dispatch("measure", rectClone($utilRect));
  24594. };
  24595. // auto recenter after timeout
  24596. let cropAutoCenterImageSelectionTimeoutId;
  24597. // animations
  24598. const recenterOpacity = spring(0, { precision: 0.0001 });
  24599. component_subscribe($$self, recenterOpacity, value => $$invalidate(27, $recenterOpacity = value));
  24600. const recenterOffset = spring();
  24601. component_subscribe($$self, recenterOffset, value => $$invalidate(28, $recenterOffset = value));
  24602. //
  24603. // crop selection presets
  24604. //
  24605. const selectedPresetIndex = derived([imageCropAspectRatio, imageOutputSize], ([$cropAspectRatio, $imageOutputSize], set) => {
  24606. if (!cropSelectPresetOptions) return;
  24607. const options = flattenOptions(cropSelectPresetOptions);
  24608. const matchedOptionValue = [...options].// to value
  24609. map(option => option[0]).// sort sizes first
  24610. sort((a, b) => {
  24611. if (isArray(a[0]) && !isArray(b[0])) return 1;
  24612. return -1;
  24613. }).// match value
  24614. find(value => {
  24615. if (isArray(value) && $imageOutputSize) {
  24616. // size + aspect ratio
  24617. const [width, height] = value;
  24618. const outputSizeMatches = $imageOutputSize.width === width && $imageOutputSize.height === height;
  24619. const aspectRatioMatches = $cropAspectRatio === getAspectRatio(width, height);
  24620. return outputSizeMatches && aspectRatioMatches;
  24621. }
  24622. // aspect ratio
  24623. return value === $cropAspectRatio;
  24624. });
  24625. const index = options.// to value
  24626. map(option => option[0]).// find index of matching value
  24627. findIndex(value => isArray(value)
  24628. ? arrayEqual(value, matchedOptionValue)
  24629. : value === matchedOptionValue);
  24630. set(index);
  24631. });
  24632. component_subscribe($$self, selectedPresetIndex, value => $$invalidate(114, $selectedPresetIndex = value));
  24633. const getAspectRatioBySelectedIndex = selectedIndex => {
  24634. if (!cropSelectPresetOptions || selectedIndex === -1) return;
  24635. const selectedValue = flattenOptions(cropSelectPresetOptions)[selectedIndex][0];
  24636. return !selectedValue
  24637. ? undefined
  24638. : isArray(selectedValue)
  24639. ? getAspectRatio(selectedValue[0], selectedValue[1])
  24640. : selectedValue;
  24641. };
  24642. //
  24643. // crop guides
  24644. //
  24645. const imageSelectionGuides = derived([rootLineColor, imageSelectionRectPresentation, isInteractingFraction], ([$rootLineColor, $rect, $isInteractingFraction], set) => {
  24646. const { rows, cols, opacity } = cropWillRenderImageSelectionGuides(interaction, $isInteractingFraction);
  24647. if (!$rect || opacity <= 0) return set([]);
  24648. const { x, y, width, height } = $rect;
  24649. const w = width / cols;
  24650. const h = height / rows;
  24651. const shapes = [];
  24652. // rows
  24653. for (let r = 1; r <= rows - 1; r++) {
  24654. const yo = y + h * r;
  24655. shapes.push({
  24656. id: `image-selection-guide-row-${r}`,
  24657. points: [vectorCreate(x, yo), vectorCreate(x + width, yo)],
  24658. opacity,
  24659. strokeWidth: 1,
  24660. strokeColor: $rootLineColor
  24661. });
  24662. }
  24663. // cols
  24664. for (let c = 1; c <= cols - 1; c++) {
  24665. const xo = x + w * c;
  24666. shapes.push({
  24667. id: `image-selection-guide-col-${c}`,
  24668. points: [vectorCreate(xo, y), vectorCreate(xo, y + height)],
  24669. opacity,
  24670. strokeWidth: 1,
  24671. strokeColor: $rootLineColor
  24672. });
  24673. }
  24674. set(shapes);
  24675. });
  24676. component_subscribe($$self, imageSelectionGuides, value => $$invalidate(137, $imageSelectionGuides = value));
  24677. const syncGuides = () => {
  24678. // remove existing guides
  24679. const overlayMarkup = $imageOverlayMarkup.filter(markup => !(/^image\-selection\-guide/).test(markup.id));
  24680. if ($isActive) {
  24681. set_store_value(imageOverlayMarkup, $imageOverlayMarkup = [...overlayMarkup, ...$imageSelectionGuides], $imageOverlayMarkup);
  24682. } else {
  24683. set_store_value(imageOverlayMarkup, $imageOverlayMarkup = overlayMarkup, $imageOverlayMarkup);
  24684. }
  24685. };
  24686. const cropUniqueId = `crop-${getUniqueId()}`;
  24687. let transformInitial = cropEnableRotationInput ? "rotation" : "zoom";
  24688. let transformToolInitial = cropUniqueId + "-" + transformInitial;
  24689. let transformSelected = transformToolInitial;
  24690. let root = undefined;
  24691. // fixes rendering issue with stage being empty in overlay mode, this basically redispatches the measure event so the stage is correctly measured
  24692. let stageRef;
  24693. const footerOffset = spring($animation ? 20 : 0);
  24694. component_subscribe($$self, footerOffset, value => $$invalidate(142, $footerOffset = value));
  24695. function measure_handler_1(event) {
  24696. bubble($$self, event);
  24697. }
  24698. const select_handler = ({ detail }) => $$invalidate(5, transformSelected = detail);
  24699. function div0_binding($$value) {
  24700. binding_callbacks[$$value ? "unshift" : "push"](() => {
  24701. stageRef = $$value;
  24702. $$invalidate(6, stageRef);
  24703. });
  24704. }
  24705. const interactable_function = e => getEventPositionInViewport(e);
  24706. function util_root_binding(value) {
  24707. root = value;
  24708. $$invalidate(13, root);
  24709. }
  24710. function measure_handler(event) {
  24711. bubble($$self, event);
  24712. }
  24713. $$self.$$set = $$props => {
  24714. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(1, isActive = $$props.isActive));
  24715. if ("stores" in $$props) $$invalidate(88, stores = $$props.stores);
  24716. if ("cropImageSelectionCornerStyle" in $$props) $$invalidate(2, cropImageSelectionCornerStyle = $$props.cropImageSelectionCornerStyle);
  24717. if ("cropWillRenderImageSelectionGuides" in $$props) $$invalidate(89, cropWillRenderImageSelectionGuides = $$props.cropWillRenderImageSelectionGuides);
  24718. if ("cropAutoCenterImageSelectionTimeout" in $$props) $$invalidate(90, cropAutoCenterImageSelectionTimeout = $$props.cropAutoCenterImageSelectionTimeout);
  24719. if ("cropEnableZoomMatchImageAspectRatio" in $$props) $$invalidate(91, cropEnableZoomMatchImageAspectRatio = $$props.cropEnableZoomMatchImageAspectRatio);
  24720. if ("cropEnableRotateMatchImageAspectRatio" in $$props) $$invalidate(92, cropEnableRotateMatchImageAspectRatio = $$props.cropEnableRotateMatchImageAspectRatio);
  24721. if ("cropEnableRotationInput" in $$props) $$invalidate(93, cropEnableRotationInput = $$props.cropEnableRotationInput);
  24722. if ("cropEnableZoom" in $$props) $$invalidate(3, cropEnableZoom = $$props.cropEnableZoom);
  24723. if ("cropEnableZoomInput" in $$props) $$invalidate(94, cropEnableZoomInput = $$props.cropEnableZoomInput);
  24724. if ("cropEnableZoomAutoHide" in $$props) $$invalidate(95, cropEnableZoomAutoHide = $$props.cropEnableZoomAutoHide);
  24725. if ("cropEnableImageSelection" in $$props) $$invalidate(96, cropEnableImageSelection = $$props.cropEnableImageSelection);
  24726. if ("cropEnableInfoIndicator" in $$props) $$invalidate(97, cropEnableInfoIndicator = $$props.cropEnableInfoIndicator);
  24727. if ("cropEnableZoomTowardsWheelPosition" in $$props) $$invalidate(98, cropEnableZoomTowardsWheelPosition = $$props.cropEnableZoomTowardsWheelPosition);
  24728. if ("cropEnableLimitWheelInputToCropSelection" in $$props) $$invalidate(99, cropEnableLimitWheelInputToCropSelection = $$props.cropEnableLimitWheelInputToCropSelection);
  24729. if ("cropEnableCenterImageSelection" in $$props) $$invalidate(100, cropEnableCenterImageSelection = $$props.cropEnableCenterImageSelection);
  24730. if ("cropEnableButtonRotateLeft" in $$props) $$invalidate(101, cropEnableButtonRotateLeft = $$props.cropEnableButtonRotateLeft);
  24731. if ("cropEnableButtonRotateRight" in $$props) $$invalidate(102, cropEnableButtonRotateRight = $$props.cropEnableButtonRotateRight);
  24732. if ("cropEnableButtonFlipHorizontal" in $$props) $$invalidate(103, cropEnableButtonFlipHorizontal = $$props.cropEnableButtonFlipHorizontal);
  24733. if ("cropEnableButtonFlipVertical" in $$props) $$invalidate(104, cropEnableButtonFlipVertical = $$props.cropEnableButtonFlipVertical);
  24734. if ("cropSelectPresetOptions" in $$props) $$invalidate(105, cropSelectPresetOptions = $$props.cropSelectPresetOptions);
  24735. if ("cropEnableSelectPreset" in $$props) $$invalidate(106, cropEnableSelectPreset = $$props.cropEnableSelectPreset);
  24736. if ("cropEnableButtonToggleCropLimit" in $$props) $$invalidate(107, cropEnableButtonToggleCropLimit = $$props.cropEnableButtonToggleCropLimit);
  24737. if ("cropWillRenderTools" in $$props) $$invalidate(108, cropWillRenderTools = $$props.cropWillRenderTools);
  24738. if ("locale" in $$props) $$invalidate(4, locale = $$props.locale);
  24739. if ("tools" in $$props) $$invalidate(0, tools = $$props.tools);
  24740. };
  24741. $$self.$$.update = () => {
  24742. if ($$self.$$.dirty[3] & /*$env*/ 33554432) {
  24743. $$invalidate(132, isOverlayMode = $env.layoutMode === "overlay");
  24744. }
  24745. if ($$self.$$.dirty[3] & /*cropEnableSelectPreset*/ 8192 | $$self.$$.dirty[4] & /*isOverlayMode*/ 256) {
  24746. $$invalidate(113, shouldRenderPresetSelect = cropEnableSelectPreset && !isOverlayMode);
  24747. }
  24748. if ($$self.$$.dirty[3] & /*$utilRect, $imageSelectionRect*/ 1342177280) {
  24749. // determine if we can center the crop, if we can, show the crop center button
  24750. $$invalidate(128, imageSelectionCenteredRect = $utilRect && $imageSelectionRect && rectCenterRect($utilRect, $imageSelectionRect));
  24751. }
  24752. if ($$self.$$.dirty[3] & /*$imageSelectionRect*/ 268435456 | $$self.$$.dirty[4] & /*imageSelectionCenteredRect*/ 16) {
  24753. $$invalidate(129, isImageSelectionDisplayed = !!($imageSelectionRect && imageSelectionCenteredRect));
  24754. }
  24755. if ($$self.$$.dirty[3] & /*$imageSelectionRect*/ 268435456 | $$self.$$.dirty[4] & /*isImageSelectionDisplayed, imageSelectionCenteredRect*/ 48) {
  24756. $$invalidate(115, isImageSelectionCentered = isImageSelectionDisplayed && rectEqual($imageSelectionRect, imageSelectionCenteredRect, value => fixPrecision(value, 5)));
  24757. }
  24758. if ($$self.$$.dirty[0] & /*locale, $imageRotation*/ 272 | $$self.$$.dirty[3] & /*cropWillRenderTools, cropEnableButtonRotateLeft, cropEnableButtonRotateRight, cropEnableButtonFlipHorizontal, $imageFlipY, $imageFlipX, cropEnableButtonFlipVertical, shouldRenderPresetSelect, cropSelectPresetOptions, $selectedPresetIndex, isImageSelectionCentered, $imageSize, $imageCropMinSize, cropEnableButtonToggleCropLimit, $imageCropLimitToImage, $env*/ 67034880) {
  24759. $$invalidate(0, tools = cropWillRenderTools(
  24760. [
  24761. cropEnableButtonRotateLeft && [
  24762. "Button",
  24763. "rotate-left",
  24764. {
  24765. label: locale.cropLabelButtonRotateLeft,
  24766. labelClass: "PinturaToolbarContentWide",
  24767. icon: locale.cropIconButtonRotateLeft,
  24768. onclick: () => {
  24769. applyRotation(-Math.PI / 2);
  24770. history.write();
  24771. }
  24772. }
  24773. ],
  24774. cropEnableButtonRotateRight && [
  24775. "Button",
  24776. "rotate-right",
  24777. {
  24778. label: locale.cropLabelButtonRotateRight,
  24779. labelClass: "PinturaToolbarContentWide",
  24780. icon: locale.cropIconButtonRotateRight,
  24781. onclick: () => {
  24782. applyRotation(Math.PI / 2);
  24783. history.write();
  24784. }
  24785. }
  24786. ],
  24787. cropEnableButtonFlipHorizontal && [
  24788. "Button",
  24789. "flip-horizontal",
  24790. {
  24791. label: locale.cropLabelButtonFlipHorizontal,
  24792. labelClass: "PinturaToolbarContentWide",
  24793. icon: locale.cropIconButtonFlipHorizontal,
  24794. onclick: () => {
  24795. if (isRotatedSideways($imageRotation)) {
  24796. set_store_value(imageFlipY, $imageFlipY = !$imageFlipY, $imageFlipY);
  24797. } else {
  24798. set_store_value(imageFlipX, $imageFlipX = !$imageFlipX, $imageFlipX);
  24799. }
  24800. history.write();
  24801. }
  24802. }
  24803. ],
  24804. cropEnableButtonFlipVertical && [
  24805. "Button",
  24806. "flip-vertical",
  24807. {
  24808. label: locale.cropLabelButtonFlipVertical,
  24809. labelClass: "PinturaToolbarContentWide",
  24810. icon: locale.cropIconButtonFlipVertical,
  24811. onclick: () => {
  24812. if (isRotatedSideways($imageRotation)) {
  24813. set_store_value(imageFlipX, $imageFlipX = !$imageFlipX, $imageFlipX);
  24814. } else {
  24815. set_store_value(imageFlipY, $imageFlipY = !$imageFlipY, $imageFlipY);
  24816. }
  24817. history.write();
  24818. }
  24819. }
  24820. ],
  24821. shouldRenderPresetSelect && cropSelectPresetOptions && [
  24822. "Dropdown",
  24823. "select-preset",
  24824. {
  24825. icon: localize(locale.cropIconSelectPreset, locale, getAspectRatioBySelectedIndex($selectedPresetIndex)),
  24826. label: locale.cropLabelSelectPreset,
  24827. labelClass: "PinturaToolbarContentWide",
  24828. options: cropSelectPresetOptions,
  24829. selectedIndex: $selectedPresetIndex,
  24830. onchange: ({ value }) => {
  24831. if (isArray(value)) {
  24832. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = getAspectRatio(value[0], value[1]), $imageCropAspectRatio);
  24833. set_store_value(imageOutputSize, $imageOutputSize = sizeCreateFromArray(value), $imageOutputSize);
  24834. } else {
  24835. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = value, $imageCropAspectRatio);
  24836. }
  24837. if (isImageSelectionCentered) {
  24838. handleRecenterAction();
  24839. }
  24840. history.write();
  24841. },
  24842. optionMapper: option => {
  24843. // if no aspect ratio found we enable the option by default
  24844. let disabled = false;
  24845. // get aspect ratio for this option
  24846. const optionAspectRatio = isArray(option.value)
  24847. ? option.value[0] / option.value[1]
  24848. : option.value;
  24849. // can be undefined in which case we don't need to check anything
  24850. if (optionAspectRatio) {
  24851. const maxCropSize = getMaxSizeInRect($imageSize, $imageRotation, optionAspectRatio);
  24852. disabled = maxCropSize.width < $imageCropMinSize.width || maxCropSize.height < $imageCropMinSize.height;
  24853. }
  24854. // add icon for this option
  24855. option.icon = getSelectionPresetOptionIcon(option.value, { bounds: 14 });
  24856. return { ...option, disabled };
  24857. }
  24858. }
  24859. ],
  24860. cropEnableButtonToggleCropLimit && [
  24861. "Dropdown",
  24862. "select-crop-limit",
  24863. {
  24864. icon: localize(locale.cropIconCropBoundary, locale, $imageCropLimitToImage),
  24865. label: locale.cropLabelCropBoundary,
  24866. labelClass: "PinturaToolbarContentWide",
  24867. onchange: ({ value }) => {
  24868. set_store_value(imageCropLimitToImage, $imageCropLimitToImage = value, $imageCropLimitToImage);
  24869. history.write();
  24870. },
  24871. options: [
  24872. [
  24873. true,
  24874. locale.cropLabelCropBoundaryEdge,
  24875. {
  24876. icon: localize(locale.cropIconCropBoundary, locale, true)
  24877. }
  24878. ],
  24879. [
  24880. false,
  24881. locale.cropLabelCropBoundaryNone,
  24882. {
  24883. icon: localize(locale.cropIconCropBoundary, locale, false)
  24884. }
  24885. ]
  24886. ]
  24887. }
  24888. ]
  24889. ].filter(Boolean),
  24890. $env,
  24891. () => ({})
  24892. ).filter(Boolean));
  24893. }
  24894. if ($$self.$$.dirty[0] & /*$isActive*/ 512) {
  24895. $isActive && imageOutlineOpacity.set(1);
  24896. }
  24897. if ($$self.$$.dirty[3] & /*$imageCropLimitToImage*/ 16777216) {
  24898. $$invalidate(14, imageZoomLevelMin = $imageCropLimitToImage ? 0 : -1);
  24899. }
  24900. if ($$self.$$.dirty[3] & /*$utilRect*/ 1073741824 | $$self.$$.dirty[4] & /*$stageRect*/ 1) {
  24901. $$invalidate(125, imageSelectionOffset = $utilRect && vectorCreate(-($stageRect.x - $utilRect.x), -($stageRect.y - $utilRect.y)));
  24902. }
  24903. if ($$self.$$.dirty[4] & /*$imageSelectionRectPresentation, imageSelectionOffset*/ 10) {
  24904. // normalized crop bounds, we use these to limit the crop interactions to the view
  24905. $$invalidate(126, imageSelectionCenter = $imageSelectionRectPresentation && vectorCreate(snapToPixel($imageSelectionRectPresentation.x + $imageSelectionRectPresentation.width * 0.5 + imageSelectionOffset.x), snapToPixel($imageSelectionRectPresentation.y + $imageSelectionRectPresentation.height * 0.5 + imageSelectionOffset.y)));
  24906. }
  24907. if ($$self.$$.dirty[3] & /*$imageSelectionRectSnapshot*/ 134217728) {
  24908. $$invalidate(130, isResizingSelection = $imageSelectionRectSnapshot != null);
  24909. }
  24910. if ($$self.$$.dirty[3] & /*$utilRect*/ 1073741824 | $$self.$$.dirty[4] & /*imageSelectionCenteredRect*/ 16) {
  24911. $$invalidate(131, isMaxSelectionRect = $utilRect && imageSelectionCenteredRect && (imageSelectionCenteredRect.height === $utilRect.height || imageSelectionCenteredRect.width === $utilRect.width));
  24912. }
  24913. if ($$self.$$.dirty[3] & /*$presentationScalar*/ 536870912 | $$self.$$.dirty[4] & /*isMaxSelectionRect, $imageScalar*/ 1152) {
  24914. $$invalidate(133, canZoomToCenter = !isMaxSelectionRect && $presentationScalar < 1 && $imageScalar < 1);
  24915. }
  24916. if ($$self.$$.dirty[3] & /*isImageSelectionCentered*/ 4194304 | $$self.$$.dirty[4] & /*isImageSelectionDisplayed, isResizingSelection, canZoomToCenter*/ 608) {
  24917. $$invalidate(10, canCenter = isImageSelectionDisplayed && !isResizingSelection && (!isImageSelectionCentered || canZoomToCenter));
  24918. }
  24919. if ($$self.$$.dirty[0] & /*$imageCropRect*/ 128 | $$self.$$.dirty[3] & /*cropEnableInfoIndicator*/ 16 | $$self.$$.dirty[4] & /*isOverlayMode*/ 256) {
  24920. $$invalidate(16, shouldRenderInfoIndicator = cropEnableInfoIndicator && !!$imageCropRect && !isOverlayMode);
  24921. }
  24922. if ($$self.$$.dirty[4] & /*$imageSelectionRectPresentation, imageSelectionOffset*/ 10) {
  24923. $$invalidate(11, imageSelectionRectOffset = $imageSelectionRectPresentation && imageSelectionOffset && {
  24924. x: $imageSelectionRectPresentation.x + imageSelectionOffset.x,
  24925. y: $imageSelectionRectPresentation.y + imageSelectionOffset.y,
  24926. width: $imageSelectionRectPresentation.width,
  24927. height: $imageSelectionRectPresentation.height
  24928. });
  24929. }
  24930. if ($$self.$$.dirty[0] & /*imageSelectionRectOffset*/ 2048 | $$self.$$.dirty[3] & /*cropEnableImageSelection*/ 8 | $$self.$$.dirty[4] & /*isOverlayMode*/ 256) {
  24931. $$invalidate(17, shouldRenderImageSelection = cropEnableImageSelection && !!imageSelectionRectOffset && !isOverlayMode);
  24932. }
  24933. if ($$self.$$.dirty[2] & /*cropAutoCenterImageSelectionTimeout*/ 268435456 | $$self.$$.dirty[3] & /*cropEnableCenterImageSelection*/ 128 | $$self.$$.dirty[4] & /*imageSelectionCenter*/ 4) {
  24934. $$invalidate(18, shouldRenderImageSelectionRecenterButton = cropEnableCenterImageSelection && !!imageSelectionCenter && !cropAutoCenterImageSelectionTimeout);
  24935. }
  24936. if ($$self.$$.dirty[0] & /*canCenter*/ 1024 | $$self.$$.dirty[2] & /*cropAutoCenterImageSelectionTimeout*/ 268435456 | $$self.$$.dirty[3] & /*$isInteracting, cropAutoCenterImageSelectionTimeoutId*/ 67174400) {
  24937. if (canCenter && cropAutoCenterImageSelectionTimeout && !$isInteracting) {
  24938. clearTimeout(cropAutoCenterImageSelectionTimeoutId);
  24939. $$invalidate(109, cropAutoCenterImageSelectionTimeoutId = setTimeout(handleRecenterAction, cropAutoCenterImageSelectionTimeout));
  24940. }
  24941. }
  24942. if ($$self.$$.dirty[3] & /*$isInteracting, cropAutoCenterImageSelectionTimeoutId*/ 67174400) {
  24943. if ($isInteracting) clearTimeout(cropAutoCenterImageSelectionTimeoutId);
  24944. }
  24945. if ($$self.$$.dirty[0] & /*canCenter*/ 1024) {
  24946. recenterOpacity.set(canCenter ? 1 : 0);
  24947. }
  24948. if ($$self.$$.dirty[4] & /*imageSelectionCenter*/ 4) {
  24949. recenterOffset.set(imageSelectionCenter);
  24950. }
  24951. if ($$self.$$.dirty[0] & /*$isActive*/ 512 | $$self.$$.dirty[4] & /*$framePadded, $imagePreviewModifiers*/ 6144) {
  24952. //
  24953. // enable seeing the image outside of the crop area, and disable the vignette effect
  24954. //
  24955. if ($isActive && !$framePadded) {
  24956. set_store_value(
  24957. imagePreviewModifiers,
  24958. $imagePreviewModifiers["crop"] = {
  24959. maskOpacity: 0.85,
  24960. maskMarkupOpacity: 0.85
  24961. },
  24962. $imagePreviewModifiers
  24963. );
  24964. } else {
  24965. delete $imagePreviewModifiers["crop"];
  24966. }
  24967. }
  24968. if ($$self.$$.dirty[4] & /*$imageSelectionGuides*/ 8192) {
  24969. // if overlay top changes
  24970. $imageSelectionGuides && syncGuides();
  24971. }
  24972. if ($$self.$$.dirty[3] & /*$env*/ 33554432) {
  24973. //
  24974. // Transform tabs
  24975. //
  24976. $$invalidate(138, hasPlentyVerticalSpace = $env.verticalSpace !== "short");
  24977. }
  24978. if ($$self.$$.dirty[4] & /*hasPlentyVerticalSpace, isOverlayMode*/ 16640) {
  24979. $$invalidate(19, shouldRenderToolbar = hasPlentyVerticalSpace && !isOverlayMode);
  24980. }
  24981. if ($$self.$$.dirty[0] & /*cropEnableZoom*/ 8 | $$self.$$.dirty[3] & /*cropEnableZoomInput*/ 2) {
  24982. $$invalidate(139, couldRenderZoomInput = cropEnableZoom && cropEnableZoomInput);
  24983. }
  24984. if ($$self.$$.dirty[3] & /*cropEnableZoomAutoHide*/ 4 | $$self.$$.dirty[4] & /*hasPlentyVerticalSpace, couldRenderZoomInput*/ 49152) {
  24985. $$invalidate(140, shouldRenderZoomInput = cropEnableZoomAutoHide
  24986. ? hasPlentyVerticalSpace && couldRenderZoomInput
  24987. : couldRenderZoomInput);
  24988. }
  24989. if ($$self.$$.dirty[3] & /*cropEnableRotationInput*/ 1 | $$self.$$.dirty[4] & /*shouldRenderZoomInput*/ 65536) {
  24990. $$invalidate(20, shouldRenderFooter = cropEnableRotationInput || shouldRenderZoomInput);
  24991. }
  24992. if ($$self.$$.dirty[4] & /*shouldRenderZoomInput*/ 65536) {
  24993. if (!shouldRenderZoomInput) {
  24994. $$invalidate(5, transformSelected = transformToolInitial);
  24995. }
  24996. }
  24997. if ($$self.$$.dirty[0] & /*transformSelected*/ 32) {
  24998. $$invalidate(21, tabsConfig = {
  24999. name: cropUniqueId,
  25000. selected: transformSelected
  25001. });
  25002. }
  25003. if ($$self.$$.dirty[0] & /*locale*/ 16 | $$self.$$.dirty[3] & /*cropEnableRotationInput*/ 1 | $$self.$$.dirty[4] & /*shouldRenderZoomInput*/ 65536) {
  25004. $$invalidate(12, tabs = [
  25005. cropEnableRotationInput && {
  25006. id: cropUniqueId + "-rotation",
  25007. label: locale.cropLabelTabRotation
  25008. },
  25009. shouldRenderZoomInput && {
  25010. id: cropUniqueId + "-zoom",
  25011. label: locale.cropLabelTabZoom
  25012. }
  25013. ].filter(Boolean));
  25014. }
  25015. if ($$self.$$.dirty[0] & /*tabs*/ 4096) {
  25016. $$invalidate(22, panels = tabs.map(tab => tab.id));
  25017. }
  25018. if ($$self.$$.dirty[0] & /*stageRef*/ 64 | $$self.$$.dirty[4] & /*isOverlayMode*/ 256) {
  25019. if (stageRef && !stageRef.children.length && isOverlayMode) {
  25020. stageRef.dispatchEvent(new CustomEvent("measure", { detail: stageRef.rect }));
  25021. }
  25022. }
  25023. if ($$self.$$.dirty[0] & /*$isActive*/ 512 | $$self.$$.dirty[4] & /*$animation*/ 131072) {
  25024. $animation && footerOffset.set($isActive ? 0 : 20);
  25025. }
  25026. if ($$self.$$.dirty[4] & /*$footerOffset*/ 262144) {
  25027. $$invalidate(23, footerStyle = $footerOffset
  25028. ? `transform: translateY(${$footerOffset}px)`
  25029. : undefined);
  25030. }
  25031. };
  25032. return [
  25033. tools,
  25034. isActive,
  25035. cropImageSelectionCornerStyle,
  25036. cropEnableZoom,
  25037. locale,
  25038. transformSelected,
  25039. stageRef,
  25040. $imageCropRect,
  25041. $imageRotation,
  25042. $isActive,
  25043. canCenter,
  25044. imageSelectionRectOffset,
  25045. tabs,
  25046. root,
  25047. imageZoomLevelMin,
  25048. $rootRect,
  25049. shouldRenderInfoIndicator,
  25050. shouldRenderImageSelection,
  25051. shouldRenderImageSelectionRecenterButton,
  25052. shouldRenderToolbar,
  25053. shouldRenderFooter,
  25054. tabsConfig,
  25055. panels,
  25056. footerStyle,
  25057. $imageRotationRange,
  25058. $imageZoomLevelRange,
  25059. $imageZoomLevel,
  25060. $recenterOpacity,
  25061. $recenterOffset,
  25062. env,
  25063. isInteracting,
  25064. rootRect,
  25065. stageRect,
  25066. utilRect,
  25067. animation,
  25068. elasticityMultiplier,
  25069. rangeInputElasticity,
  25070. presentationScalar,
  25071. imagePreviewModifiers,
  25072. imageFlipX,
  25073. imageFlipY,
  25074. imageRotation,
  25075. imageRotationRange,
  25076. imageOutputSize,
  25077. imageSelectionRect,
  25078. imageSelectionRectSnapshot,
  25079. imageSelectionRectIntent,
  25080. imageSelectionRectPresentation,
  25081. imageCropRectIntent,
  25082. imageCropRectOrigin,
  25083. imageCropRect,
  25084. imageCropMinSize,
  25085. imageCropMaxSize,
  25086. imageCropRange,
  25087. imageCropAspectRatio,
  25088. imageCropLimitToImage,
  25089. imageSize,
  25090. imageScalar,
  25091. imageOverlayMarkup,
  25092. framePadded,
  25093. handleSelectionGrab,
  25094. handleSelectionDrag,
  25095. handleSelectionRelease,
  25096. handleRotateStart,
  25097. handleRotateMove,
  25098. handleRotateEnd,
  25099. handleImageDragStart,
  25100. handleImageDrag,
  25101. handleImageDragEnd,
  25102. handleImageDragRelease,
  25103. imageCropRangeAspectRatio,
  25104. imageZoomLevelRange,
  25105. imageZoomLevel,
  25106. handleResizeStart,
  25107. handleResizeMove,
  25108. handleResizeEnd,
  25109. handleGestureStart,
  25110. handleGestureUpdate,
  25111. handleGestureEnd,
  25112. handleWheel,
  25113. handleRecenterAction,
  25114. recenterOpacity,
  25115. recenterOffset,
  25116. selectedPresetIndex,
  25117. imageSelectionGuides,
  25118. cropUniqueId,
  25119. footerOffset,
  25120. name,
  25121. stores,
  25122. cropWillRenderImageSelectionGuides,
  25123. cropAutoCenterImageSelectionTimeout,
  25124. cropEnableZoomMatchImageAspectRatio,
  25125. cropEnableRotateMatchImageAspectRatio,
  25126. cropEnableRotationInput,
  25127. cropEnableZoomInput,
  25128. cropEnableZoomAutoHide,
  25129. cropEnableImageSelection,
  25130. cropEnableInfoIndicator,
  25131. cropEnableZoomTowardsWheelPosition,
  25132. cropEnableLimitWheelInputToCropSelection,
  25133. cropEnableCenterImageSelection,
  25134. cropEnableButtonRotateLeft,
  25135. cropEnableButtonRotateRight,
  25136. cropEnableButtonFlipHorizontal,
  25137. cropEnableButtonFlipVertical,
  25138. cropSelectPresetOptions,
  25139. cropEnableSelectPreset,
  25140. cropEnableButtonToggleCropLimit,
  25141. cropWillRenderTools,
  25142. cropAutoCenterImageSelectionTimeoutId,
  25143. $imageSize,
  25144. $imageFlipY,
  25145. $imageFlipX,
  25146. shouldRenderPresetSelect,
  25147. $selectedPresetIndex,
  25148. isImageSelectionCentered,
  25149. $imageCropMinSize,
  25150. $imageCropLimitToImage,
  25151. $env,
  25152. $isInteracting,
  25153. $imageSelectionRectSnapshot,
  25154. $imageSelectionRect,
  25155. $presentationScalar,
  25156. $utilRect,
  25157. $stageRect,
  25158. imageSelectionOffset,
  25159. imageSelectionCenter,
  25160. $imageSelectionRectPresentation,
  25161. imageSelectionCenteredRect,
  25162. isImageSelectionDisplayed,
  25163. isResizingSelection,
  25164. isMaxSelectionRect,
  25165. isOverlayMode,
  25166. canZoomToCenter,
  25167. $imageScalar,
  25168. $framePadded,
  25169. $imagePreviewModifiers,
  25170. $imageSelectionGuides,
  25171. hasPlentyVerticalSpace,
  25172. couldRenderZoomInput,
  25173. shouldRenderZoomInput,
  25174. $animation,
  25175. $footerOffset,
  25176. measure_handler_1,
  25177. select_handler,
  25178. div0_binding,
  25179. interactable_function,
  25180. util_root_binding,
  25181. measure_handler
  25182. ];
  25183. }
  25184. class Crop extends SvelteComponent {
  25185. constructor(options) {
  25186. super();
  25187. init(
  25188. this,
  25189. options,
  25190. instance$k,
  25191. create_fragment$k,
  25192. safe_not_equal,
  25193. {
  25194. name: 87,
  25195. isActive: 1,
  25196. stores: 88,
  25197. cropImageSelectionCornerStyle: 2,
  25198. cropWillRenderImageSelectionGuides: 89,
  25199. cropAutoCenterImageSelectionTimeout: 90,
  25200. cropEnableZoomMatchImageAspectRatio: 91,
  25201. cropEnableRotateMatchImageAspectRatio: 92,
  25202. cropEnableRotationInput: 93,
  25203. cropEnableZoom: 3,
  25204. cropEnableZoomInput: 94,
  25205. cropEnableZoomAutoHide: 95,
  25206. cropEnableImageSelection: 96,
  25207. cropEnableInfoIndicator: 97,
  25208. cropEnableZoomTowardsWheelPosition: 98,
  25209. cropEnableLimitWheelInputToCropSelection: 99,
  25210. cropEnableCenterImageSelection: 100,
  25211. cropEnableButtonRotateLeft: 101,
  25212. cropEnableButtonRotateRight: 102,
  25213. cropEnableButtonFlipHorizontal: 103,
  25214. cropEnableButtonFlipVertical: 104,
  25215. cropSelectPresetOptions: 105,
  25216. cropEnableSelectPreset: 106,
  25217. cropEnableButtonToggleCropLimit: 107,
  25218. cropWillRenderTools: 108,
  25219. locale: 4,
  25220. tools: 0
  25221. },
  25222. [-1, -1, -1, -1, -1, -1, -1]
  25223. );
  25224. }
  25225. get name() {
  25226. return this.$$.ctx[87];
  25227. }
  25228. get isActive() {
  25229. return this.$$.ctx[1];
  25230. }
  25231. set isActive(isActive) {
  25232. this.$set({ isActive });
  25233. flush();
  25234. }
  25235. get stores() {
  25236. return this.$$.ctx[88];
  25237. }
  25238. set stores(stores) {
  25239. this.$set({ stores });
  25240. flush();
  25241. }
  25242. get cropImageSelectionCornerStyle() {
  25243. return this.$$.ctx[2];
  25244. }
  25245. set cropImageSelectionCornerStyle(cropImageSelectionCornerStyle) {
  25246. this.$set({ cropImageSelectionCornerStyle });
  25247. flush();
  25248. }
  25249. get cropWillRenderImageSelectionGuides() {
  25250. return this.$$.ctx[89];
  25251. }
  25252. set cropWillRenderImageSelectionGuides(cropWillRenderImageSelectionGuides) {
  25253. this.$set({ cropWillRenderImageSelectionGuides });
  25254. flush();
  25255. }
  25256. get cropAutoCenterImageSelectionTimeout() {
  25257. return this.$$.ctx[90];
  25258. }
  25259. set cropAutoCenterImageSelectionTimeout(cropAutoCenterImageSelectionTimeout) {
  25260. this.$set({ cropAutoCenterImageSelectionTimeout });
  25261. flush();
  25262. }
  25263. get cropEnableZoomMatchImageAspectRatio() {
  25264. return this.$$.ctx[91];
  25265. }
  25266. set cropEnableZoomMatchImageAspectRatio(cropEnableZoomMatchImageAspectRatio) {
  25267. this.$set({ cropEnableZoomMatchImageAspectRatio });
  25268. flush();
  25269. }
  25270. get cropEnableRotateMatchImageAspectRatio() {
  25271. return this.$$.ctx[92];
  25272. }
  25273. set cropEnableRotateMatchImageAspectRatio(cropEnableRotateMatchImageAspectRatio) {
  25274. this.$set({ cropEnableRotateMatchImageAspectRatio });
  25275. flush();
  25276. }
  25277. get cropEnableRotationInput() {
  25278. return this.$$.ctx[93];
  25279. }
  25280. set cropEnableRotationInput(cropEnableRotationInput) {
  25281. this.$set({ cropEnableRotationInput });
  25282. flush();
  25283. }
  25284. get cropEnableZoom() {
  25285. return this.$$.ctx[3];
  25286. }
  25287. set cropEnableZoom(cropEnableZoom) {
  25288. this.$set({ cropEnableZoom });
  25289. flush();
  25290. }
  25291. get cropEnableZoomInput() {
  25292. return this.$$.ctx[94];
  25293. }
  25294. set cropEnableZoomInput(cropEnableZoomInput) {
  25295. this.$set({ cropEnableZoomInput });
  25296. flush();
  25297. }
  25298. get cropEnableZoomAutoHide() {
  25299. return this.$$.ctx[95];
  25300. }
  25301. set cropEnableZoomAutoHide(cropEnableZoomAutoHide) {
  25302. this.$set({ cropEnableZoomAutoHide });
  25303. flush();
  25304. }
  25305. get cropEnableImageSelection() {
  25306. return this.$$.ctx[96];
  25307. }
  25308. set cropEnableImageSelection(cropEnableImageSelection) {
  25309. this.$set({ cropEnableImageSelection });
  25310. flush();
  25311. }
  25312. get cropEnableInfoIndicator() {
  25313. return this.$$.ctx[97];
  25314. }
  25315. set cropEnableInfoIndicator(cropEnableInfoIndicator) {
  25316. this.$set({ cropEnableInfoIndicator });
  25317. flush();
  25318. }
  25319. get cropEnableZoomTowardsWheelPosition() {
  25320. return this.$$.ctx[98];
  25321. }
  25322. set cropEnableZoomTowardsWheelPosition(cropEnableZoomTowardsWheelPosition) {
  25323. this.$set({ cropEnableZoomTowardsWheelPosition });
  25324. flush();
  25325. }
  25326. get cropEnableLimitWheelInputToCropSelection() {
  25327. return this.$$.ctx[99];
  25328. }
  25329. set cropEnableLimitWheelInputToCropSelection(cropEnableLimitWheelInputToCropSelection) {
  25330. this.$set({ cropEnableLimitWheelInputToCropSelection });
  25331. flush();
  25332. }
  25333. get cropEnableCenterImageSelection() {
  25334. return this.$$.ctx[100];
  25335. }
  25336. set cropEnableCenterImageSelection(cropEnableCenterImageSelection) {
  25337. this.$set({ cropEnableCenterImageSelection });
  25338. flush();
  25339. }
  25340. get cropEnableButtonRotateLeft() {
  25341. return this.$$.ctx[101];
  25342. }
  25343. set cropEnableButtonRotateLeft(cropEnableButtonRotateLeft) {
  25344. this.$set({ cropEnableButtonRotateLeft });
  25345. flush();
  25346. }
  25347. get cropEnableButtonRotateRight() {
  25348. return this.$$.ctx[102];
  25349. }
  25350. set cropEnableButtonRotateRight(cropEnableButtonRotateRight) {
  25351. this.$set({ cropEnableButtonRotateRight });
  25352. flush();
  25353. }
  25354. get cropEnableButtonFlipHorizontal() {
  25355. return this.$$.ctx[103];
  25356. }
  25357. set cropEnableButtonFlipHorizontal(cropEnableButtonFlipHorizontal) {
  25358. this.$set({ cropEnableButtonFlipHorizontal });
  25359. flush();
  25360. }
  25361. get cropEnableButtonFlipVertical() {
  25362. return this.$$.ctx[104];
  25363. }
  25364. set cropEnableButtonFlipVertical(cropEnableButtonFlipVertical) {
  25365. this.$set({ cropEnableButtonFlipVertical });
  25366. flush();
  25367. }
  25368. get cropSelectPresetOptions() {
  25369. return this.$$.ctx[105];
  25370. }
  25371. set cropSelectPresetOptions(cropSelectPresetOptions) {
  25372. this.$set({ cropSelectPresetOptions });
  25373. flush();
  25374. }
  25375. get cropEnableSelectPreset() {
  25376. return this.$$.ctx[106];
  25377. }
  25378. set cropEnableSelectPreset(cropEnableSelectPreset) {
  25379. this.$set({ cropEnableSelectPreset });
  25380. flush();
  25381. }
  25382. get cropEnableButtonToggleCropLimit() {
  25383. return this.$$.ctx[107];
  25384. }
  25385. set cropEnableButtonToggleCropLimit(cropEnableButtonToggleCropLimit) {
  25386. this.$set({ cropEnableButtonToggleCropLimit });
  25387. flush();
  25388. }
  25389. get cropWillRenderTools() {
  25390. return this.$$.ctx[108];
  25391. }
  25392. set cropWillRenderTools(cropWillRenderTools) {
  25393. this.$set({ cropWillRenderTools });
  25394. flush();
  25395. }
  25396. get locale() {
  25397. return this.$$.ctx[4];
  25398. }
  25399. set locale(locale) {
  25400. this.$set({ locale });
  25401. flush();
  25402. }
  25403. get tools() {
  25404. return this.$$.ctx[0];
  25405. }
  25406. set tools(tools) {
  25407. this.$set({ tools });
  25408. flush();
  25409. }
  25410. }
  25411. // @ts-ignore
  25412. var _plugin_crop = { util: ['crop', Crop] };
  25413. /* src/core/ui/plugins/filter/index.svelte generated by Svelte v3.37.0 */
  25414. function create_option_slot$2(ctx) {
  25415. let div1;
  25416. let div0;
  25417. let option = /*option*/ ctx[68];
  25418. let t0;
  25419. let span;
  25420. let t1_value = (isFunction(/*option*/ ctx[68].label)
  25421. ? /*option*/ ctx[68].label(/*locale*/ ctx[2])
  25422. : /*option*/ ctx[68].label) + "";
  25423. let t1;
  25424. let mounted;
  25425. let dispose;
  25426. function measure_handler_1(...args) {
  25427. return /*measure_handler_1*/ ctx[48](/*option*/ ctx[68], ...args);
  25428. }
  25429. const assign_div0 = () => /*div0_binding*/ ctx[49](div0, option);
  25430. const unassign_div0 = () => /*div0_binding*/ ctx[49](null, option);
  25431. return {
  25432. c() {
  25433. div1 = element("div");
  25434. div0 = element("div");
  25435. t0 = space();
  25436. span = element("span");
  25437. t1 = text(t1_value);
  25438. attr(div0, "class", FILTER_PREVIEW_CLASS_NAME);
  25439. attr(div1, "slot", "option");
  25440. attr(div1, "class", "PinturaFilterOption");
  25441. },
  25442. m(target, anchor) {
  25443. insert(target, div1, anchor);
  25444. append(div1, div0);
  25445. assign_div0();
  25446. append(div1, t0);
  25447. append(div1, span);
  25448. append(span, t1);
  25449. if (!mounted) {
  25450. dispose = [
  25451. listen(div0, "measure", measure_handler_1),
  25452. action_destroyer(measurable.call(null, div0))
  25453. ];
  25454. mounted = true;
  25455. }
  25456. },
  25457. p(new_ctx, dirty) {
  25458. ctx = new_ctx;
  25459. if (option !== /*option*/ ctx[68]) {
  25460. unassign_div0();
  25461. option = /*option*/ ctx[68];
  25462. assign_div0();
  25463. }
  25464. if (dirty[0] & /*locale*/ 4 | dirty[2] & /*option*/ 64 && t1_value !== (t1_value = (isFunction(/*option*/ ctx[68].label)
  25465. ? /*option*/ ctx[68].label(/*locale*/ ctx[2])
  25466. : /*option*/ ctx[68].label) + "")) set_data(t1, t1_value);
  25467. },
  25468. d(detaching) {
  25469. if (detaching) detach(div1);
  25470. unassign_div0();
  25471. mounted = false;
  25472. run_all(dispose);
  25473. }
  25474. };
  25475. }
  25476. // (357:8) <Scrollable elasticity={elasticityMultiplier * scrollElasticity} onscroll={(offset) => (tileScrollOffset = offset)} bind:maskFeatherStartOpacity={tileLeftOpacity} bind:maskFeatherEndOpacity={tileRightOpacity} bind:maskFeatherSize={tileMargin} on:measure={(e) => (tileScrollContainerRect = e.detail)} >
  25477. function create_default_slot$8(ctx) {
  25478. let radiogroup;
  25479. let current;
  25480. radiogroup = new RadioGroup({
  25481. props: {
  25482. locale: /*locale*/ ctx[2],
  25483. layout: "row",
  25484. options: /*filterOptions*/ ctx[3],
  25485. selectedIndex: /*selectedFilterIndex*/ ctx[10],
  25486. onchange: /*handleChangeFilter*/ ctx[29],
  25487. $$slots: {
  25488. option: [
  25489. create_option_slot$2,
  25490. ({ option }) => ({ 68: option }),
  25491. ({ option }) => [0, 0, option ? 64 : 0]
  25492. ]
  25493. },
  25494. $$scope: { ctx }
  25495. }
  25496. });
  25497. return {
  25498. c() {
  25499. create_component(radiogroup.$$.fragment);
  25500. },
  25501. m(target, anchor) {
  25502. mount_component(radiogroup, target, anchor);
  25503. current = true;
  25504. },
  25505. p(ctx, dirty) {
  25506. const radiogroup_changes = {};
  25507. if (dirty[0] & /*locale*/ 4) radiogroup_changes.locale = /*locale*/ ctx[2];
  25508. if (dirty[0] & /*filterOptions*/ 8) radiogroup_changes.options = /*filterOptions*/ ctx[3];
  25509. if (dirty[0] & /*selectedFilterIndex*/ 1024) radiogroup_changes.selectedIndex = /*selectedFilterIndex*/ ctx[10];
  25510. if (dirty[0] & /*locale, tileElements*/ 516 | dirty[2] & /*$$scope, option*/ 192) {
  25511. radiogroup_changes.$$scope = { dirty, ctx };
  25512. }
  25513. radiogroup.$set(radiogroup_changes);
  25514. },
  25515. i(local) {
  25516. if (current) return;
  25517. transition_in(radiogroup.$$.fragment, local);
  25518. current = true;
  25519. },
  25520. o(local) {
  25521. transition_out(radiogroup.$$.fragment, local);
  25522. current = false;
  25523. },
  25524. d(detaching) {
  25525. destroy_component(radiogroup, detaching);
  25526. }
  25527. };
  25528. }
  25529. // (356:4)
  25530. function create_footer_slot$4(ctx) {
  25531. let div;
  25532. let scrollable;
  25533. let updating_maskFeatherStartOpacity;
  25534. let updating_maskFeatherEndOpacity;
  25535. let updating_maskFeatherSize;
  25536. let current;
  25537. let mounted;
  25538. let dispose;
  25539. function scrollable_maskFeatherStartOpacity_binding(value) {
  25540. /*scrollable_maskFeatherStartOpacity_binding*/ ctx[51](value);
  25541. }
  25542. function scrollable_maskFeatherEndOpacity_binding(value) {
  25543. /*scrollable_maskFeatherEndOpacity_binding*/ ctx[52](value);
  25544. }
  25545. function scrollable_maskFeatherSize_binding(value) {
  25546. /*scrollable_maskFeatherSize_binding*/ ctx[53](value);
  25547. }
  25548. let scrollable_props = {
  25549. elasticity: /*elasticityMultiplier*/ ctx[15] * /*scrollElasticity*/ ctx[16],
  25550. onscroll: /*func*/ ctx[50],
  25551. $$slots: { default: [create_default_slot$8] },
  25552. $$scope: { ctx }
  25553. };
  25554. if (/*tileLeftOpacity*/ ctx[4] !== void 0) {
  25555. scrollable_props.maskFeatherStartOpacity = /*tileLeftOpacity*/ ctx[4];
  25556. }
  25557. if (/*tileRightOpacity*/ ctx[5] !== void 0) {
  25558. scrollable_props.maskFeatherEndOpacity = /*tileRightOpacity*/ ctx[5];
  25559. }
  25560. if (/*tileMargin*/ ctx[6] !== void 0) {
  25561. scrollable_props.maskFeatherSize = /*tileMargin*/ ctx[6];
  25562. }
  25563. scrollable = new Scrollable({ props: scrollable_props });
  25564. binding_callbacks.push(() => bind(scrollable, "maskFeatherStartOpacity", scrollable_maskFeatherStartOpacity_binding));
  25565. binding_callbacks.push(() => bind(scrollable, "maskFeatherEndOpacity", scrollable_maskFeatherEndOpacity_binding));
  25566. binding_callbacks.push(() => bind(scrollable, "maskFeatherSize", scrollable_maskFeatherSize_binding));
  25567. scrollable.$on("measure", /*measure_handler_2*/ ctx[54]);
  25568. return {
  25569. c() {
  25570. div = element("div");
  25571. create_component(scrollable.$$.fragment);
  25572. attr(div, "slot", "footer");
  25573. attr(div, "style", /*footerStyle*/ ctx[11]);
  25574. },
  25575. m(target, anchor) {
  25576. insert(target, div, anchor);
  25577. mount_component(scrollable, div, null);
  25578. current = true;
  25579. if (!mounted) {
  25580. dispose = listen(div, "transitionend", /*handleTransitionEnd*/ ctx[27]);
  25581. mounted = true;
  25582. }
  25583. },
  25584. p(ctx, dirty) {
  25585. const scrollable_changes = {};
  25586. if (dirty[0] & /*tileScrollOffset*/ 128) scrollable_changes.onscroll = /*func*/ ctx[50];
  25587. if (dirty[0] & /*locale, filterOptions, selectedFilterIndex, tileElements*/ 1548 | dirty[2] & /*$$scope*/ 128) {
  25588. scrollable_changes.$$scope = { dirty, ctx };
  25589. }
  25590. if (!updating_maskFeatherStartOpacity && dirty[0] & /*tileLeftOpacity*/ 16) {
  25591. updating_maskFeatherStartOpacity = true;
  25592. scrollable_changes.maskFeatherStartOpacity = /*tileLeftOpacity*/ ctx[4];
  25593. add_flush_callback(() => updating_maskFeatherStartOpacity = false);
  25594. }
  25595. if (!updating_maskFeatherEndOpacity && dirty[0] & /*tileRightOpacity*/ 32) {
  25596. updating_maskFeatherEndOpacity = true;
  25597. scrollable_changes.maskFeatherEndOpacity = /*tileRightOpacity*/ ctx[5];
  25598. add_flush_callback(() => updating_maskFeatherEndOpacity = false);
  25599. }
  25600. if (!updating_maskFeatherSize && dirty[0] & /*tileMargin*/ 64) {
  25601. updating_maskFeatherSize = true;
  25602. scrollable_changes.maskFeatherSize = /*tileMargin*/ ctx[6];
  25603. add_flush_callback(() => updating_maskFeatherSize = false);
  25604. }
  25605. scrollable.$set(scrollable_changes);
  25606. if (!current || dirty[0] & /*footerStyle*/ 2048) {
  25607. attr(div, "style", /*footerStyle*/ ctx[11]);
  25608. }
  25609. },
  25610. i(local) {
  25611. if (current) return;
  25612. transition_in(scrollable.$$.fragment, local);
  25613. current = true;
  25614. },
  25615. o(local) {
  25616. transition_out(scrollable.$$.fragment, local);
  25617. current = false;
  25618. },
  25619. d(detaching) {
  25620. if (detaching) detach(div);
  25621. destroy_component(scrollable);
  25622. mounted = false;
  25623. dispose();
  25624. }
  25625. };
  25626. }
  25627. function create_fragment$j(ctx) {
  25628. let util;
  25629. let current;
  25630. util = new Util({
  25631. props: {
  25632. $$slots: { footer: [create_footer_slot$4] },
  25633. $$scope: { ctx }
  25634. }
  25635. });
  25636. util.$on("measure", /*measure_handler*/ ctx[55]);
  25637. return {
  25638. c() {
  25639. create_component(util.$$.fragment);
  25640. },
  25641. m(target, anchor) {
  25642. mount_component(util, target, anchor);
  25643. current = true;
  25644. },
  25645. p(ctx, dirty) {
  25646. const util_changes = {};
  25647. if (dirty[0] & /*footerStyle, tileScrollOffset, tileLeftOpacity, tileRightOpacity, tileMargin, tileScrollContainerRect, locale, filterOptions, selectedFilterIndex, tileElements*/ 4092 | dirty[2] & /*$$scope*/ 128) {
  25648. util_changes.$$scope = { dirty, ctx };
  25649. }
  25650. util.$set(util_changes);
  25651. },
  25652. i(local) {
  25653. if (current) return;
  25654. transition_in(util.$$.fragment, local);
  25655. current = true;
  25656. },
  25657. o(local) {
  25658. transition_out(util.$$.fragment, local);
  25659. current = false;
  25660. },
  25661. d(detaching) {
  25662. destroy_component(util, detaching);
  25663. }
  25664. };
  25665. }
  25666. let FILTER_PREVIEW_CLASS_NAME = "PinturaFilterPreview";
  25667. function instance$j($$self, $$props, $$invalidate) {
  25668. let filterOptionsFlattened;
  25669. let selectedFilterIndex;
  25670. let footerStyle;
  25671. let $imageColorMatrix;
  25672. let $tileRects;
  25673. let $canvasSize;
  25674. let $imageTransforms;
  25675. let $animation;
  25676. let $isActive,
  25677. $$unsubscribe_isActive = noop,
  25678. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(40, $isActive = $$value)), isActive);
  25679. let $utilRect;
  25680. let $stageRect;
  25681. let $imageGamma;
  25682. let $imagePreview;
  25683. let $imageSize;
  25684. let $imageBackgroundColor;
  25685. let $isActiveFraction,
  25686. $$unsubscribe_isActiveFraction = noop,
  25687. $$subscribe_isActiveFraction = () => ($$unsubscribe_isActiveFraction(), $$unsubscribe_isActiveFraction = subscribe(isActiveFraction, $$value => $$invalidate(45, $isActiveFraction = $$value)), isActiveFraction);
  25688. let $footerOffset;
  25689. let $imageTiles;
  25690. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  25691. $$self.$$.on_destroy.push(() => $$unsubscribe_isActiveFraction());
  25692. const name = "filter";
  25693. let { isActive } = $$props;
  25694. $$subscribe_isActive();
  25695. let { isActiveFraction } = $$props;
  25696. $$subscribe_isActiveFraction();
  25697. let { stores } = $$props;
  25698. let { locale } = $$props;
  25699. let { filterFunctions } = $$props;
  25700. let { filterOptions } = $$props;
  25701. // connect filter choice to stores
  25702. const { history, interfaceImages, stageRect, utilRect, animation, elasticityMultiplier, scrollElasticity, imageSize, imagePreview, imageCropRect, imageRotation, imageFlipX, imageFlipY, imageBackgroundColor, imageGamma, imageColorMatrix } = stores;
  25703. component_subscribe($$self, stageRect, value => $$invalidate(42, $stageRect = value));
  25704. component_subscribe($$self, utilRect, value => $$invalidate(41, $utilRect = value));
  25705. component_subscribe($$self, animation, value => $$invalidate(39, $animation = value));
  25706. component_subscribe($$self, imageSize, value => $$invalidate(57, $imageSize = value));
  25707. component_subscribe($$self, imagePreview, value => $$invalidate(44, $imagePreview = value));
  25708. component_subscribe($$self, imageBackgroundColor, value => $$invalidate(58, $imageBackgroundColor = value));
  25709. component_subscribe($$self, imageGamma, value => $$invalidate(43, $imageGamma = value));
  25710. component_subscribe($$self, imageColorMatrix, value => $$invalidate(36, $imageColorMatrix = value));
  25711. const getFilterIndex = (imageColorMatrix, filterOptionsFlattened) => {
  25712. if (!imageColorMatrix || !imageColorMatrix["filter"] || !filterOptionsFlattened) return 0;
  25713. const filterColorMatrix = imageColorMatrix["filter"];
  25714. return filterOptionsFlattened.// get id and compare matrices
  25715. findIndex(([id]) => {
  25716. if (!filterFunctions[id]) return false;
  25717. const matrix = filterFunctions[id]();
  25718. return arrayEqual(matrix, filterColorMatrix);
  25719. });
  25720. };
  25721. const tileRects = writable({});
  25722. component_subscribe($$self, tileRects, value => $$invalidate(37, $tileRects = value));
  25723. const handleTileResize = (item, rect) => set_store_value(tileRects, $tileRects[item.value] = rect, $tileRects);
  25724. const canvasSize = derived(tileRects, $tileRects => {
  25725. if (!$tileRects[undefined]) return;
  25726. const tileRectFirst = $tileRects[undefined];
  25727. if ($canvasSize && sizeEqual($canvasSize, tileRectFirst)) return $canvasSize;
  25728. return sizeClone(tileRectFirst);
  25729. });
  25730. component_subscribe($$self, canvasSize, value => $$invalidate(56, $canvasSize = value));
  25731. const imageTransforms = derived(
  25732. [
  25733. isActive,
  25734. canvasSize,
  25735. imageCropRect,
  25736. imageSize,
  25737. imageRotation,
  25738. imageFlipX,
  25739. imageFlipY
  25740. ],
  25741. ([
  25742. $isActive,
  25743. $canvasSize,
  25744. $imageCropRect,
  25745. $imageSize,
  25746. $imageRotation,
  25747. $imageFlipX,
  25748. $imageFlipY
  25749. ], set) => {
  25750. if (!$isActive || !$canvasSize || !$imageSize) return $imageTransforms;
  25751. const imageRect = rectCreateFromSize($imageSize);
  25752. const imageCenter = rectCenter(imageRect);
  25753. // get base crop rect so we can correctly apply transforms
  25754. const cropRectBase = getBaseCropRect($imageSize, $imageCropRect, $imageRotation);
  25755. const cropRectBaseCenter = rectCenter(cropRectBase);
  25756. const imageTranslation = vectorSubtract(vectorClone(imageCenter), cropRectBaseCenter);
  25757. const imageOrigin = vectorInvert(vectorClone(imageTranslation));
  25758. // scalar
  25759. const imageScalar = Math.max($canvasSize.width / $imageCropRect.width, $canvasSize.height / $imageCropRect.height);
  25760. // update preview transforms
  25761. set({
  25762. origin: imageOrigin,
  25763. translation: imageTranslation,
  25764. rotation: {
  25765. x: $imageFlipY ? Math.PI : 0,
  25766. y: $imageFlipX ? Math.PI : 0,
  25767. z: $imageRotation
  25768. },
  25769. perspective: vectorCreateEmpty(),
  25770. scale: imageScalar
  25771. });
  25772. }
  25773. );
  25774. component_subscribe($$self, imageTransforms, value => $$invalidate(38, $imageTransforms = value));
  25775. const cloneImageTransforms = imageTransforms => ({
  25776. origin: vectorClone(imageTransforms.origin),
  25777. translation: vectorClone(imageTransforms.translation),
  25778. rotation: { ...imageTransforms.rotation },
  25779. perspective: vectorClone(imageTransforms.perspective),
  25780. scale: imageTransforms.scale
  25781. });
  25782. //
  25783. // Footer
  25784. //
  25785. const footerOffset = spring($animation ? 20 : 0);
  25786. component_subscribe($$self, footerOffset, value => $$invalidate(46, $footerOffset = value));
  25787. let tileCornerRadius;
  25788. const tileElements = {};
  25789. const handleTransitionEnd = e => {
  25790. if (e.target.className !== FILTER_PREVIEW_CLASS_NAME) return;
  25791. $$invalidate(33, tileCornerRadius = Object.keys(tileElements).reduce(
  25792. (prev, curr) => {
  25793. const element = tileElements[curr];
  25794. const style = getComputedStyle(element);
  25795. const corners = ["top-left", "top-right", "bottom-left", "bottom-right"].map(corner => style.getPropertyValue(`border-${corner}-radius`)).map(unitToPixels).// this better aligns WebGL rounded corner with css rounded corner
  25796. map(v => v * 1.25);
  25797. prev[curr] = corners;
  25798. return prev;
  25799. },
  25800. {}
  25801. ));
  25802. };
  25803. let tileLeftOpacity; // set by Scrollable
  25804. let tileRightOpacity; // set by Scrollable
  25805. let tileMargin; // set by Scrollable
  25806. let tileScrollOffset = { x: 0, y: 0 };
  25807. let tileScrollContainerRect;
  25808. let tileWrapperOffset;
  25809. const imageTiles = writable([]);
  25810. component_subscribe($$self, imageTiles, value => $$invalidate(47, $imageTiles = value));
  25811. // clones an image tile for use in canvas
  25812. const cloneImageTile = tile => {
  25813. const clone = {
  25814. // doesn't clone everything but should be enough
  25815. ...tile,
  25816. data: $imagePreview,
  25817. size: $imageSize,
  25818. offset: { ...tile.offset },
  25819. mask: { ...tile.mask },
  25820. backgroundColor: $imageBackgroundColor
  25821. };
  25822. clone.opacity = $isActiveFraction;
  25823. clone.offset.y += $footerOffset;
  25824. clone.mask.y += $footerOffset;
  25825. return clone;
  25826. };
  25827. const handleChangeFilter = ({ value }) => {
  25828. set_store_value(
  25829. imageColorMatrix,
  25830. $imageColorMatrix = {
  25831. ...$imageColorMatrix,
  25832. filter: isFunction(filterFunctions[value])
  25833. ? filterFunctions[value]()
  25834. : undefined
  25835. },
  25836. $imageColorMatrix
  25837. );
  25838. history.write();
  25839. };
  25840. // when destroyed we need to make sure all image previews are cleared
  25841. onDestroy(() => {
  25842. interfaceImages.set([]);
  25843. });
  25844. const measure_handler_1 = (option, e) => handleTileResize(option, e.detail);
  25845. function div0_binding($$value, option) {
  25846. binding_callbacks[$$value ? "unshift" : "push"](() => {
  25847. tileElements[option.value] = $$value;
  25848. $$invalidate(9, tileElements);
  25849. });
  25850. }
  25851. const func = offset => $$invalidate(7, tileScrollOffset = offset);
  25852. function scrollable_maskFeatherStartOpacity_binding(value) {
  25853. tileLeftOpacity = value;
  25854. $$invalidate(4, tileLeftOpacity);
  25855. }
  25856. function scrollable_maskFeatherEndOpacity_binding(value) {
  25857. tileRightOpacity = value;
  25858. $$invalidate(5, tileRightOpacity);
  25859. }
  25860. function scrollable_maskFeatherSize_binding(value) {
  25861. tileMargin = value;
  25862. $$invalidate(6, tileMargin);
  25863. }
  25864. const measure_handler_2 = e => $$invalidate(8, tileScrollContainerRect = e.detail);
  25865. function measure_handler(event) {
  25866. bubble($$self, event);
  25867. }
  25868. $$self.$$set = $$props => {
  25869. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(0, isActive = $$props.isActive));
  25870. if ("isActiveFraction" in $$props) $$subscribe_isActiveFraction($$invalidate(1, isActiveFraction = $$props.isActiveFraction));
  25871. if ("stores" in $$props) $$invalidate(31, stores = $$props.stores);
  25872. if ("locale" in $$props) $$invalidate(2, locale = $$props.locale);
  25873. if ("filterFunctions" in $$props) $$invalidate(32, filterFunctions = $$props.filterFunctions);
  25874. if ("filterOptions" in $$props) $$invalidate(3, filterOptions = $$props.filterOptions);
  25875. };
  25876. $$self.$$.update = () => {
  25877. if ($$self.$$.dirty[0] & /*filterOptions*/ 8) {
  25878. $$invalidate(35, filterOptionsFlattened = flattenOptions(filterOptions));
  25879. }
  25880. if ($$self.$$.dirty[1] & /*$imageColorMatrix, filterOptionsFlattened*/ 48) {
  25881. $$invalidate(10, selectedFilterIndex = getFilterIndex($imageColorMatrix, filterOptionsFlattened));
  25882. }
  25883. if ($$self.$$.dirty[1] & /*$animation, $isActive*/ 768) {
  25884. $animation && footerOffset.set($isActive ? 0 : 20);
  25885. }
  25886. if ($$self.$$.dirty[1] & /*$isActive, $utilRect, $stageRect*/ 3584) {
  25887. if ($isActive && $utilRect && $stageRect) {
  25888. const tileTopOffset = $stageRect.y + $stageRect.height + $utilRect.y;
  25889. $$invalidate(34, tileWrapperOffset = {
  25890. x: $stageRect.x - $utilRect.x,
  25891. y: tileTopOffset
  25892. });
  25893. }
  25894. }
  25895. if ($$self.$$.dirty[0] & /*tileScrollOffset, tileScrollContainerRect, tileMargin, tileLeftOpacity, tileRightOpacity*/ 496 | $$self.$$.dirty[1] & /*$imageTransforms, tileWrapperOffset, tileCornerRadius, filterOptionsFlattened, $tileRects, $imageColorMatrix, filterFunctions, $imageGamma*/ 4350) {
  25896. if ($imageTransforms && tileWrapperOffset && tileScrollOffset && tileScrollContainerRect && tileCornerRadius) {
  25897. const boundsX = tileWrapperOffset.x + tileScrollContainerRect.x;
  25898. const offsetX = boundsX + tileScrollOffset.x;
  25899. const offsetY = tileWrapperOffset.y;
  25900. const containerLeft = tileScrollContainerRect.x + tileWrapperOffset.x;
  25901. const containerRight = containerLeft + tileScrollContainerRect.width;
  25902. imageTiles.set(filterOptionsFlattened.map(([id], i) => {
  25903. const tileRect = $tileRects[id];
  25904. // test if is outside of view
  25905. const tileLeft = tileScrollOffset.x + tileRect.x;
  25906. const tileRight = tileLeft + tileRect.width;
  25907. if (tileRight < 0 || tileLeft > tileScrollContainerRect.width) return false;
  25908. const x = offsetX + tileRect.x;
  25909. const y = offsetY + tileRect.y;
  25910. const preview = cloneImageTransforms($imageTransforms);
  25911. preview.offset = vectorCreate(tileRect.width * 0.5 + x, tileRect.height * 0.5 + y);
  25912. let clipX = 0;
  25913. let clipWidth = 0;
  25914. preview.maskOpacity = 1;
  25915. preview.mask = rectCreate(x + clipX, y, tileRect.width + clipWidth, tileRect.height);
  25916. preview.maskFeather = [1, 0, 1, 0, 1, containerRight, 1, containerRight];
  25917. if (tileLeft < tileMargin && tileLeftOpacity < 1) {
  25918. preview.maskFeather[0] = tileLeftOpacity;
  25919. preview.maskFeather[1] = containerLeft;
  25920. preview.maskFeather[2] = 1;
  25921. preview.maskFeather[3] = containerLeft + tileMargin;
  25922. }
  25923. if (tileRight > tileScrollContainerRect.width - tileMargin && tileRightOpacity < 1) {
  25924. preview.maskFeather[4] = tileRightOpacity;
  25925. preview.maskFeather[5] = containerRight - tileMargin;
  25926. preview.maskFeather[6] = 1;
  25927. preview.maskFeather[7] = containerRight;
  25928. }
  25929. preview.maskCornerRadius = tileCornerRadius[id];
  25930. let colorMatrices = $imageColorMatrix && Object.keys($imageColorMatrix).filter(name => name != "filter").map(name => $imageColorMatrix[name]) || [];
  25931. if (isFunction(filterFunctions[id])) {
  25932. colorMatrices.push(filterFunctions[id]());
  25933. }
  25934. preview.colorMatrix = colorMatrices.length
  25935. ? getColorMatrixFromColorMatrices(colorMatrices)
  25936. : undefined;
  25937. preview.gamma = $imageGamma;
  25938. return preview;
  25939. }).filter(Boolean));
  25940. }
  25941. }
  25942. if ($$self.$$.dirty[1] & /*$isActiveFraction, $imageTiles, $footerOffset, $imagePreview*/ 122880) {
  25943. // Will update `interfaceImages` store when
  25944. // - $isActiveFraction is updated
  25945. // - $imageTiles is updated
  25946. // - $footerOffset is updated
  25947. if ($isActiveFraction > 0 && $imageTiles) {
  25948. // clone tiles
  25949. interfaceImages.set($imageTiles.map(cloneImageTile));
  25950. } else {
  25951. interfaceImages.set([]);
  25952. }
  25953. }
  25954. if ($$self.$$.dirty[1] & /*$footerOffset*/ 32768) {
  25955. $$invalidate(11, footerStyle = $footerOffset
  25956. ? `transform: translateY(${$footerOffset}px)`
  25957. : undefined);
  25958. }
  25959. };
  25960. return [
  25961. isActive,
  25962. isActiveFraction,
  25963. locale,
  25964. filterOptions,
  25965. tileLeftOpacity,
  25966. tileRightOpacity,
  25967. tileMargin,
  25968. tileScrollOffset,
  25969. tileScrollContainerRect,
  25970. tileElements,
  25971. selectedFilterIndex,
  25972. footerStyle,
  25973. stageRect,
  25974. utilRect,
  25975. animation,
  25976. elasticityMultiplier,
  25977. scrollElasticity,
  25978. imageSize,
  25979. imagePreview,
  25980. imageBackgroundColor,
  25981. imageGamma,
  25982. imageColorMatrix,
  25983. tileRects,
  25984. handleTileResize,
  25985. canvasSize,
  25986. imageTransforms,
  25987. footerOffset,
  25988. handleTransitionEnd,
  25989. imageTiles,
  25990. handleChangeFilter,
  25991. name,
  25992. stores,
  25993. filterFunctions,
  25994. tileCornerRadius,
  25995. tileWrapperOffset,
  25996. filterOptionsFlattened,
  25997. $imageColorMatrix,
  25998. $tileRects,
  25999. $imageTransforms,
  26000. $animation,
  26001. $isActive,
  26002. $utilRect,
  26003. $stageRect,
  26004. $imageGamma,
  26005. $imagePreview,
  26006. $isActiveFraction,
  26007. $footerOffset,
  26008. $imageTiles,
  26009. measure_handler_1,
  26010. div0_binding,
  26011. func,
  26012. scrollable_maskFeatherStartOpacity_binding,
  26013. scrollable_maskFeatherEndOpacity_binding,
  26014. scrollable_maskFeatherSize_binding,
  26015. measure_handler_2,
  26016. measure_handler
  26017. ];
  26018. }
  26019. class Filter extends SvelteComponent {
  26020. constructor(options) {
  26021. super();
  26022. init(
  26023. this,
  26024. options,
  26025. instance$j,
  26026. create_fragment$j,
  26027. safe_not_equal,
  26028. {
  26029. name: 30,
  26030. isActive: 0,
  26031. isActiveFraction: 1,
  26032. stores: 31,
  26033. locale: 2,
  26034. filterFunctions: 32,
  26035. filterOptions: 3
  26036. },
  26037. [-1, -1, -1]
  26038. );
  26039. }
  26040. get name() {
  26041. return this.$$.ctx[30];
  26042. }
  26043. get isActive() {
  26044. return this.$$.ctx[0];
  26045. }
  26046. set isActive(isActive) {
  26047. this.$set({ isActive });
  26048. flush();
  26049. }
  26050. get isActiveFraction() {
  26051. return this.$$.ctx[1];
  26052. }
  26053. set isActiveFraction(isActiveFraction) {
  26054. this.$set({ isActiveFraction });
  26055. flush();
  26056. }
  26057. get stores() {
  26058. return this.$$.ctx[31];
  26059. }
  26060. set stores(stores) {
  26061. this.$set({ stores });
  26062. flush();
  26063. }
  26064. get locale() {
  26065. return this.$$.ctx[2];
  26066. }
  26067. set locale(locale) {
  26068. this.$set({ locale });
  26069. flush();
  26070. }
  26071. get filterFunctions() {
  26072. return this.$$.ctx[32];
  26073. }
  26074. set filterFunctions(filterFunctions) {
  26075. this.$set({ filterFunctions });
  26076. flush();
  26077. }
  26078. get filterOptions() {
  26079. return this.$$.ctx[3];
  26080. }
  26081. set filterOptions(filterOptions) {
  26082. this.$set({ filterOptions });
  26083. flush();
  26084. }
  26085. }
  26086. // @ts-ignore
  26087. var _plugin_filter = { util: ['filter', Filter] };
  26088. /* src/core/ui/plugins/finetune/index.svelte generated by Svelte v3.37.0 */
  26089. function create_default_slot_2$1(ctx) {
  26090. let span;
  26091. let t_value = /*tab*/ ctx[37].label + "";
  26092. let t;
  26093. return {
  26094. c() {
  26095. span = element("span");
  26096. t = text(t_value);
  26097. },
  26098. m(target, anchor) {
  26099. insert(target, span, anchor);
  26100. append(span, t);
  26101. },
  26102. p(ctx, dirty) {
  26103. if (dirty[1] & /*tab*/ 64 && t_value !== (t_value = /*tab*/ ctx[37].label + "")) set_data(t, t_value);
  26104. },
  26105. d(detaching) {
  26106. if (detaching) detach(span);
  26107. }
  26108. };
  26109. }
  26110. // (145:8) <Scrollable elasticity={elasticityMultiplier * scrollElasticity} class="PinturaControlListScroller" >
  26111. function create_default_slot_1$2(ctx) {
  26112. let tablist;
  26113. let current;
  26114. const tablist_spread_levels = [
  26115. { class: "PinturaControlList" },
  26116. { tabs: /*tabs*/ ctx[1] },
  26117. /*tabsConfig*/ ctx[3]
  26118. ];
  26119. let tablist_props = {
  26120. $$slots: {
  26121. default: [
  26122. create_default_slot_2$1,
  26123. ({ tab }) => ({ 37: tab }),
  26124. ({ tab }) => [0, tab ? 64 : 0]
  26125. ]
  26126. },
  26127. $$scope: { ctx }
  26128. };
  26129. for (let i = 0; i < tablist_spread_levels.length; i += 1) {
  26130. tablist_props = assign(tablist_props, tablist_spread_levels[i]);
  26131. }
  26132. tablist = new TabList({ props: tablist_props });
  26133. tablist.$on("select", /*select_handler*/ ctx[22]);
  26134. return {
  26135. c() {
  26136. create_component(tablist.$$.fragment);
  26137. },
  26138. m(target, anchor) {
  26139. mount_component(tablist, target, anchor);
  26140. current = true;
  26141. },
  26142. p(ctx, dirty) {
  26143. const tablist_changes = (dirty[0] & /*tabs, tabsConfig*/ 10)
  26144. ? get_spread_update(tablist_spread_levels, [
  26145. tablist_spread_levels[0],
  26146. dirty[0] & /*tabs*/ 2 && { tabs: /*tabs*/ ctx[1] },
  26147. dirty[0] & /*tabsConfig*/ 8 && get_spread_object(/*tabsConfig*/ ctx[3])
  26148. ])
  26149. : {};
  26150. if (dirty[1] & /*$$scope, tab*/ 192) {
  26151. tablist_changes.$$scope = { dirty, ctx };
  26152. }
  26153. tablist.$set(tablist_changes);
  26154. },
  26155. i(local) {
  26156. if (current) return;
  26157. transition_in(tablist.$$.fragment, local);
  26158. current = true;
  26159. },
  26160. o(local) {
  26161. transition_out(tablist.$$.fragment, local);
  26162. current = false;
  26163. },
  26164. d(detaching) {
  26165. destroy_component(tablist, detaching);
  26166. }
  26167. };
  26168. }
  26169. // (160:8) <TabPanels class="PinturaControlPanels" panelClass="PinturaControlPanel" {panels} {...tabsConfig} let:panel >
  26170. function create_default_slot$7(ctx) {
  26171. let rangeinput;
  26172. let current;
  26173. const rangeinput_spread_levels = [/*$rangeInputConfig*/ ctx[5][/*panel*/ ctx[36]]];
  26174. let rangeinput_props = {};
  26175. for (let i = 0; i < rangeinput_spread_levels.length; i += 1) {
  26176. rangeinput_props = assign(rangeinput_props, rangeinput_spread_levels[i]);
  26177. }
  26178. rangeinput = new RangeInput({ props: rangeinput_props });
  26179. return {
  26180. c() {
  26181. create_component(rangeinput.$$.fragment);
  26182. },
  26183. m(target, anchor) {
  26184. mount_component(rangeinput, target, anchor);
  26185. current = true;
  26186. },
  26187. p(ctx, dirty) {
  26188. const rangeinput_changes = (dirty[0] & /*$rangeInputConfig*/ 32 | dirty[1] & /*panel*/ 32)
  26189. ? get_spread_update(rangeinput_spread_levels, [get_spread_object(/*$rangeInputConfig*/ ctx[5][/*panel*/ ctx[36]])])
  26190. : {};
  26191. rangeinput.$set(rangeinput_changes);
  26192. },
  26193. i(local) {
  26194. if (current) return;
  26195. transition_in(rangeinput.$$.fragment, local);
  26196. current = true;
  26197. },
  26198. o(local) {
  26199. transition_out(rangeinput.$$.fragment, local);
  26200. current = false;
  26201. },
  26202. d(detaching) {
  26203. destroy_component(rangeinput, detaching);
  26204. }
  26205. };
  26206. }
  26207. // (144:4)
  26208. function create_footer_slot$3(ctx) {
  26209. let div;
  26210. let scrollable;
  26211. let t;
  26212. let tabpanels;
  26213. let current;
  26214. scrollable = new Scrollable({
  26215. props: {
  26216. elasticity: /*elasticityMultiplier*/ ctx[9] * /*scrollElasticity*/ ctx[8],
  26217. class: "PinturaControlListScroller",
  26218. $$slots: { default: [create_default_slot_1$2] },
  26219. $$scope: { ctx }
  26220. }
  26221. });
  26222. const tabpanels_spread_levels = [
  26223. { class: "PinturaControlPanels" },
  26224. { panelClass: "PinturaControlPanel" },
  26225. { panels: /*panels*/ ctx[4] },
  26226. /*tabsConfig*/ ctx[3]
  26227. ];
  26228. let tabpanels_props = {
  26229. $$slots: {
  26230. default: [
  26231. create_default_slot$7,
  26232. ({ panel }) => ({ 36: panel }),
  26233. ({ panel }) => [0, panel ? 32 : 0]
  26234. ]
  26235. },
  26236. $$scope: { ctx }
  26237. };
  26238. for (let i = 0; i < tabpanels_spread_levels.length; i += 1) {
  26239. tabpanels_props = assign(tabpanels_props, tabpanels_spread_levels[i]);
  26240. }
  26241. tabpanels = new TabPanels({ props: tabpanels_props });
  26242. return {
  26243. c() {
  26244. div = element("div");
  26245. create_component(scrollable.$$.fragment);
  26246. t = space();
  26247. create_component(tabpanels.$$.fragment);
  26248. attr(div, "slot", "footer");
  26249. attr(div, "style", /*footerStyle*/ ctx[6]);
  26250. },
  26251. m(target, anchor) {
  26252. insert(target, div, anchor);
  26253. mount_component(scrollable, div, null);
  26254. append(div, t);
  26255. mount_component(tabpanels, div, null);
  26256. current = true;
  26257. },
  26258. p(ctx, dirty) {
  26259. const scrollable_changes = {};
  26260. if (dirty[0] & /*tabs, tabsConfig, tabSelected*/ 14 | dirty[1] & /*$$scope*/ 128) {
  26261. scrollable_changes.$$scope = { dirty, ctx };
  26262. }
  26263. scrollable.$set(scrollable_changes);
  26264. const tabpanels_changes = (dirty[0] & /*panels, tabsConfig*/ 24)
  26265. ? get_spread_update(tabpanels_spread_levels, [
  26266. tabpanels_spread_levels[0],
  26267. tabpanels_spread_levels[1],
  26268. dirty[0] & /*panels*/ 16 && { panels: /*panels*/ ctx[4] },
  26269. dirty[0] & /*tabsConfig*/ 8 && get_spread_object(/*tabsConfig*/ ctx[3])
  26270. ])
  26271. : {};
  26272. if (dirty[0] & /*$rangeInputConfig*/ 32 | dirty[1] & /*$$scope, panel*/ 160) {
  26273. tabpanels_changes.$$scope = { dirty, ctx };
  26274. }
  26275. tabpanels.$set(tabpanels_changes);
  26276. if (!current || dirty[0] & /*footerStyle*/ 64) {
  26277. attr(div, "style", /*footerStyle*/ ctx[6]);
  26278. }
  26279. },
  26280. i(local) {
  26281. if (current) return;
  26282. transition_in(scrollable.$$.fragment, local);
  26283. transition_in(tabpanels.$$.fragment, local);
  26284. current = true;
  26285. },
  26286. o(local) {
  26287. transition_out(scrollable.$$.fragment, local);
  26288. transition_out(tabpanels.$$.fragment, local);
  26289. current = false;
  26290. },
  26291. d(detaching) {
  26292. if (detaching) detach(div);
  26293. destroy_component(scrollable);
  26294. destroy_component(tabpanels);
  26295. }
  26296. };
  26297. }
  26298. function create_fragment$i(ctx) {
  26299. let util;
  26300. let current;
  26301. util = new Util({
  26302. props: {
  26303. $$slots: { footer: [create_footer_slot$3] },
  26304. $$scope: { ctx }
  26305. }
  26306. });
  26307. util.$on("measure", /*measure_handler*/ ctx[23]);
  26308. return {
  26309. c() {
  26310. create_component(util.$$.fragment);
  26311. },
  26312. m(target, anchor) {
  26313. mount_component(util, target, anchor);
  26314. current = true;
  26315. },
  26316. p(ctx, dirty) {
  26317. const util_changes = {};
  26318. if (dirty[0] & /*footerStyle, panels, tabsConfig, $rangeInputConfig, tabs, tabSelected*/ 126 | dirty[1] & /*$$scope*/ 128) {
  26319. util_changes.$$scope = { dirty, ctx };
  26320. }
  26321. util.$set(util_changes);
  26322. },
  26323. i(local) {
  26324. if (current) return;
  26325. transition_in(util.$$.fragment, local);
  26326. current = true;
  26327. },
  26328. o(local) {
  26329. transition_out(util.$$.fragment, local);
  26330. current = false;
  26331. },
  26332. d(detaching) {
  26333. destroy_component(util, detaching);
  26334. }
  26335. };
  26336. }
  26337. function instance$i($$self, $$props, $$invalidate) {
  26338. let tabs;
  26339. let tabSelected;
  26340. let tabsConfig;
  26341. let panels;
  26342. let footerStyle;
  26343. let $rangeInputConfig;
  26344. let $panelValues;
  26345. let $animation;
  26346. let $isActive,
  26347. $$unsubscribe_isActive = noop,
  26348. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(20, $isActive = $$value)), isActive);
  26349. let $footerOffset;
  26350. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  26351. const name = "finetune";
  26352. let { stores } = $$props;
  26353. let { isActive } = $$props;
  26354. $$subscribe_isActive();
  26355. let { locale = {} } = $$props;
  26356. let { finetuneControlConfiguration } = $$props;
  26357. let { finetuneOptions } = $$props;
  26358. const { history, animation, scrollElasticity, elasticityMultiplier, rangeInputElasticity, imageColorMatrix, imageConvolutionMatrix, imageGamma, imageVignette, imageNoise } = stores;
  26359. component_subscribe($$self, animation, value => $$invalidate(19, $animation = value));
  26360. const imageEffectStores = {
  26361. imageColorMatrix,
  26362. imageConvolutionMatrix,
  26363. imageGamma,
  26364. imageVignette,
  26365. imageNoise
  26366. };
  26367. //
  26368. // Tabs
  26369. //
  26370. const uid = `finetune-${getUniqueId()}`;
  26371. //
  26372. // Range inputs
  26373. //
  26374. const panelValues = writable({});
  26375. component_subscribe($$self, panelValues, value => $$invalidate(18, $panelValues = value));
  26376. const rangeInputConfig = writable({});
  26377. component_subscribe($$self, rangeInputConfig, value => $$invalidate(5, $rangeInputConfig = value));
  26378. const updateRangeInputState = () => {
  26379. set_store_value(
  26380. rangeInputConfig,
  26381. $rangeInputConfig = Object.keys($panelValues).reduce(
  26382. (config, id) => {
  26383. const { base, min, max, getLabel, getStore, setValue = (store, v) => store.set(v) } = finetuneControlConfiguration[id];
  26384. const store = getStore(imageEffectStores);
  26385. const value = $panelValues[id] != null ? $panelValues[id] : base;
  26386. config[id] = {
  26387. base,
  26388. min,
  26389. max,
  26390. value,
  26391. valueLabel: getLabel
  26392. ? getLabel(value, min, max, max - min)
  26393. : Math.round(100 * value),
  26394. oninputmove: v => {
  26395. setValue(store, v);
  26396. },
  26397. oninputend: v => {
  26398. setValue(store, v);
  26399. history.write();
  26400. },
  26401. elasticity: elasticityMultiplier * rangeInputElasticity,
  26402. labelReset: locale.labelReset
  26403. };
  26404. return config;
  26405. },
  26406. {}
  26407. ),
  26408. $rangeInputConfig
  26409. );
  26410. };
  26411. // need to unsubscribe when redrawing vie
  26412. let unsubs = [];
  26413. const subscribePanelStores = config => {
  26414. if (unsubs) unsubs.forEach(unsub => unsub());
  26415. unsubs = panels.map(id => {
  26416. const { getStore, getValue = passthrough } = config[id];
  26417. const store = getStore(imageEffectStores);
  26418. return store.subscribe(value => {
  26419. const currentValue = value != null ? getValue(value) : value;
  26420. set_store_value(panelValues, $panelValues = { ...$panelValues, [id]: currentValue }, $panelValues);
  26421. });
  26422. });
  26423. };
  26424. //
  26425. // Footer
  26426. //
  26427. const footerOffset = spring($animation ? 20 : 0);
  26428. component_subscribe($$self, footerOffset, value => $$invalidate(21, $footerOffset = value));
  26429. const select_handler = ({ detail }) => $$invalidate(2, tabSelected = detail);
  26430. function measure_handler(event) {
  26431. bubble($$self, event);
  26432. }
  26433. $$self.$$set = $$props => {
  26434. if ("stores" in $$props) $$invalidate(14, stores = $$props.stores);
  26435. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(0, isActive = $$props.isActive));
  26436. if ("locale" in $$props) $$invalidate(15, locale = $$props.locale);
  26437. if ("finetuneControlConfiguration" in $$props) $$invalidate(16, finetuneControlConfiguration = $$props.finetuneControlConfiguration);
  26438. if ("finetuneOptions" in $$props) $$invalidate(17, finetuneOptions = $$props.finetuneOptions);
  26439. };
  26440. $$self.$$.update = () => {
  26441. if ($$self.$$.dirty[0] & /*finetuneOptions, locale*/ 163840) {
  26442. $$invalidate(1, tabs = finetuneOptions
  26443. ? finetuneOptions.map(([id, label]) => ({
  26444. id,
  26445. label: isFunction(label) ? label(locale) : label
  26446. }))
  26447. : []);
  26448. }
  26449. if ($$self.$$.dirty[0] & /*tabs*/ 2) {
  26450. $$invalidate(2, tabSelected = tabs.length && tabs[0].id);
  26451. }
  26452. if ($$self.$$.dirty[0] & /*tabSelected*/ 4) {
  26453. $$invalidate(3, tabsConfig = { name: uid, selected: tabSelected });
  26454. }
  26455. if ($$self.$$.dirty[0] & /*tabs*/ 2) {
  26456. $$invalidate(4, panels = tabs.map(tab => tab.id));
  26457. }
  26458. if ($$self.$$.dirty[0] & /*finetuneControlConfiguration*/ 65536) {
  26459. finetuneControlConfiguration && subscribePanelStores(finetuneControlConfiguration);
  26460. }
  26461. if ($$self.$$.dirty[0] & /*finetuneControlConfiguration, $panelValues*/ 327680) {
  26462. finetuneControlConfiguration && $panelValues && updateRangeInputState();
  26463. }
  26464. if ($$self.$$.dirty[0] & /*$animation, $isActive*/ 1572864) {
  26465. $animation && footerOffset.set($isActive ? 0 : 20);
  26466. }
  26467. if ($$self.$$.dirty[0] & /*$footerOffset*/ 2097152) {
  26468. $$invalidate(6, footerStyle = $footerOffset
  26469. ? `transform: translateY(${$footerOffset}px)`
  26470. : undefined);
  26471. }
  26472. };
  26473. return [
  26474. isActive,
  26475. tabs,
  26476. tabSelected,
  26477. tabsConfig,
  26478. panels,
  26479. $rangeInputConfig,
  26480. footerStyle,
  26481. animation,
  26482. scrollElasticity,
  26483. elasticityMultiplier,
  26484. panelValues,
  26485. rangeInputConfig,
  26486. footerOffset,
  26487. name,
  26488. stores,
  26489. locale,
  26490. finetuneControlConfiguration,
  26491. finetuneOptions,
  26492. $panelValues,
  26493. $animation,
  26494. $isActive,
  26495. $footerOffset,
  26496. select_handler,
  26497. measure_handler
  26498. ];
  26499. }
  26500. class Finetune extends SvelteComponent {
  26501. constructor(options) {
  26502. super();
  26503. init(
  26504. this,
  26505. options,
  26506. instance$i,
  26507. create_fragment$i,
  26508. safe_not_equal,
  26509. {
  26510. name: 13,
  26511. stores: 14,
  26512. isActive: 0,
  26513. locale: 15,
  26514. finetuneControlConfiguration: 16,
  26515. finetuneOptions: 17
  26516. },
  26517. [-1, -1]
  26518. );
  26519. }
  26520. get name() {
  26521. return this.$$.ctx[13];
  26522. }
  26523. get stores() {
  26524. return this.$$.ctx[14];
  26525. }
  26526. set stores(stores) {
  26527. this.$set({ stores });
  26528. flush();
  26529. }
  26530. get isActive() {
  26531. return this.$$.ctx[0];
  26532. }
  26533. set isActive(isActive) {
  26534. this.$set({ isActive });
  26535. flush();
  26536. }
  26537. get locale() {
  26538. return this.$$.ctx[15];
  26539. }
  26540. set locale(locale) {
  26541. this.$set({ locale });
  26542. flush();
  26543. }
  26544. get finetuneControlConfiguration() {
  26545. return this.$$.ctx[16];
  26546. }
  26547. set finetuneControlConfiguration(finetuneControlConfiguration) {
  26548. this.$set({ finetuneControlConfiguration });
  26549. flush();
  26550. }
  26551. get finetuneOptions() {
  26552. return this.$$.ctx[17];
  26553. }
  26554. set finetuneOptions(finetuneOptions) {
  26555. this.$set({ finetuneOptions });
  26556. flush();
  26557. }
  26558. }
  26559. // @ts-ignore
  26560. var _plugin_finetune = { util: ['finetune', Finetune] };
  26561. /* src/core/ui/components/ShapeManipulator.svelte generated by Svelte v3.37.0 */
  26562. function get_each_context$4(ctx, list, i) {
  26563. const child_ctx = ctx.slice();
  26564. child_ctx[47] = list[i].key;
  26565. child_ctx[48] = list[i].index;
  26566. child_ctx[49] = list[i].translate;
  26567. child_ctx[50] = list[i].scale;
  26568. child_ctx[14] = list[i].rotate;
  26569. child_ctx[51] = list[i].dir;
  26570. child_ctx[52] = list[i].center;
  26571. child_ctx[53] = list[i].type;
  26572. return child_ctx;
  26573. }
  26574. // (247:4) {#if type === 'edge' && resizeAxis !== 'both'}
  26575. function create_if_block_1$3(ctx) {
  26576. let div;
  26577. let div_style_value;
  26578. return {
  26579. c() {
  26580. div = element("div");
  26581. attr(div, "class", "PinturaShapeManipulator");
  26582. attr(div, "data-control", "point");
  26583. attr(div, "style", div_style_value = `pointer-events:none;transform: translate3d(${/*center*/ ctx[52].x}px, ${/*center*/ ctx[52].y}px, 0) scale(${/*$selectionScale*/ ctx[5]}, ${/*$selectionScale*/ ctx[5]}); opacity: ${/*$selectionOpacity*/ ctx[6]}`);
  26584. },
  26585. m(target, anchor) {
  26586. insert(target, div, anchor);
  26587. },
  26588. p(ctx, dirty) {
  26589. if (dirty[0] & /*resizeControls, $selectionScale, $selectionOpacity*/ 104 && div_style_value !== (div_style_value = `pointer-events:none;transform: translate3d(${/*center*/ ctx[52].x}px, ${/*center*/ ctx[52].y}px, 0) scale(${/*$selectionScale*/ ctx[5]}, ${/*$selectionScale*/ ctx[5]}); opacity: ${/*$selectionOpacity*/ ctx[6]}`)) {
  26590. attr(div, "style", div_style_value);
  26591. }
  26592. },
  26593. d(detaching) {
  26594. if (detaching) detach(div);
  26595. }
  26596. };
  26597. }
  26598. // (226:0) {#each resizeControls as { key, index, translate, scale, rotate, dir, center, type }
  26599. function create_each_block$4(key_1, ctx) {
  26600. let div;
  26601. let div_aria_label_value;
  26602. let div_tabindex_value;
  26603. let div_data_control_value;
  26604. let div_style_value;
  26605. let t;
  26606. let if_block_anchor;
  26607. let mounted;
  26608. let dispose;
  26609. function nudge_handler(...args) {
  26610. return /*nudge_handler*/ ctx[18](/*index*/ ctx[48], ...args);
  26611. }
  26612. let if_block = /*type*/ ctx[53] === "edge" && /*resizeAxis*/ ctx[2] !== "both" && create_if_block_1$3(ctx);
  26613. return {
  26614. key: key_1,
  26615. first: null,
  26616. c() {
  26617. div = element("div");
  26618. t = space();
  26619. if (if_block) if_block.c();
  26620. if_block_anchor = empty();
  26621. attr(div, "role", "button");
  26622. attr(div, "aria-label", div_aria_label_value = `Drag ${/*type*/ ctx[53]} ${/*key*/ ctx[47]}`);
  26623. attr(div, "tabindex", div_tabindex_value = /*type*/ ctx[53] === "edge" ? -1 : 0);
  26624. attr(div, "class", "PinturaShapeManipulator");
  26625. attr(div, "data-control", div_data_control_value = /*type*/ ctx[53]);
  26626. attr(div, "style", div_style_value = `cursor: ${/*dir*/ ctx[51] ? /*dir*/ ctx[51] + "-resize" : "move"}; transform: translate3d(${/*translate*/ ctx[49].x}px, ${/*translate*/ ctx[49].y}px, 0)${/*type*/ ctx[53] === "edge"
  26627. ? ` rotate(${/*rotate*/ ctx[14]}rad)`
  26628. : ""} scale(${/*type*/ ctx[53] === "point"
  26629. ? /*$selectionScale*/ ctx[5]
  26630. : /*scale*/ ctx[50].x}, ${/*type*/ ctx[53] === "point"
  26631. ? /*$selectionScale*/ ctx[5]
  26632. : /*scale*/ ctx[50].y}); opacity: ${/*$selectionOpacity*/ ctx[6]}`);
  26633. this.first = div;
  26634. },
  26635. m(target, anchor) {
  26636. insert(target, div, anchor);
  26637. insert(target, t, anchor);
  26638. if (if_block) if_block.m(target, anchor);
  26639. insert(target, if_block_anchor, anchor);
  26640. if (!mounted) {
  26641. dispose = [
  26642. listen(div, "keydown", /*handleKeyDown*/ ctx[7]),
  26643. listen(div, "keyup", /*handleKeyUp*/ ctx[8]),
  26644. listen(div, "nudge", nudge_handler),
  26645. action_destroyer(nudgeable.call(null, div)),
  26646. listen(div, "interactionstart", function () {
  26647. if (is_function(/*resize*/ ctx[11]("start", /*index*/ ctx[48]))) /*resize*/ ctx[11]("start", /*index*/ ctx[48]).apply(this, arguments);
  26648. }),
  26649. listen(div, "interactionupdate", function () {
  26650. if (is_function(/*resize*/ ctx[11]("move", /*index*/ ctx[48]))) /*resize*/ ctx[11]("move", /*index*/ ctx[48]).apply(this, arguments);
  26651. }),
  26652. listen(div, "interactionend", function () {
  26653. if (is_function(/*resize*/ ctx[11]("end", /*index*/ ctx[48]))) /*resize*/ ctx[11]("end", /*index*/ ctx[48]).apply(this, arguments);
  26654. }),
  26655. action_destroyer(interactable.call(null, div))
  26656. ];
  26657. mounted = true;
  26658. }
  26659. },
  26660. p(new_ctx, dirty) {
  26661. ctx = new_ctx;
  26662. if (dirty[0] & /*resizeControls*/ 8 && div_aria_label_value !== (div_aria_label_value = `Drag ${/*type*/ ctx[53]} ${/*key*/ ctx[47]}`)) {
  26663. attr(div, "aria-label", div_aria_label_value);
  26664. }
  26665. if (dirty[0] & /*resizeControls*/ 8 && div_tabindex_value !== (div_tabindex_value = /*type*/ ctx[53] === "edge" ? -1 : 0)) {
  26666. attr(div, "tabindex", div_tabindex_value);
  26667. }
  26668. if (dirty[0] & /*resizeControls*/ 8 && div_data_control_value !== (div_data_control_value = /*type*/ ctx[53])) {
  26669. attr(div, "data-control", div_data_control_value);
  26670. }
  26671. if (dirty[0] & /*resizeControls, $selectionScale, $selectionOpacity*/ 104 && div_style_value !== (div_style_value = `cursor: ${/*dir*/ ctx[51] ? /*dir*/ ctx[51] + "-resize" : "move"}; transform: translate3d(${/*translate*/ ctx[49].x}px, ${/*translate*/ ctx[49].y}px, 0)${/*type*/ ctx[53] === "edge"
  26672. ? ` rotate(${/*rotate*/ ctx[14]}rad)`
  26673. : ""} scale(${/*type*/ ctx[53] === "point"
  26674. ? /*$selectionScale*/ ctx[5]
  26675. : /*scale*/ ctx[50].x}, ${/*type*/ ctx[53] === "point"
  26676. ? /*$selectionScale*/ ctx[5]
  26677. : /*scale*/ ctx[50].y}); opacity: ${/*$selectionOpacity*/ ctx[6]}`)) {
  26678. attr(div, "style", div_style_value);
  26679. }
  26680. if (/*type*/ ctx[53] === "edge" && /*resizeAxis*/ ctx[2] !== "both") {
  26681. if (if_block) {
  26682. if_block.p(ctx, dirty);
  26683. } else {
  26684. if_block = create_if_block_1$3(ctx);
  26685. if_block.c();
  26686. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  26687. }
  26688. } else if (if_block) {
  26689. if_block.d(1);
  26690. if_block = null;
  26691. }
  26692. },
  26693. d(detaching) {
  26694. if (detaching) detach(div);
  26695. if (detaching) detach(t);
  26696. if (if_block) if_block.d(detaching);
  26697. if (detaching) detach(if_block_anchor);
  26698. mounted = false;
  26699. run_all(dispose);
  26700. }
  26701. };
  26702. }
  26703. // (255:0) {#if enableRotating && rotationControlActive}
  26704. function create_if_block$3(ctx) {
  26705. let div;
  26706. let div_style_value;
  26707. let mounted;
  26708. let dispose;
  26709. return {
  26710. c() {
  26711. div = element("div");
  26712. attr(div, "role", "button");
  26713. attr(div, "aria-label", "Drag rotator");
  26714. attr(div, "tabindex", "0");
  26715. attr(div, "class", "PinturaShapeManipulator");
  26716. attr(div, "data-control", "rotate");
  26717. attr(div, "style", div_style_value = `transform: translate3d(${/*rotatorPoint*/ ctx[0].x}px, ${/*rotatorPoint*/ ctx[0].y}px, 0) scale(${/*$selectionScale*/ ctx[5]}, ${/*$selectionScale*/ ctx[5]}); opacity: ${/*$selectionOpacity*/ ctx[6]}`);
  26718. },
  26719. m(target, anchor) {
  26720. insert(target, div, anchor);
  26721. if (!mounted) {
  26722. dispose = [
  26723. listen(div, "keydown", /*handleKeyDown*/ ctx[7]),
  26724. listen(div, "keyup", /*handleKeyUp*/ ctx[8]),
  26725. listen(div, "nudge", /*handleRotateNudge*/ ctx[13]),
  26726. action_destroyer(nudgeable.call(null, div)),
  26727. listen(div, "interactionstart", /*rotate*/ ctx[14]("start")),
  26728. listen(div, "interactionupdate", /*rotate*/ ctx[14]("move")),
  26729. listen(div, "interactionend", /*rotate*/ ctx[14]("end")),
  26730. action_destroyer(interactable.call(null, div))
  26731. ];
  26732. mounted = true;
  26733. }
  26734. },
  26735. p(ctx, dirty) {
  26736. if (dirty[0] & /*rotatorPoint, $selectionScale, $selectionOpacity*/ 97 && div_style_value !== (div_style_value = `transform: translate3d(${/*rotatorPoint*/ ctx[0].x}px, ${/*rotatorPoint*/ ctx[0].y}px, 0) scale(${/*$selectionScale*/ ctx[5]}, ${/*$selectionScale*/ ctx[5]}); opacity: ${/*$selectionOpacity*/ ctx[6]}`)) {
  26737. attr(div, "style", div_style_value);
  26738. }
  26739. },
  26740. d(detaching) {
  26741. if (detaching) detach(div);
  26742. mounted = false;
  26743. run_all(dispose);
  26744. }
  26745. };
  26746. }
  26747. function create_fragment$h(ctx) {
  26748. let each_blocks = [];
  26749. let each_1_lookup = new Map();
  26750. let t;
  26751. let if_block_anchor;
  26752. let each_value = /*resizeControls*/ ctx[3];
  26753. const get_key = ctx => /*key*/ ctx[47];
  26754. for (let i = 0; i < each_value.length; i += 1) {
  26755. let child_ctx = get_each_context$4(ctx, each_value, i);
  26756. let key = get_key(child_ctx);
  26757. each_1_lookup.set(key, each_blocks[i] = create_each_block$4(key, child_ctx));
  26758. }
  26759. let if_block = /*enableRotating*/ ctx[1] && /*rotationControlActive*/ ctx[4] && create_if_block$3(ctx);
  26760. return {
  26761. c() {
  26762. for (let i = 0; i < each_blocks.length; i += 1) {
  26763. each_blocks[i].c();
  26764. }
  26765. t = space();
  26766. if (if_block) if_block.c();
  26767. if_block_anchor = empty();
  26768. },
  26769. m(target, anchor) {
  26770. for (let i = 0; i < each_blocks.length; i += 1) {
  26771. each_blocks[i].m(target, anchor);
  26772. }
  26773. insert(target, t, anchor);
  26774. if (if_block) if_block.m(target, anchor);
  26775. insert(target, if_block_anchor, anchor);
  26776. },
  26777. p(ctx, dirty) {
  26778. if (dirty[0] & /*resizeControls, $selectionScale, $selectionOpacity, resizeAxis, handleKeyDown, handleKeyUp, handleResizeNudge, resize*/ 6636) {
  26779. each_value = /*resizeControls*/ ctx[3];
  26780. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, t.parentNode, destroy_block, create_each_block$4, t, get_each_context$4);
  26781. }
  26782. if (/*enableRotating*/ ctx[1] && /*rotationControlActive*/ ctx[4]) {
  26783. if (if_block) {
  26784. if_block.p(ctx, dirty);
  26785. } else {
  26786. if_block = create_if_block$3(ctx);
  26787. if_block.c();
  26788. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  26789. }
  26790. } else if (if_block) {
  26791. if_block.d(1);
  26792. if_block = null;
  26793. }
  26794. },
  26795. i: noop,
  26796. o: noop,
  26797. d(detaching) {
  26798. for (let i = 0; i < each_blocks.length; i += 1) {
  26799. each_blocks[i].d(detaching);
  26800. }
  26801. if (detaching) detach(t);
  26802. if (if_block) if_block.d(detaching);
  26803. if (detaching) detach(if_block_anchor);
  26804. }
  26805. };
  26806. }
  26807. function instance$h($$self, $$props, $$invalidate) {
  26808. let resizeAxis;
  26809. let resizeControls;
  26810. let rotationControlActive;
  26811. let $selectionScale;
  26812. let $selectionOpacity;
  26813. const dispatch = createEventDispatcher();
  26814. // which cursor to render
  26815. const EIGTH_PI = QUART_PI * 0.5;
  26816. const N = HALF_PI;
  26817. const N0 = N - EIGTH_PI;
  26818. const N1 = N + EIGTH_PI;
  26819. const S = -HALF_PI;
  26820. const S0 = S - EIGTH_PI;
  26821. const S1 = S + EIGTH_PI;
  26822. const E = PI;
  26823. const E0 = E - EIGTH_PI;
  26824. const E1 = -PI + EIGTH_PI;
  26825. const W0 = EIGTH_PI;
  26826. const W1 = -EIGTH_PI;
  26827. const NW = N - QUART_PI;
  26828. const NW0 = NW - EIGTH_PI;
  26829. const NW1 = NW + EIGTH_PI;
  26830. const NE = PI - QUART_PI;
  26831. const NE0 = NE - EIGTH_PI;
  26832. const NE1 = NE + EIGTH_PI;
  26833. const SE = S - QUART_PI;
  26834. const SE0 = SE + EIGTH_PI;
  26835. const SE1 = SE - EIGTH_PI;
  26836. const SW = S + QUART_PI;
  26837. const SW0 = SW + EIGTH_PI;
  26838. const SW1 = SW - EIGTH_PI;
  26839. let { points = [] } = $$props;
  26840. let { rotatorPoint = undefined } = $$props;
  26841. let { visible = false } = $$props;
  26842. let { enableResizing = true } = $$props;
  26843. let { enableRotating = true } = $$props;
  26844. // // internal
  26845. let shiftKey = false;
  26846. const handleKeyDown = e => shiftKey = e.shiftKey;
  26847. const handleKeyUp = e => shiftKey = false;
  26848. // state
  26849. const selectionScale = spring(0.5, {
  26850. precision: 0.0001,
  26851. stiffness: 0.3,
  26852. damping: 0.7
  26853. });
  26854. component_subscribe($$self, selectionScale, value => $$invalidate(5, $selectionScale = value));
  26855. const selectionOpacity = spring(0, {
  26856. precision: 0.001,
  26857. stiffness: 0.3,
  26858. damping: 0.7
  26859. });
  26860. component_subscribe($$self, selectionOpacity, value => $$invalidate(6, $selectionOpacity = value));
  26861. const rotate = type => ({ detail }) => {
  26862. // always make sure we have a translation to work with
  26863. const translation = detail && detail.translation
  26864. ? detail.translation
  26865. : vectorCreate(0, 0);
  26866. dispatch(`rotate${type}`, { translation, shiftKey });
  26867. };
  26868. const resize = (type, indexes) => ({ detail }) => {
  26869. // always make sure we have a translation to work with
  26870. const translation = detail && detail.translation
  26871. ? detail.translation
  26872. : vectorCreate(0, 0);
  26873. // done transforming the points
  26874. dispatch(`resize${type}`, { indexes, translation, shiftKey });
  26875. };
  26876. // https://en.wikipedia.org/wiki/Radian#/media/File:Degree-Radian_Conversion.svg
  26877. const getDirectionByAngle = angle => {
  26878. let dir = "";
  26879. const isNorth = angle <= N1 && angle >= N0;
  26880. const isSouth = angle >= S0 && angle <= S1;
  26881. const isEast = angle <= E1 || angle >= E0;
  26882. const isWest = angle >= W1 && angle <= W0;
  26883. const isNorthEast = angle >= NE0 && angle <= NE1;
  26884. const isNorthWest = angle >= NW0 && angle <= NW1;
  26885. const isSouthEast = angle <= SE0 && angle >= SE1;
  26886. const isSouthWest = angle <= SW0 && angle >= SW1;
  26887. if (isNorth || isSouth) dir = "ns";
  26888. if (isEast || isWest) dir = "ew";
  26889. if (isNorthEast || isSouthWest) dir = "nesw";
  26890. if (isNorthWest || isSouthEast) dir = "nwse";
  26891. return dir;
  26892. };
  26893. // 2 points -> [corner, corner]
  26894. // 3 points => [corner, edge, corner, edge, corner, edge],
  26895. // 4 points => [corner, edge, corner, edge, corner, edge, corner, edge]
  26896. const mapPointsToControls = (points, axis) => {
  26897. let i = 0;
  26898. const center = vectorCenter(points);
  26899. const out = [];
  26900. const l = points.length;
  26901. const isLine = l === 2;
  26902. const isAxisLimited = axis !== "both";
  26903. for (; i < l; i++) {
  26904. const p0 = points[i - 1] || points[points.length - 1];
  26905. const p1 = points[i];
  26906. const p2 = points[i + 1] || points[0];
  26907. const dir = Math.atan2(p2.y - p1.y, p2.x - p1.x);
  26908. // create corner, only allowed if axis equal 'both'
  26909. if (!isAxisLimited) {
  26910. const a = vectorNormalize(vectorCreate(p0.x - p1.x, p0.y - p1.y));
  26911. const b = vectorNormalize(vectorCreate(p2.x - p1.x, p2.y - p1.y));
  26912. const cornerVector = vectorCreate(a.x + b.x, a.y + b.y);
  26913. out.push({
  26914. index: [i],
  26915. key: `point-${i}`,
  26916. type: "point",
  26917. scale: { x: 1, y: 1 },
  26918. translate: { x: p1.x, y: p1.y },
  26919. angle: undefined,
  26920. rotate: isLine ? 0 : dir,
  26921. center: p1,
  26922. dir: isLine
  26923. ? undefined
  26924. : getDirectionByAngle(Math.atan2(cornerVector.y, cornerVector.x))
  26925. });
  26926. }
  26927. // if only two points, skip edge
  26928. if (isLine) continue;
  26929. const mid = vectorCreate(p1.x + (p2.x - p1.x) * 0.5, p1.y + (p2.y - p1.y) * 0.5);
  26930. // only allow horizontal controls
  26931. if (axis === "horizontal" && i % 2 === 0) continue;
  26932. // only allow vertical controls
  26933. if (axis === "vertical" && i % 2 !== 0) continue;
  26934. // create edge
  26935. out.push({
  26936. index: [i, i + 1 === l ? 0 : i + 1],
  26937. key: `edge-${i}`,
  26938. type: "edge",
  26939. scale: { x: vectorDistance(p1, p2), y: 1 },
  26940. translate: { x: p1.x, y: p1.y },
  26941. angle: dir,
  26942. rotate: dir,
  26943. center: mid,
  26944. dir: getDirectionByAngle(Math.atan2(center.y - mid.y, center.x - mid.x))
  26945. });
  26946. }
  26947. return out;
  26948. };
  26949. const handleResizeNudge = (indexes, translation) => {
  26950. dispatch(`resizestart`, {
  26951. indexes,
  26952. translation: vectorCreateEmpty()
  26953. });
  26954. dispatch(`resizemove`, { indexes, translation });
  26955. dispatch(`resizeend`, {
  26956. indexes,
  26957. translation: vectorCreateEmpty()
  26958. });
  26959. };
  26960. const handleRotateNudge = ({ detail }) => {
  26961. dispatch(`rotatestart`, { translation: vectorCreateEmpty() });
  26962. dispatch(`rotatemove`, { translation: detail });
  26963. dispatch(`rotateend`, { translation: vectorCreateEmpty() });
  26964. };
  26965. const nudge_handler = (index, { detail }) => handleResizeNudge(index, detail);
  26966. $$self.$$set = $$props => {
  26967. if ("points" in $$props) $$invalidate(15, points = $$props.points);
  26968. if ("rotatorPoint" in $$props) $$invalidate(0, rotatorPoint = $$props.rotatorPoint);
  26969. if ("visible" in $$props) $$invalidate(16, visible = $$props.visible);
  26970. if ("enableResizing" in $$props) $$invalidate(17, enableResizing = $$props.enableResizing);
  26971. if ("enableRotating" in $$props) $$invalidate(1, enableRotating = $$props.enableRotating);
  26972. };
  26973. $$self.$$.update = () => {
  26974. if ($$self.$$.dirty[0] & /*visible*/ 65536) {
  26975. selectionScale.set(visible ? 1 : 0.5);
  26976. }
  26977. if ($$self.$$.dirty[0] & /*visible*/ 65536) {
  26978. selectionOpacity.set(visible ? 1 : 0);
  26979. }
  26980. if ($$self.$$.dirty[0] & /*enableResizing*/ 131072) {
  26981. $$invalidate(2, resizeAxis = !enableResizing
  26982. ? false
  26983. : isString(enableResizing) ? enableResizing : "both");
  26984. }
  26985. if ($$self.$$.dirty[0] & /*resizeAxis, points*/ 32772) {
  26986. $$invalidate(3, resizeControls = resizeAxis && mapPointsToControls(points, resizeAxis) || []);
  26987. }
  26988. if ($$self.$$.dirty[0] & /*points*/ 32768) {
  26989. $$invalidate(4, rotationControlActive = points.length > 2);
  26990. }
  26991. };
  26992. return [
  26993. rotatorPoint,
  26994. enableRotating,
  26995. resizeAxis,
  26996. resizeControls,
  26997. rotationControlActive,
  26998. $selectionScale,
  26999. $selectionOpacity,
  27000. handleKeyDown,
  27001. handleKeyUp,
  27002. selectionScale,
  27003. selectionOpacity,
  27004. resize,
  27005. handleResizeNudge,
  27006. handleRotateNudge,
  27007. rotate,
  27008. points,
  27009. visible,
  27010. enableResizing,
  27011. nudge_handler
  27012. ];
  27013. }
  27014. class ShapeManipulator extends SvelteComponent {
  27015. constructor(options) {
  27016. super();
  27017. init(
  27018. this,
  27019. options,
  27020. instance$h,
  27021. create_fragment$h,
  27022. safe_not_equal,
  27023. {
  27024. points: 15,
  27025. rotatorPoint: 0,
  27026. visible: 16,
  27027. enableResizing: 17,
  27028. enableRotating: 1
  27029. },
  27030. [-1, -1]
  27031. );
  27032. }
  27033. }
  27034. var getEventPositionInEditor = (e, viewOffset) => {
  27035. const positionInViewport = getEventPositionInViewport(e);
  27036. return vectorSubtract(positionInViewport, viewOffset);
  27037. };
  27038. let result$1 = null;
  27039. var isAndroid = () => {
  27040. if (result$1 === null)
  27041. result$1 = isUserAgent(/Android/);
  27042. return result$1;
  27043. };
  27044. var cursorMoveToEnd = (field) => (field.selectionStart = field.selectionEnd = field.value.length);
  27045. let result = null;
  27046. var supportsVisualViewport = () => {
  27047. if (result === null) {
  27048. result = isBrowser() && 'visualViewport' in window;
  27049. }
  27050. return result;
  27051. };
  27052. var createSoftKeyboardObserver = (cb) => {
  27053. if (!supportsVisualViewport())
  27054. return false;
  27055. const heightNormal = visualViewport.height;
  27056. const testState = () => {
  27057. cb(visualViewport.height < heightNormal ? 'visible' : 'hidden');
  27058. };
  27059. visualViewport.addEventListener('resize', testState);
  27060. return () => visualViewport.removeEventListener('resize', testState);
  27061. };
  27062. /* src/core/ui/components/InputForm.svelte generated by Svelte v3.37.0 */
  27063. function create_fragment$g(ctx) {
  27064. let div2;
  27065. let div1;
  27066. let button0;
  27067. let t0;
  27068. let div0;
  27069. let t1;
  27070. let button1;
  27071. let current;
  27072. let mounted;
  27073. let dispose;
  27074. button0 = new Button({
  27075. props: {
  27076. onclick: /*oncancel*/ ctx[1],
  27077. label: /*labelCancel*/ ctx[5],
  27078. icon: /*iconCancel*/ ctx[7],
  27079. hideLabel: !/*labelCancelShow*/ ctx[6]
  27080. }
  27081. });
  27082. const default_slot_template = /*#slots*/ ctx[20].default;
  27083. const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[19], null);
  27084. button1 = new Button({
  27085. props: {
  27086. onclick: /*onconfirm*/ ctx[0],
  27087. label: /*labelConfirm*/ ctx[2],
  27088. icon: /*iconConfirm*/ ctx[4],
  27089. hideLabel: !/*labelConfirmShow*/ ctx[3],
  27090. class: "PinturaInputFormButtonConfirm"
  27091. }
  27092. });
  27093. return {
  27094. c() {
  27095. div2 = element("div");
  27096. div1 = element("div");
  27097. create_component(button0.$$.fragment);
  27098. t0 = space();
  27099. div0 = element("div");
  27100. if (default_slot) default_slot.c();
  27101. t1 = space();
  27102. create_component(button1.$$.fragment);
  27103. attr(div0, "class", "PinturaInputFormFields");
  27104. attr(div1, "class", "PinturaInputFormInner");
  27105. attr(div2, "class", "PinturaInputForm");
  27106. attr(div2, "style", /*style*/ ctx[9]);
  27107. },
  27108. m(target, anchor) {
  27109. insert(target, div2, anchor);
  27110. append(div2, div1);
  27111. mount_component(button0, div1, null);
  27112. append(div1, t0);
  27113. append(div1, div0);
  27114. if (default_slot) {
  27115. default_slot.m(div0, null);
  27116. }
  27117. append(div1, t1);
  27118. mount_component(button1, div1, null);
  27119. /*div2_binding*/ ctx[21](div2);
  27120. current = true;
  27121. if (!mounted) {
  27122. dispose = [
  27123. listen(div2, "focusin", /*handleFocusIn*/ ctx[10]),
  27124. listen(div2, "focusout", /*handleFocusOut*/ ctx[11]),
  27125. listen(div2, "measure", /*handleMeasure*/ ctx[12]),
  27126. action_destroyer(measurable.call(null, div2))
  27127. ];
  27128. mounted = true;
  27129. }
  27130. },
  27131. p(ctx, dirty) {
  27132. const button0_changes = {};
  27133. if (dirty[0] & /*oncancel*/ 2) button0_changes.onclick = /*oncancel*/ ctx[1];
  27134. if (dirty[0] & /*labelCancel*/ 32) button0_changes.label = /*labelCancel*/ ctx[5];
  27135. if (dirty[0] & /*iconCancel*/ 128) button0_changes.icon = /*iconCancel*/ ctx[7];
  27136. if (dirty[0] & /*labelCancelShow*/ 64) button0_changes.hideLabel = !/*labelCancelShow*/ ctx[6];
  27137. button0.$set(button0_changes);
  27138. if (default_slot) {
  27139. if (default_slot.p && dirty[0] & /*$$scope*/ 524288) {
  27140. update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[19], dirty, null, null);
  27141. }
  27142. }
  27143. const button1_changes = {};
  27144. if (dirty[0] & /*onconfirm*/ 1) button1_changes.onclick = /*onconfirm*/ ctx[0];
  27145. if (dirty[0] & /*labelConfirm*/ 4) button1_changes.label = /*labelConfirm*/ ctx[2];
  27146. if (dirty[0] & /*iconConfirm*/ 16) button1_changes.icon = /*iconConfirm*/ ctx[4];
  27147. if (dirty[0] & /*labelConfirmShow*/ 8) button1_changes.hideLabel = !/*labelConfirmShow*/ ctx[3];
  27148. button1.$set(button1_changes);
  27149. if (!current || dirty[0] & /*style*/ 512) {
  27150. attr(div2, "style", /*style*/ ctx[9]);
  27151. }
  27152. },
  27153. i(local) {
  27154. if (current) return;
  27155. transition_in(button0.$$.fragment, local);
  27156. transition_in(default_slot, local);
  27157. transition_in(button1.$$.fragment, local);
  27158. current = true;
  27159. },
  27160. o(local) {
  27161. transition_out(button0.$$.fragment, local);
  27162. transition_out(default_slot, local);
  27163. transition_out(button1.$$.fragment, local);
  27164. current = false;
  27165. },
  27166. d(detaching) {
  27167. if (detaching) detach(div2);
  27168. destroy_component(button0);
  27169. if (default_slot) default_slot.d(detaching);
  27170. destroy_component(button1);
  27171. /*div2_binding*/ ctx[21](null);
  27172. mounted = false;
  27173. run_all(dispose);
  27174. }
  27175. };
  27176. }
  27177. const panelDelay = 200;
  27178. function instance$g($$self, $$props, $$invalidate) {
  27179. let computedStyle;
  27180. let shouldStickToKeyboard;
  27181. let style;
  27182. let { $$slots: slots = {}, $$scope } = $$props;
  27183. let { onconfirm } = $$props;
  27184. let { oncancel } = $$props;
  27185. let { autoFocus = true } = $$props;
  27186. let { autoPositionCursor = true } = $$props;
  27187. let { labelConfirm } = $$props;
  27188. let { labelConfirmShow = true } = $$props;
  27189. let { iconConfirm } = $$props;
  27190. let { labelCancel } = $$props;
  27191. let { labelCancelShow = false } = $$props;
  27192. let { iconCancel } = $$props;
  27193. let { panelOffset = vectorCreateEmpty() } = $$props;
  27194. let panelVisible = false;
  27195. let panelHeight = undefined;
  27196. let panelRevealTimeout = undefined;
  27197. let panelPosition = "";
  27198. let panelOpacity = 0;
  27199. let root;
  27200. const isTextarea = element => (/textarea/i).test(element);
  27201. const preventTextAreaScrollingOnIOS = element => {
  27202. // preventsDefault on textarea events when can no longer scroll up or down in textarea
  27203. let lastScreenY;
  27204. const handleTouchStart = e => lastScreenY = e.touches[0].screenY;
  27205. const handleTouchMove = e => {
  27206. const currentScreenY = e.touches[0].screenY;
  27207. const target = e.target;
  27208. if ((/textarea/i).test(target.nodeName)) {
  27209. // moving down
  27210. if (currentScreenY > lastScreenY) {
  27211. if (target.scrollTop == 0) {
  27212. e.preventDefault();
  27213. }
  27214. } else // moving up
  27215. if (currentScreenY < lastScreenY) {
  27216. if (target.scrollTop + target.offsetHeight == target.scrollHeight) {
  27217. e.preventDefault();
  27218. }
  27219. } else {
  27220. e.preventDefault();
  27221. }
  27222. lastScreenY = currentScreenY;
  27223. } else {
  27224. e.preventDefault();
  27225. }
  27226. };
  27227. element.addEventListener("touchstart", handleTouchStart);
  27228. element.addEventListener("touchmove", handleTouchMove);
  27229. return () => {
  27230. element.removeEventListener("touchstart", handleTouchStart);
  27231. element.removeEventListener("touchmove", handleTouchMove);
  27232. };
  27233. };
  27234. const focus = () => {
  27235. const field = root.querySelector("input, textarea");
  27236. field.focus();
  27237. field.select();
  27238. };
  27239. const show = () => {
  27240. panelVisible = true;
  27241. // browser does not support keyboard listener, place modal at top of view
  27242. if (!unsubSoftKeyboardListener && (isIOS() || isAndroid())) {
  27243. $$invalidate(16, panelPosition = "top:1em;bottom:auto;");
  27244. }
  27245. // prevent interacting with the root element
  27246. if (isIOS()) preventTextAreaScrollingOnIOS(root);
  27247. // reveal
  27248. $$invalidate(17, panelOpacity = 1);
  27249. };
  27250. const hide = () => {
  27251. panelVisible = false;
  27252. $$invalidate(17, panelOpacity = 0);
  27253. };
  27254. const handleSoftKeyboard = keyboardState => {
  27255. // shouldn't stick, we'll stick it to the top of the viewport so the keyboard doesn't obscure the input field
  27256. if (!shouldStickToKeyboard) {
  27257. $$invalidate(16, panelPosition = `top: 4.5em; bottom: auto`);
  27258. return;
  27259. }
  27260. // no need to continue, already hidden
  27261. if (keyboardState === "hidden" && !panelVisible) {
  27262. focus();
  27263. return;
  27264. }
  27265. // gonna update position here
  27266. clearTimeout(panelRevealTimeout);
  27267. panelRevealTimeout = undefined;
  27268. // position
  27269. $$invalidate(16, panelPosition = `top:${visualViewport.height - panelHeight - panelOffset.y}px`);
  27270. // if a soft keyboard is detected, turn into modal mode
  27271. if (keyboardState === "visible") {
  27272. // stick to keyboard
  27273. $$invalidate(8, root.dataset.layout = "stick", root);
  27274. // need to refocus
  27275. focus();
  27276. // place above keyboard
  27277. show();
  27278. } else // keyboard is hidden
  27279. {
  27280. hide();
  27281. }
  27282. };
  27283. let focusDateTime;
  27284. const handleFocusIn = e => {
  27285. if (!isTextarea(e.target)) return;
  27286. // we need to remember focus time so we can detect unrealistic blur event caused by soft keyboard shenanigans
  27287. focusDateTime = Date.now();
  27288. // move cursor
  27289. if (autoPositionCursor) cursorMoveToEnd(e.target);
  27290. // wait a couple milliseconds
  27291. clearTimeout(panelRevealTimeout);
  27292. panelRevealTimeout = setTimeout(show, panelDelay);
  27293. };
  27294. const handleFocusOut = e => {
  27295. const focusDuration = Date.now() - focusDateTime;
  27296. if (focusDuration > 50) return;
  27297. // unrealistic blur, refocus
  27298. e.stopPropagation();
  27299. focus();
  27300. };
  27301. const unsubSoftKeyboardListener = createSoftKeyboardObserver(handleSoftKeyboard);
  27302. const handleMeasure = ({ detail }) => {
  27303. panelHeight = detail.height;
  27304. };
  27305. onMount(() => {
  27306. if (!autoFocus) return;
  27307. focus();
  27308. });
  27309. onDestroy(() => {
  27310. unsubSoftKeyboardListener && unsubSoftKeyboardListener();
  27311. });
  27312. function div2_binding($$value) {
  27313. binding_callbacks[$$value ? "unshift" : "push"](() => {
  27314. root = $$value;
  27315. $$invalidate(8, root);
  27316. });
  27317. }
  27318. $$self.$$set = $$props => {
  27319. if ("onconfirm" in $$props) $$invalidate(0, onconfirm = $$props.onconfirm);
  27320. if ("oncancel" in $$props) $$invalidate(1, oncancel = $$props.oncancel);
  27321. if ("autoFocus" in $$props) $$invalidate(13, autoFocus = $$props.autoFocus);
  27322. if ("autoPositionCursor" in $$props) $$invalidate(14, autoPositionCursor = $$props.autoPositionCursor);
  27323. if ("labelConfirm" in $$props) $$invalidate(2, labelConfirm = $$props.labelConfirm);
  27324. if ("labelConfirmShow" in $$props) $$invalidate(3, labelConfirmShow = $$props.labelConfirmShow);
  27325. if ("iconConfirm" in $$props) $$invalidate(4, iconConfirm = $$props.iconConfirm);
  27326. if ("labelCancel" in $$props) $$invalidate(5, labelCancel = $$props.labelCancel);
  27327. if ("labelCancelShow" in $$props) $$invalidate(6, labelCancelShow = $$props.labelCancelShow);
  27328. if ("iconCancel" in $$props) $$invalidate(7, iconCancel = $$props.iconCancel);
  27329. if ("panelOffset" in $$props) $$invalidate(15, panelOffset = $$props.panelOffset);
  27330. if ("$$scope" in $$props) $$invalidate(19, $$scope = $$props.$$scope);
  27331. };
  27332. $$self.$$.update = () => {
  27333. if ($$self.$$.dirty[0] & /*root*/ 256) {
  27334. $$invalidate(18, computedStyle = root && getComputedStyle(root));
  27335. }
  27336. if ($$self.$$.dirty[0] & /*computedStyle*/ 262144) {
  27337. shouldStickToKeyboard = computedStyle && computedStyle.getPropertyValue("--editor-modal") === "1";
  27338. }
  27339. if ($$self.$$.dirty[0] & /*panelOpacity, panelPosition*/ 196608) {
  27340. $$invalidate(9, style = `opacity:${panelOpacity};${panelPosition}`);
  27341. }
  27342. };
  27343. return [
  27344. onconfirm,
  27345. oncancel,
  27346. labelConfirm,
  27347. labelConfirmShow,
  27348. iconConfirm,
  27349. labelCancel,
  27350. labelCancelShow,
  27351. iconCancel,
  27352. root,
  27353. style,
  27354. handleFocusIn,
  27355. handleFocusOut,
  27356. handleMeasure,
  27357. autoFocus,
  27358. autoPositionCursor,
  27359. panelOffset,
  27360. panelPosition,
  27361. panelOpacity,
  27362. computedStyle,
  27363. $$scope,
  27364. slots,
  27365. div2_binding
  27366. ];
  27367. }
  27368. class InputForm extends SvelteComponent {
  27369. constructor(options) {
  27370. super();
  27371. init(
  27372. this,
  27373. options,
  27374. instance$g,
  27375. create_fragment$g,
  27376. safe_not_equal,
  27377. {
  27378. onconfirm: 0,
  27379. oncancel: 1,
  27380. autoFocus: 13,
  27381. autoPositionCursor: 14,
  27382. labelConfirm: 2,
  27383. labelConfirmShow: 3,
  27384. iconConfirm: 4,
  27385. labelCancel: 5,
  27386. labelCancelShow: 6,
  27387. iconCancel: 7,
  27388. panelOffset: 15
  27389. },
  27390. [-1, -1]
  27391. );
  27392. }
  27393. }
  27394. /* src/core/ui/components/ShapeLayoutEditor.svelte generated by Svelte v3.37.0 */
  27395. function get_each_context$3(ctx, list, i) {
  27396. const child_ctx = ctx.slice();
  27397. child_ctx[178] = list[i];
  27398. child_ctx[180] = i;
  27399. return child_ctx;
  27400. }
  27401. // (2627:12) {#each shapeNavList as item, index (item.id)}
  27402. function create_each_block$3(key_1, ctx) {
  27403. let li;
  27404. let button;
  27405. let colorpreview;
  27406. let t0;
  27407. let span;
  27408. let t1_value = /*item*/ ctx[178].name + "";
  27409. let t1;
  27410. let button_aria_label_value;
  27411. let t2;
  27412. let current;
  27413. let mounted;
  27414. let dispose;
  27415. colorpreview = new ColorPreview({
  27416. props: { color: /*item*/ ctx[178].color }
  27417. });
  27418. function click_handler(...args) {
  27419. return /*click_handler*/ ctx[124](/*index*/ ctx[180], ...args);
  27420. }
  27421. return {
  27422. key: key_1,
  27423. first: null,
  27424. c() {
  27425. li = element("li");
  27426. button = element("button");
  27427. create_component(colorpreview.$$.fragment);
  27428. t0 = space();
  27429. span = element("span");
  27430. t1 = text(t1_value);
  27431. t2 = space();
  27432. attr(button, "class", "PinturaShapeListItem");
  27433. attr(button, "type", "button");
  27434. attr(button, "aria-label", button_aria_label_value = "Select shape " + /*item*/ ctx[178].name);
  27435. this.first = li;
  27436. },
  27437. m(target, anchor) {
  27438. insert(target, li, anchor);
  27439. append(li, button);
  27440. mount_component(colorpreview, button, null);
  27441. append(button, t0);
  27442. append(button, span);
  27443. append(span, t1);
  27444. append(li, t2);
  27445. current = true;
  27446. if (!mounted) {
  27447. dispose = listen(button, "click", click_handler);
  27448. mounted = true;
  27449. }
  27450. },
  27451. p(new_ctx, dirty) {
  27452. ctx = new_ctx;
  27453. const colorpreview_changes = {};
  27454. if (dirty[0] & /*shapeNavList*/ 524288) colorpreview_changes.color = /*item*/ ctx[178].color;
  27455. colorpreview.$set(colorpreview_changes);
  27456. if ((!current || dirty[0] & /*shapeNavList*/ 524288) && t1_value !== (t1_value = /*item*/ ctx[178].name + "")) set_data(t1, t1_value);
  27457. if (!current || dirty[0] & /*shapeNavList*/ 524288 && button_aria_label_value !== (button_aria_label_value = "Select shape " + /*item*/ ctx[178].name)) {
  27458. attr(button, "aria-label", button_aria_label_value);
  27459. }
  27460. },
  27461. i(local) {
  27462. if (current) return;
  27463. transition_in(colorpreview.$$.fragment, local);
  27464. current = true;
  27465. },
  27466. o(local) {
  27467. transition_out(colorpreview.$$.fragment, local);
  27468. current = false;
  27469. },
  27470. d(detaching) {
  27471. if (detaching) detach(li);
  27472. destroy_component(colorpreview);
  27473. mounted = false;
  27474. dispose();
  27475. }
  27476. };
  27477. }
  27478. // (2643:4) {#if shouldRenderShapeManipulator}
  27479. function create_if_block_2$2(ctx) {
  27480. let shapemanipulator;
  27481. let current;
  27482. shapemanipulator = new ShapeManipulator({
  27483. props: {
  27484. visible: true,
  27485. points: /*shapeManipulatorPoints*/ ctx[8],
  27486. rotatorPoint: /*shapeManipulatorRotationPointPosition*/ ctx[14],
  27487. enableResizing: /*allowedResizeControls*/ ctx[13],
  27488. enableRotating: /*allowRotateControls*/ ctx[6]
  27489. }
  27490. });
  27491. shapemanipulator.$on("resizestart", /*handleManipulatorResizeGrab*/ ctx[25]);
  27492. shapemanipulator.$on("resizemove", /*handleManipulatorResizeDrag*/ ctx[26]);
  27493. shapemanipulator.$on("resizeend", /*handleManipulatorResizeEnd*/ ctx[27]);
  27494. shapemanipulator.$on("rotatestart", /*handleManipulatorRotateGrab*/ ctx[28]);
  27495. shapemanipulator.$on("rotatemove", /*handleManipulatorRotateDrag*/ ctx[29]);
  27496. shapemanipulator.$on("rotateend", /*handleManipulatorRotateEnd*/ ctx[30]);
  27497. return {
  27498. c() {
  27499. create_component(shapemanipulator.$$.fragment);
  27500. },
  27501. m(target, anchor) {
  27502. mount_component(shapemanipulator, target, anchor);
  27503. current = true;
  27504. },
  27505. p(ctx, dirty) {
  27506. const shapemanipulator_changes = {};
  27507. if (dirty[0] & /*shapeManipulatorPoints*/ 256) shapemanipulator_changes.points = /*shapeManipulatorPoints*/ ctx[8];
  27508. if (dirty[0] & /*shapeManipulatorRotationPointPosition*/ 16384) shapemanipulator_changes.rotatorPoint = /*shapeManipulatorRotationPointPosition*/ ctx[14];
  27509. if (dirty[0] & /*allowedResizeControls*/ 8192) shapemanipulator_changes.enableResizing = /*allowedResizeControls*/ ctx[13];
  27510. if (dirty[0] & /*allowRotateControls*/ 64) shapemanipulator_changes.enableRotating = /*allowRotateControls*/ ctx[6];
  27511. shapemanipulator.$set(shapemanipulator_changes);
  27512. },
  27513. i(local) {
  27514. if (current) return;
  27515. transition_in(shapemanipulator.$$.fragment, local);
  27516. current = true;
  27517. },
  27518. o(local) {
  27519. transition_out(shapemanipulator.$$.fragment, local);
  27520. current = false;
  27521. },
  27522. d(detaching) {
  27523. destroy_component(shapemanipulator, detaching);
  27524. }
  27525. };
  27526. }
  27527. // (2659:4) {#if shouldRenderTextInput}
  27528. function create_if_block_1$2(ctx) {
  27529. let inputform;
  27530. let current;
  27531. inputform = new InputForm({
  27532. props: {
  27533. panelOffset: /*offset*/ ctx[1],
  27534. onconfirm: /*handleTextConfirm*/ ctx[36],
  27535. oncancel: /*handleTextCancel*/ ctx[37],
  27536. labelCancel: /*locale*/ ctx[3].shapeLabelInputCancel,
  27537. iconCancel: /*locale*/ ctx[3].shapeIconInputCancel,
  27538. labelConfirm: /*locale*/ ctx[3].shapeLabelInputConfirm,
  27539. iconConfirm: /*locale*/ ctx[3].shapeIconInputConfirm,
  27540. $$slots: { default: [create_default_slot$6] },
  27541. $$scope: { ctx }
  27542. }
  27543. });
  27544. return {
  27545. c() {
  27546. create_component(inputform.$$.fragment);
  27547. },
  27548. m(target, anchor) {
  27549. mount_component(inputform, target, anchor);
  27550. current = true;
  27551. },
  27552. p(ctx, dirty) {
  27553. const inputform_changes = {};
  27554. if (dirty[0] & /*offset*/ 2) inputform_changes.panelOffset = /*offset*/ ctx[1];
  27555. if (dirty[0] & /*locale*/ 8) inputform_changes.labelCancel = /*locale*/ ctx[3].shapeLabelInputCancel;
  27556. if (dirty[0] & /*locale*/ 8) inputform_changes.iconCancel = /*locale*/ ctx[3].shapeIconInputCancel;
  27557. if (dirty[0] & /*locale*/ 8) inputform_changes.labelConfirm = /*locale*/ ctx[3].shapeLabelInputConfirm;
  27558. if (dirty[0] & /*locale*/ 8) inputform_changes.iconConfirm = /*locale*/ ctx[3].shapeIconInputConfirm;
  27559. if (dirty[0] & /*markupTextInputStyle, textInput, textInputText*/ 100352 | dirty[5] & /*$$scope*/ 67108864) {
  27560. inputform_changes.$$scope = { dirty, ctx };
  27561. }
  27562. inputform.$set(inputform_changes);
  27563. },
  27564. i(local) {
  27565. if (current) return;
  27566. transition_in(inputform.$$.fragment, local);
  27567. current = true;
  27568. },
  27569. o(local) {
  27570. transition_out(inputform.$$.fragment, local);
  27571. current = false;
  27572. },
  27573. d(detaching) {
  27574. destroy_component(inputform, detaching);
  27575. }
  27576. };
  27577. }
  27578. // (2660:8) <InputForm panelOffset={offset} onconfirm={handleTextConfirm} oncancel={handleTextCancel} labelCancel={locale.shapeLabelInputCancel} iconCancel={locale.shapeIconInputCancel} labelConfirm={locale.shapeLabelInputConfirm} iconConfirm={locale.shapeIconInputConfirm} >
  27579. function create_default_slot$6(ctx) {
  27580. let textarea;
  27581. let mounted;
  27582. let dispose;
  27583. return {
  27584. c() {
  27585. textarea = element("textarea");
  27586. attr(textarea, "style", /*markupTextInputStyle*/ ctx[16]);
  27587. attr(textarea, "spellcheck", "false");
  27588. attr(textarea, "autocorrect", "off");
  27589. attr(textarea, "autocapitalize", "off");
  27590. },
  27591. m(target, anchor) {
  27592. insert(target, textarea, anchor);
  27593. /*textarea_binding*/ ctx[125](textarea);
  27594. set_input_value(textarea, /*textInputText*/ ctx[15]);
  27595. if (!mounted) {
  27596. dispose = [
  27597. listen(textarea, "keydown", /*handleTextInputKeyDown*/ ctx[34]),
  27598. listen(textarea, "keypress", /*handleTextInputAttempt*/ ctx[33]),
  27599. listen(textarea, "keyup", /*handleTextInputKeyUp*/ ctx[35]),
  27600. listen(textarea, "input", /*handleTextInput*/ ctx[32]),
  27601. listen(textarea, "input", /*textarea_input_handler*/ ctx[126])
  27602. ];
  27603. mounted = true;
  27604. }
  27605. },
  27606. p(ctx, dirty) {
  27607. if (dirty[0] & /*markupTextInputStyle*/ 65536) {
  27608. attr(textarea, "style", /*markupTextInputStyle*/ ctx[16]);
  27609. }
  27610. if (dirty[0] & /*textInputText*/ 32768) {
  27611. set_input_value(textarea, /*textInputText*/ ctx[15]);
  27612. }
  27613. },
  27614. d(detaching) {
  27615. if (detaching) detach(textarea);
  27616. /*textarea_binding*/ ctx[125](null);
  27617. mounted = false;
  27618. run_all(dispose);
  27619. }
  27620. };
  27621. }
  27622. // (2684:4) {#if $markupControlsOpacity > 0}
  27623. function create_if_block$2(ctx) {
  27624. let div;
  27625. let dynamiccomponenttree;
  27626. let current;
  27627. let mounted;
  27628. let dispose;
  27629. dynamiccomponenttree = new DynamicComponentTree_1({
  27630. props: { items: /*shapeControls*/ ctx[18] }
  27631. });
  27632. return {
  27633. c() {
  27634. div = element("div");
  27635. create_component(dynamiccomponenttree.$$.fragment);
  27636. attr(div, "class", "PinturaShapeControls");
  27637. attr(div, "style", /*markupControlsStyle*/ ctx[17]);
  27638. },
  27639. m(target, anchor) {
  27640. insert(target, div, anchor);
  27641. mount_component(dynamiccomponenttree, div, null);
  27642. current = true;
  27643. if (!mounted) {
  27644. dispose = [
  27645. listen(div, "measure", /*measure_handler_1*/ ctx[127]),
  27646. action_destroyer(measurable.call(null, div))
  27647. ];
  27648. mounted = true;
  27649. }
  27650. },
  27651. p(ctx, dirty) {
  27652. const dynamiccomponenttree_changes = {};
  27653. if (dirty[0] & /*shapeControls*/ 262144) dynamiccomponenttree_changes.items = /*shapeControls*/ ctx[18];
  27654. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  27655. if (!current || dirty[0] & /*markupControlsStyle*/ 131072) {
  27656. attr(div, "style", /*markupControlsStyle*/ ctx[17]);
  27657. }
  27658. },
  27659. i(local) {
  27660. if (current) return;
  27661. transition_in(dynamiccomponenttree.$$.fragment, local);
  27662. current = true;
  27663. },
  27664. o(local) {
  27665. transition_out(dynamiccomponenttree.$$.fragment, local);
  27666. current = false;
  27667. },
  27668. d(detaching) {
  27669. if (detaching) detach(div);
  27670. destroy_component(dynamiccomponenttree);
  27671. mounted = false;
  27672. run_all(dispose);
  27673. }
  27674. };
  27675. }
  27676. function create_fragment$f(ctx) {
  27677. let div;
  27678. let nav;
  27679. let ul;
  27680. let each_blocks = [];
  27681. let each_1_lookup = new Map();
  27682. let t0;
  27683. let t1;
  27684. let t2;
  27685. let interactable_action;
  27686. let current;
  27687. let mounted;
  27688. let dispose;
  27689. let each_value = /*shapeNavList*/ ctx[19];
  27690. const get_key = ctx => /*item*/ ctx[178].id;
  27691. for (let i = 0; i < each_value.length; i += 1) {
  27692. let child_ctx = get_each_context$3(ctx, each_value, i);
  27693. let key = get_key(child_ctx);
  27694. each_1_lookup.set(key, each_blocks[i] = create_each_block$3(key, child_ctx));
  27695. }
  27696. let if_block0 = /*shouldRenderShapeManipulator*/ ctx[7] && create_if_block_2$2(ctx);
  27697. let if_block1 = /*shouldRenderTextInput*/ ctx[9] && create_if_block_1$2(ctx);
  27698. let if_block2 = /*$markupControlsOpacity*/ ctx[10] > 0 && create_if_block$2(ctx);
  27699. return {
  27700. c() {
  27701. div = element("div");
  27702. nav = element("nav");
  27703. ul = element("ul");
  27704. for (let i = 0; i < each_blocks.length; i += 1) {
  27705. each_blocks[i].c();
  27706. }
  27707. t0 = space();
  27708. if (if_block0) if_block0.c();
  27709. t1 = space();
  27710. if (if_block1) if_block1.c();
  27711. t2 = space();
  27712. if (if_block2) if_block2.c();
  27713. attr(nav, "class", "PinturaShapeList");
  27714. attr(nav, "data-visible", /*showShapeList*/ ctx[12]);
  27715. attr(div, "class", "PinturaShapeEditor");
  27716. attr(div, "tabindex", "0");
  27717. },
  27718. m(target, anchor) {
  27719. insert(target, div, anchor);
  27720. append(div, nav);
  27721. append(nav, ul);
  27722. for (let i = 0; i < each_blocks.length; i += 1) {
  27723. each_blocks[i].m(ul, null);
  27724. }
  27725. append(div, t0);
  27726. if (if_block0) if_block0.m(div, null);
  27727. append(div, t1);
  27728. if (if_block1) if_block1.m(div, null);
  27729. append(div, t2);
  27730. if (if_block2) if_block2.m(div, null);
  27731. current = true;
  27732. if (!mounted) {
  27733. dispose = [
  27734. listen(nav, "focusin", /*handleFocusIn*/ ctx[40]),
  27735. listen(nav, "focusout", /*handleFocusOut*/ ctx[41]),
  27736. listen(div, "keydown", /*handleKey*/ ctx[31]),
  27737. listen(div, "nudge", /*handleNudge*/ ctx[39]),
  27738. listen(div, "measure", /*measure_handler*/ ctx[123]),
  27739. action_destroyer(measurable.call(null, div)),
  27740. action_destroyer(nudgeable.call(null, div)),
  27741. listen(div, "interactionstart", /*handleInteractionStart*/ ctx[21]),
  27742. listen(div, "interactionupdate", /*handleInteractionUpdate*/ ctx[22]),
  27743. listen(div, "interactionrelease", /*handleInteractionRelease*/ ctx[23]),
  27744. listen(div, "interactionend", /*handleInteractionEnd*/ ctx[24]),
  27745. action_destroyer(interactable_action = interactable.call(null, div, {
  27746. drag: true,
  27747. pinch: true,
  27748. inertia: true,
  27749. matchTarget: true,
  27750. getEventPosition: /*interactable_function*/ ctx[128]
  27751. }))
  27752. ];
  27753. mounted = true;
  27754. }
  27755. },
  27756. p(ctx, dirty) {
  27757. if (dirty[0] & /*shapeNavList, selectShape, markup*/ 524305) {
  27758. each_value = /*shapeNavList*/ ctx[19];
  27759. group_outros();
  27760. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, ul, outro_and_destroy_block, create_each_block$3, null, get_each_context$3);
  27761. check_outros();
  27762. }
  27763. if (!current || dirty[0] & /*showShapeList*/ 4096) {
  27764. attr(nav, "data-visible", /*showShapeList*/ ctx[12]);
  27765. }
  27766. if (/*shouldRenderShapeManipulator*/ ctx[7]) {
  27767. if (if_block0) {
  27768. if_block0.p(ctx, dirty);
  27769. if (dirty[0] & /*shouldRenderShapeManipulator*/ 128) {
  27770. transition_in(if_block0, 1);
  27771. }
  27772. } else {
  27773. if_block0 = create_if_block_2$2(ctx);
  27774. if_block0.c();
  27775. transition_in(if_block0, 1);
  27776. if_block0.m(div, t1);
  27777. }
  27778. } else if (if_block0) {
  27779. group_outros();
  27780. transition_out(if_block0, 1, 1, () => {
  27781. if_block0 = null;
  27782. });
  27783. check_outros();
  27784. }
  27785. if (/*shouldRenderTextInput*/ ctx[9]) {
  27786. if (if_block1) {
  27787. if_block1.p(ctx, dirty);
  27788. if (dirty[0] & /*shouldRenderTextInput*/ 512) {
  27789. transition_in(if_block1, 1);
  27790. }
  27791. } else {
  27792. if_block1 = create_if_block_1$2(ctx);
  27793. if_block1.c();
  27794. transition_in(if_block1, 1);
  27795. if_block1.m(div, t2);
  27796. }
  27797. } else if (if_block1) {
  27798. group_outros();
  27799. transition_out(if_block1, 1, 1, () => {
  27800. if_block1 = null;
  27801. });
  27802. check_outros();
  27803. }
  27804. if (/*$markupControlsOpacity*/ ctx[10] > 0) {
  27805. if (if_block2) {
  27806. if_block2.p(ctx, dirty);
  27807. if (dirty[0] & /*$markupControlsOpacity*/ 1024) {
  27808. transition_in(if_block2, 1);
  27809. }
  27810. } else {
  27811. if_block2 = create_if_block$2(ctx);
  27812. if_block2.c();
  27813. transition_in(if_block2, 1);
  27814. if_block2.m(div, null);
  27815. }
  27816. } else if (if_block2) {
  27817. group_outros();
  27818. transition_out(if_block2, 1, 1, () => {
  27819. if_block2 = null;
  27820. });
  27821. check_outros();
  27822. }
  27823. if (interactable_action && is_function(interactable_action.update) && dirty[0] & /*rootRect*/ 4) interactable_action.update.call(null, {
  27824. drag: true,
  27825. pinch: true,
  27826. inertia: true,
  27827. matchTarget: true,
  27828. getEventPosition: /*interactable_function*/ ctx[128]
  27829. });
  27830. },
  27831. i(local) {
  27832. if (current) return;
  27833. for (let i = 0; i < each_value.length; i += 1) {
  27834. transition_in(each_blocks[i]);
  27835. }
  27836. transition_in(if_block0);
  27837. transition_in(if_block1);
  27838. transition_in(if_block2);
  27839. current = true;
  27840. },
  27841. o(local) {
  27842. for (let i = 0; i < each_blocks.length; i += 1) {
  27843. transition_out(each_blocks[i]);
  27844. }
  27845. transition_out(if_block0);
  27846. transition_out(if_block1);
  27847. transition_out(if_block2);
  27848. current = false;
  27849. },
  27850. d(detaching) {
  27851. if (detaching) detach(div);
  27852. for (let i = 0; i < each_blocks.length; i += 1) {
  27853. each_blocks[i].d();
  27854. }
  27855. if (if_block0) if_block0.d();
  27856. if (if_block1) if_block1.d();
  27857. if (if_block2) if_block2.d();
  27858. mounted = false;
  27859. run_all(dispose);
  27860. }
  27861. };
  27862. }
  27863. const ROTATION_CONTROL_OFFSET = 20;
  27864. const MIN_TEXT_MARKUP_WIDTH = 10;
  27865. const shapeControlDist = 16;
  27866. function instance$f($$self, $$props, $$invalidate) {
  27867. let activeMarkup;
  27868. let activeShapeId;
  27869. let activeMarkupComputed;
  27870. let activeMarkupItemIsDraft;
  27871. let shapeProps;
  27872. let shapeActivePoints;
  27873. let allowResizeControls;
  27874. let allowRotateControls;
  27875. let allowedResizeControls;
  27876. let shouldRenderShapeManipulator;
  27877. let shapeActiveScreenPoints;
  27878. let shapeManipulatorPoints;
  27879. let shapeManipulatorRotationPoint;
  27880. let shapeManipulatorRotationPointPosition;
  27881. let isTextMarkupSelected;
  27882. let shouldRenderTextInput;
  27883. let textShapeOrigin;
  27884. let textShapeDisplayOrigin;
  27885. let textSizeDisplayOrigin;
  27886. let textRectDisplayOrigin;
  27887. let textInputText;
  27888. let markupTextInputStyle;
  27889. let controlledMarkupItem;
  27890. let allowShapeFlip;
  27891. let allowShapeChangeTextLayout;
  27892. let allowShapeDuplicate;
  27893. let allowShapeRemove;
  27894. let allowShapeReorder;
  27895. let allowShapeInput;
  27896. let allowShapeAdjustOpacity;
  27897. let markupControlsAnchorPosition;
  27898. let shapeControlsPosition;
  27899. let markupControlsStyle;
  27900. let shapeControls;
  27901. let shapeNavList;
  27902. let $keysPressedStored;
  27903. let $markupControlsOpacity;
  27904. let { uid = getUniqueId() } = $$props; // used to control manipulator lines
  27905. let { ui } = $$props;
  27906. let { markup } = $$props;
  27907. let { offset } = $$props;
  27908. let { contextRotation = 0 } = $$props;
  27909. let { contextFlipX = false } = $$props;
  27910. let { contextFlipY = false } = $$props;
  27911. let { contextScale } = $$props;
  27912. let { active = false } = $$props;
  27913. let { opacity = 1 } = $$props;
  27914. let { parentRect } = $$props;
  27915. let { rootRect } = $$props;
  27916. let { utilRect } = $$props;
  27917. let { oninteractionstart = noop$1 } = $$props;
  27918. let { oninteractionupdate = noop$1 } = $$props;
  27919. let { oninteractionrelease = noop$1 } = $$props;
  27920. let { oninteractionend = noop$1 } = $$props;
  27921. let { onaddshape = noop$1 } = $$props;
  27922. let { onupdateshape = noop$1 } = $$props;
  27923. let { onselectshape = noop$1 } = $$props;
  27924. let { onremoveshape = noop$1 } = $$props;
  27925. let { beforeSelectShape = () => true } = $$props;
  27926. let { beforeDeselectShape = () => true } = $$props;
  27927. let { beforeRemoveShape = () => true } = $$props;
  27928. let { beforeUpdateShape = (shape, props) => props } = $$props;
  27929. let { willRenderShapeControls = passthrough } = $$props;
  27930. let { mapEditorPointToImagePoint } = $$props;
  27931. let { mapImagePointToEditorPoint } = $$props;
  27932. let { eraseRadius = undefined } = $$props;
  27933. let { selectRadius = undefined } = $$props;
  27934. let { enableButtonFlipVertical = false } = $$props;
  27935. let { enableTapToAddText = true } = $$props;
  27936. let { locale } = $$props;
  27937. //
  27938. // Cache
  27939. //
  27940. const updateShape = (shape, props, parentRect) => {
  27941. let propsToUpdate = beforeUpdateShape({ ...shape }, props, { ...parentRect });
  27942. shapeUpdateProps(shape, propsToUpdate, parentRect);
  27943. };
  27944. //
  27945. // Helpers
  27946. //
  27947. const circleOverlapsWithLine = (point, radius, from, to) => {
  27948. const ac = vectorCreate(point.x - from.x, point.y - from.y);
  27949. const ab = vectorCreate(to.x - from.x, to.y - from.y);
  27950. const ab2 = vectorDot(ab, ab);
  27951. const acab = vectorDot(ac, ab);
  27952. let t = acab / ab2;
  27953. t = t < 0 ? 0 : t;
  27954. t = t > 1 ? 1 : t;
  27955. const h = vectorCreate(ab.x * t + from.x - point.x, ab.y * t + from.y - point.y);
  27956. const h2 = vectorDot(h, h);
  27957. return h2 <= radius * radius;
  27958. };
  27959. const circleOverlapsWithPath = (position, radius, points) => {
  27960. const l = points.length;
  27961. for (let i = 0; i < l - 1; i++) {
  27962. if (circleOverlapsWithLine(position, radius, points[i], points[i + 1])) return true;
  27963. }
  27964. return false;
  27965. };
  27966. const circleOverlapsWithPolygon = (position, radius, points) => {
  27967. // if center is in polygon
  27968. if (pointInPoly(position, points)) return true;
  27969. if (circleOverlapsWithPath(position, radius, points)) return true;
  27970. return circleOverlapsWithLine(position, radius, points[0], points[points.length - 1]);
  27971. };
  27972. const circleOverlapsWithEllipse = (position, radius, ellipse, rotation, flipX, flipY) => {
  27973. const points = ellipseToPolygon(vectorCreate(ellipse.x, ellipse.y), ellipse.rx, ellipse.ry, rotation, flipX, flipY, 12);
  27974. return circleOverlapsWithPolygon(position, radius, points);
  27975. };
  27976. const circleOverlapsWithRect = (position, radius, rect, rotation, pivot) => circleOverlapsWithPolygon(position, radius, rectRotate(rect, rotation, pivot || rectCenter(rect)));
  27977. const shapeToPoly = (computedShape, resolution = 12) => {
  27978. if (shapeIsRect(computedShape)) {
  27979. return rectRotate(computedShape, computedShape.rotation, rectCenter(computedShape));
  27980. } else if (shapeIsText(computedShape)) {
  27981. const computedRect = getMarkupShapeRect(computedShape);
  27982. return rectRotate(computedRect, computedShape.rotation, rectCenter(computedRect));
  27983. } else if (shapeIsEllipse(computedShape)) {
  27984. return ellipseToPolygon(vectorCreate(computedShape.x, computedShape.y), computedShape.rx, computedShape.ry, computedShape.rotation, computedShape.flipX, computedShape.flipY, resolution);
  27985. }
  27986. return [];
  27987. };
  27988. //
  27989. // Shape creator
  27990. //
  27991. const keysPressedStored = getContext("keysPressed");
  27992. component_subscribe($$self, keysPressedStored, value => $$invalidate(137, $keysPressedStored = value));
  27993. const getShapeUpdateRotation = (rotation, flipX, flipY) => {
  27994. if (rotation === 0) return rotation;
  27995. if (flipX && flipY) return rotation;
  27996. if (flipX) return -rotation;
  27997. if (flipY) return -rotation;
  27998. return rotation;
  27999. };
  28000. const createShape = (shapeDefault, options = {}) => {
  28001. // state
  28002. let interactionOrigin;
  28003. let interactionRadius;
  28004. let interactionPosition;
  28005. let isEllipse = shapeIsEllipse(shapeDefault);
  28006. let isText = shapeIsText(shapeDefault);
  28007. let isRelative = options.position === "relative";
  28008. if (shapeIsPath(shapeDefault)) {
  28009. return {
  28010. start: e => {
  28011. const { origin } = e.detail;
  28012. interactionRadius = 4;
  28013. interactionOrigin = vectorClone(origin);
  28014. interactionPosition = vectorClone(origin);
  28015. const originPoint = mapEditorPointToImagePoint(origin);
  28016. if (isRelative) {
  28017. originPoint.x = isRelative
  28018. ? toPercentage(originPoint.x, parentRect.width)
  28019. : originPoint.x;
  28020. originPoint.y = isRelative
  28021. ? toPercentage(originPoint.y, parentRect.height)
  28022. : originPoint.y;
  28023. }
  28024. // add to markup so it's drawn
  28025. addMarkupItemDraft({ ...shapeDefault, points: [originPoint] });
  28026. },
  28027. update: e => {
  28028. const draft = getMarkupItemDraft();
  28029. const { translation } = e.detail;
  28030. // position
  28031. const pointerPosition = vectorCreate(interactionOrigin.x + translation.x, interactionOrigin.y + translation.y);
  28032. // distance between interaction and pointer if it's too close, we don't draw this point
  28033. const dist = vectorDistance(interactionPosition, pointerPosition);
  28034. if (fixPrecision(dist, 5) <= interactionRadius) return;
  28035. // get angle between interaction and pointer
  28036. const angle = vectorAngleBetween(pointerPosition, interactionPosition);
  28037. // move brush towards pointer at angle
  28038. const moveDist = interactionRadius - dist;
  28039. interactionPosition.x += moveDist * Math.cos(angle);
  28040. interactionPosition.y += moveDist * Math.sin(angle);
  28041. // create point
  28042. const point = mapEditorPointToImagePoint(interactionPosition);
  28043. if (point) {
  28044. point.x = isRelative
  28045. ? toPercentage(point.x, parentRect.width)
  28046. : point.x;
  28047. point.y = isRelative
  28048. ? toPercentage(point.y, parentRect.height)
  28049. : point.y;
  28050. }
  28051. draft.points = draft.points.concat(point);
  28052. syncShapes();
  28053. },
  28054. release: e => e.detail.preventInertia(),
  28055. end: e => {
  28056. if (e.detail.isTap) return discardMarkupItemDraft();
  28057. const shape = confirmMarkupItemDraft();
  28058. onaddshape(shape);
  28059. }
  28060. };
  28061. } else if (isEllipse || isText || shapeIsRect(shapeDefault)) {
  28062. return {
  28063. start: e => {
  28064. const { origin } = e.detail;
  28065. // need to remember origin so we can correctly apply interaction translation
  28066. interactionOrigin = vectorClone(origin);
  28067. const mappedOriginPosition = mapEditorPointToImagePoint(interactionOrigin);
  28068. // add to markup so it's drawn
  28069. const draft = {
  28070. ...shapeDefault,
  28071. rotation: -1 * getShapeUpdateRotation(contextRotation, contextFlipX, contextFlipY),
  28072. x: isRelative
  28073. ? toPercentage(mappedOriginPosition.x, parentRect.width)
  28074. : mappedOriginPosition.x,
  28075. y: isRelative
  28076. ? toPercentage(mappedOriginPosition.y, parentRect.height)
  28077. : mappedOriginPosition.y
  28078. };
  28079. // de-flip shape
  28080. draft.flipX = contextFlipX;
  28081. draft.flipY = contextFlipY;
  28082. // remove position
  28083. delete draft.position;
  28084. // hide initially
  28085. draft.opacity = 0;
  28086. //
  28087. if (isEllipse) {
  28088. draft.rx = isRelative ? toPercentage(0) : 0;
  28089. draft.ry = isRelative ? toPercentage(0) : 0;
  28090. } else {
  28091. draft.width = isRelative ? toPercentage(0) : 0;
  28092. draft.height = isRelative ? toPercentage(0) : 0;
  28093. }
  28094. addMarkupItemDraft(draft);
  28095. },
  28096. update: e => {
  28097. const draft = getMarkupItemDraft();
  28098. draft.opacity = 1;
  28099. const { aspectRatio } = draft;
  28100. let { translation } = e.detail;
  28101. // limit to aspect ratio
  28102. if (aspectRatio) {
  28103. const t = Math.abs(translation.x) * aspectRatio;
  28104. translation.x = translation.x;
  28105. translation.y = t * Math.sign(translation.y);
  28106. }
  28107. // position
  28108. const pointerPosition = vectorCreate(interactionOrigin.x + translation.x, interactionOrigin.y + translation.y);
  28109. const mappedOriginPosition = mapEditorPointToImagePoint(interactionOrigin);
  28110. const mappedPointerPosition = mapEditorPointToImagePoint(pointerPosition);
  28111. const pivot = {
  28112. x: mappedOriginPosition.x + (mappedPointerPosition.x - mappedOriginPosition.x) * 0.5,
  28113. y: mappedOriginPosition.y + (mappedPointerPosition.y - mappedOriginPosition.y) * 0.5
  28114. };
  28115. const rotation = getShapeUpdateRotation(contextRotation, contextFlipX, contextFlipY);
  28116. vectorRotate(mappedOriginPosition, rotation, pivot);
  28117. vectorRotate(mappedPointerPosition, rotation, pivot);
  28118. const l = Math.min(mappedOriginPosition.x, mappedPointerPosition.x);
  28119. const t = Math.min(mappedOriginPosition.y, mappedPointerPosition.y);
  28120. const r = Math.max(mappedOriginPosition.x, mappedPointerPosition.x);
  28121. const b = Math.max(mappedOriginPosition.y, mappedPointerPosition.y);
  28122. let width = r - l;
  28123. let height = b - t;
  28124. let props = {};
  28125. if (isEllipse) {
  28126. props.x = l + width * 0.5;
  28127. props.y = t + height * 0.5;
  28128. props.rx = width * 0.5;
  28129. props.ry = height * 0.5;
  28130. } else {
  28131. props.x = l;
  28132. props.y = t;
  28133. props.width = width;
  28134. props.height = height;
  28135. }
  28136. updateShape(draft, props, parentRect);
  28137. syncShapes();
  28138. },
  28139. release: e => {
  28140. e.detail.preventInertia();
  28141. },
  28142. end: e => {
  28143. const draft = getMarkupItemDraft();
  28144. if (e.detail.isTap) {
  28145. // will cancel if is not text shape
  28146. if (!shapeIsText(draft) || !enableTapToAddText || interactionTarget) return discardMarkupItemDraft();
  28147. // will add 'auto' text shape if not targetting other shape
  28148. delete draft.width;
  28149. delete draft.height;
  28150. delete draft.textAlign;
  28151. // position the shape correctly
  28152. const draftComputedShape = shapeComputeDisplay({ ...draft }, parentRect);
  28153. const size = textSize(draft.text, draftComputedShape);
  28154. size.width *= contextScale;
  28155. size.height *= contextScale;
  28156. const mappedOriginPosition = mapEditorPointToImagePoint({
  28157. x: interactionOrigin.x,
  28158. y: interactionOrigin.y - size.height * 0.5
  28159. });
  28160. const mappedPointerPosition = mapEditorPointToImagePoint({
  28161. x: interactionOrigin.x + size.width,
  28162. y: interactionOrigin.y + size.height * 0.5
  28163. });
  28164. const pivot = {
  28165. x: mappedOriginPosition.x + (mappedPointerPosition.x - mappedOriginPosition.x) * 0.5,
  28166. y: mappedOriginPosition.y + (mappedPointerPosition.y - mappedOriginPosition.y) * 0.5
  28167. };
  28168. const rotation = getShapeUpdateRotation(contextRotation, contextFlipX, contextFlipY);
  28169. vectorRotate(mappedOriginPosition, rotation, pivot);
  28170. vectorRotate(mappedPointerPosition, rotation, pivot);
  28171. const l = Math.min(mappedOriginPosition.x, mappedPointerPosition.x);
  28172. const t = Math.min(mappedOriginPosition.y, mappedPointerPosition.y);
  28173. draft.x = isString(draft.x)
  28174. ? toPercentage(l, parentRect.width)
  28175. : l;
  28176. draft.y = isString(draft.y)
  28177. ? toPercentage(t, parentRect.height)
  28178. : t;
  28179. }
  28180. // reveal
  28181. draft.opacity = 1;
  28182. // finish markup
  28183. if (!shapeIsText(draft)) {
  28184. const shape = confirmMarkupItemDraft();
  28185. onaddshape(shape);
  28186. }
  28187. // select the draft
  28188. selectShape(draft);
  28189. // also enable editing the text
  28190. if (shapeIsText(draft)) editMarkupItem(draft);
  28191. }
  28192. };
  28193. } else if (shapeIsLine(shapeDefault)) {
  28194. return {
  28195. start: e => {
  28196. const { origin } = e.detail;
  28197. const originMapped = mapEditorPointToImagePoint(origin);
  28198. const originSnapped = vectorApply(originMapped, snapToPixel);
  28199. interactionOrigin = vectorClone(origin);
  28200. // add to markup so it's drawn
  28201. addMarkupItemDraft({
  28202. ...shapeDefault,
  28203. x1: isRelative
  28204. ? toPercentage(originSnapped.x, parentRect.width)
  28205. : originSnapped.x,
  28206. y1: isRelative
  28207. ? toPercentage(originSnapped.y, parentRect.height)
  28208. : originSnapped.y,
  28209. x2: isRelative
  28210. ? toPercentage(originSnapped.x, parentRect.width)
  28211. : originSnapped.x,
  28212. y2: isRelative
  28213. ? toPercentage(originSnapped.y, parentRect.height)
  28214. : originSnapped.y,
  28215. opacity: 0
  28216. });
  28217. },
  28218. update: e => {
  28219. const draft = getMarkupItemDraft();
  28220. const { translation } = e.detail;
  28221. const interactionTarget = vectorAdd(vectorClone(interactionOrigin), translation);
  28222. // shift pressed
  28223. if ($keysPressedStored.includes(16)) {
  28224. const length = vectorDistance(interactionOrigin, interactionTarget);
  28225. const angle = vectorAngleBetween(interactionOrigin, interactionTarget);
  28226. const angleSnapInterval = Math.PI / 4;
  28227. const angleSnapped = angleSnapInterval * Math.round(angle / angleSnapInterval);
  28228. interactionTarget.x = interactionOrigin.x + length * Math.cos(angleSnapped);
  28229. interactionTarget.y = interactionOrigin.y + length * Math.sin(angleSnapped);
  28230. }
  28231. // update line end position
  28232. const point = mapEditorPointToImagePoint(interactionTarget);
  28233. updateMarkupShape(draft, {
  28234. x2: isRelative
  28235. ? toPercentage(point.x, parentRect.width)
  28236. : point.x,
  28237. y2: isRelative
  28238. ? toPercentage(point.y, parentRect.height)
  28239. : point.y,
  28240. opacity: 1
  28241. });
  28242. syncShapes();
  28243. },
  28244. release: e => e.detail.preventInertia(),
  28245. end: e => {
  28246. const draft = getMarkupItemDraft();
  28247. if (e.detail.isTap) return discardMarkupItemDraft();
  28248. draft.opacity = 1;
  28249. // finish markup
  28250. const shape = confirmMarkupItemDraft();
  28251. onaddshape(shape);
  28252. // select the draft
  28253. selectShape(shape);
  28254. }
  28255. };
  28256. }
  28257. };
  28258. const eraseShape = () => {
  28259. let origin;
  28260. let positionPrevious;
  28261. return {
  28262. start: e => {
  28263. origin = e.detail.origin;
  28264. positionPrevious = origin;
  28265. },
  28266. update: e => {
  28267. const { translation } = e.detail;
  28268. const positionCurrent = vectorCreate(origin.x + translation.x, origin.y + translation.y);
  28269. const shapesThatCanBeErased = markup.filter(shape => !shape.disableErase);
  28270. const shapesFound = getShapesBetweenPoints(shapesThatCanBeErased, mapEditorPointToImagePoint(positionPrevious), mapEditorPointToImagePoint(positionCurrent), eraseRadius);
  28271. const shapesRemoved = removeMarkupItems(shapesFound);
  28272. shapesRemoved.forEach(onremoveshape);
  28273. positionPrevious = vectorClone(positionCurrent);
  28274. },
  28275. release: e => e.detail.preventInertia(),
  28276. end: () => {
  28277. }
  28278. };
  28279. };
  28280. //
  28281. // Mapping coordinates
  28282. //
  28283. const getImagePointWithScreenTranslation = (point, translation) => {
  28284. const pointInScreenSpace = mapImagePointToEditorPoint(point);
  28285. return mapEditorPointToImagePoint(vectorAdd(pointInScreenSpace, translation));
  28286. };
  28287. //
  28288. // Interaction
  28289. //
  28290. // image zoom
  28291. // const handleWheel = (e) => {
  28292. // TODO: ZOOM image
  28293. // }
  28294. // image pan
  28295. // const handleImagePan = (e) => {
  28296. // TODO: PAN image
  28297. // }
  28298. //
  28299. // markup manipulate
  28300. //
  28301. const translateShape = (shapeCurrent, shapeOriginComputed, translation) => {
  28302. if (shapeIsLine(shapeCurrent)) {
  28303. const beginImageOffset = getImagePointWithScreenTranslation(shapeLineGetStartPoint(shapeOriginComputed), translation);
  28304. const endImageOffset = getImagePointWithScreenTranslation(shapeLineGetEndPoint(shapeOriginComputed), translation);
  28305. updateShape(
  28306. shapeCurrent,
  28307. {
  28308. x1: beginImageOffset.x,
  28309. y1: beginImageOffset.y,
  28310. x2: endImageOffset.x,
  28311. y2: endImageOffset.y
  28312. },
  28313. parentRect
  28314. );
  28315. } else if (shapeIsRect(shapeCurrent) || shapeIsText(shapeCurrent) || shapeIsEllipse(shapeCurrent)) {
  28316. const imagePoint = getImagePointWithScreenTranslation(shapeOriginComputed, translation);
  28317. updateShape(shapeCurrent, imagePoint, parentRect);
  28318. }
  28319. syncShapes();
  28320. };
  28321. const IndexFlipXMap = { 0: 1, 1: 0, 2: 3, 3: 2 };
  28322. const IndexFlipYMap = { 0: 3, 1: 2, 2: 1, 3: 0 };
  28323. const resizeMarkup = (shapeCurrent, shapeOriginComputed, indexes, translation, options) => {
  28324. if (shapeIsLine(shapeCurrent)) {
  28325. const [targetIndex] = indexes;
  28326. const snap = $keysPressedStored.includes(16)
  28327. ? (origin, target) => {
  28328. const length = vectorDistance(origin, target);
  28329. const angle = vectorAngleBetween(origin, target);
  28330. const angleSnapInterval = Math.PI / 4;
  28331. const angleSnapped = angleSnapInterval * Math.round(angle / angleSnapInterval) - contextRotation % angleSnapInterval;
  28332. target.x = origin.x + length * Math.cos(angleSnapped);
  28333. target.y = origin.y + length * Math.sin(angleSnapped);
  28334. }
  28335. : (origin, target) => target;
  28336. if (targetIndex === 0) {
  28337. const point = getImagePointWithScreenTranslation(shapeLineGetStartPoint(shapeOriginComputed), translation);
  28338. snap(vectorCreate(shapeOriginComputed.x2, shapeOriginComputed.y2), point);
  28339. updateShape(shapeCurrent, { x1: point.x, y1: point.y }, parentRect);
  28340. } else if (targetIndex === 1) {
  28341. const point = getImagePointWithScreenTranslation(shapeLineGetEndPoint(shapeOriginComputed), translation);
  28342. snap(vectorCreate(shapeOriginComputed.x1, shapeOriginComputed.y1), point);
  28343. updateShape(shapeCurrent, { x2: point.x, y2: point.y }, parentRect);
  28344. }
  28345. } else if (shapeHasSize(shapeCurrent) || shapeIsEllipse(shapeCurrent) || shapeIsTextBox(shapeCurrent)) {
  28346. let hasAutoHeight = false;
  28347. let shapeOriginRect;
  28348. if (shapeIsEllipse(shapeCurrent)) {
  28349. shapeOriginRect = rectCreateFromEllipse(shapeOriginComputed);
  28350. } else if (shapeHasSize(shapeCurrent)) {
  28351. shapeOriginRect = rectCreateFromAny(shapeOriginComputed);
  28352. } else {
  28353. // is text with 'width' only
  28354. hasAutoHeight = true;
  28355. shapeOriginRect = rectCreateFromAny(shapeOriginComputed);
  28356. const size = textSize(shapeOriginComputed.text, shapeOriginComputed);
  28357. shapeOriginRect.height = size.height;
  28358. }
  28359. let shapeAspectRatio;
  28360. if (shapeCurrent.aspectRatio) {
  28361. shapeAspectRatio = shapeCurrent.aspectRatio;
  28362. } else if (options.shiftKey && !hasAutoHeight) {
  28363. shapeAspectRatio = shapeOriginRect.width / shapeOriginRect.height;
  28364. }
  28365. // current shape
  28366. const rectAligned = rectCreateFromAny(shapeOriginRect);
  28367. const rectAlignedCenterPosition = rectCenter(rectAligned);
  28368. const rectRotation = shapeCurrent.rotation;
  28369. const rectAlignedCorners = rectGetCorners(rectAligned);
  28370. const rectCorners = rectRotate(rectAligned, rectRotation);
  28371. // is translating one corner
  28372. if (indexes.length === 1) {
  28373. // corner
  28374. let cornerIndex = indexes[0];
  28375. if (shapeCurrent.flipX) cornerIndex = IndexFlipXMap[cornerIndex];
  28376. if (shapeCurrent.flipY) cornerIndex = IndexFlipYMap[cornerIndex];
  28377. const [tl, tr, br, bl] = rectAlignedCorners;
  28378. const screenTargetPosition = mapImagePointToEditorPoint(rectCorners[cornerIndex]);
  28379. vectorAdd(screenTargetPosition, translation);
  28380. const imageTargetPosition = mapEditorPointToImagePoint(screenTargetPosition);
  28381. const imageTargetTranslation = vectorCreate(imageTargetPosition.x - rectCorners[cornerIndex].x, imageTargetPosition.y - rectCorners[cornerIndex].y);
  28382. // if (shapeCurrent.flipX) imageTargetTranslation.x = -imageTargetTranslation.x;
  28383. // if (shapeCurrent.flipY) imageTargetTranslation.y = -imageTargetTranslation.y;
  28384. const imageTargetTranslationAligned = vectorRotate(vectorClone(imageTargetTranslation), -rectRotation);
  28385. const imageTargetPositionAligned = vectorCreate(rectAlignedCorners[cornerIndex].x + imageTargetTranslationAligned.x, rectAlignedCorners[cornerIndex].y + imageTargetTranslationAligned.y);
  28386. let anchor;
  28387. if (cornerIndex === 0) anchor = br;
  28388. if (cornerIndex === 1) anchor = bl;
  28389. if (cornerIndex === 2) anchor = tl;
  28390. if (cornerIndex === 3) anchor = tr;
  28391. // create an aligned and updated rectangle
  28392. const rectAlignedResized = rectCreateFromPoints(anchor, imageTargetPositionAligned);
  28393. // limit rect
  28394. if (shapeAspectRatio) {
  28395. // get size that adheres to aspect ratio but still fits current rectangle
  28396. const { width, height } = rectContainRect(rectAlignedResized, shapeAspectRatio);
  28397. const [t, r, b, l] = rectToBounds(rectAlignedResized);
  28398. // update size
  28399. rectAlignedResized.width = width;
  28400. rectAlignedResized.height = height;
  28401. // align to anchor
  28402. if (imageTargetPositionAligned.y < anchor.y) {
  28403. rectAlignedResized.y = b - height;
  28404. }
  28405. if (imageTargetPositionAligned.x < anchor.x) {
  28406. rectAlignedResized.x = r - width;
  28407. }
  28408. }
  28409. // rotate the aligned rectangle around it's original pivot point
  28410. const rr = rectRotate(rectAlignedResized, rectRotation, rectAlignedCenterPosition);
  28411. // now calculate the new center and then rotate the tl and br corners around that center to find their new positions
  28412. const rrc = vectorCenter(rr);
  28413. const p1 = vectorRotate(rr[0], -rectRotation, rrc);
  28414. const p2 = vectorRotate(rr[2], -rectRotation, rrc);
  28415. // if (shapeCurrent.flipX || shapeCurrent.flipY) {
  28416. // vectorsFlip([p1, p2], shapeCurrent.flipX, shapeCurrent.flipY, rectAlignedCenterPosition.x, rectAlignedCenterPosition.y)
  28417. // }
  28418. const rectUpdated = rectCreateFromPoints(p1, p2);
  28419. updateShape(
  28420. shapeCurrent,
  28421. shapeIsEllipse(shapeCurrent)
  28422. ? ellipseCreateFromRect(rectUpdated)
  28423. : rectUpdated,
  28424. parentRect
  28425. );
  28426. } else // is translating two corner points
  28427. {
  28428. // 0-1 -> 2-3
  28429. // 1-2 -> 3-0
  28430. // 2-3 -> 0-1
  28431. // 3-0 -> 1-2
  28432. indexes = indexes.map(index => {
  28433. if (shapeCurrent.flipX) index = IndexFlipXMap[index];
  28434. if (shapeCurrent.flipY) index = IndexFlipYMap[index];
  28435. return index;
  28436. });
  28437. const [cornerA, cornerB] = indexes.map(index => rectCorners[index]);
  28438. const mid = {
  28439. x: cornerA.x + (cornerB.x - cornerA.x) * 0.5,
  28440. y: cornerA.y + (cornerB.y - cornerA.y) * 0.5
  28441. };
  28442. const [cornerAlignedA, cornerAlignedB] = indexes.map(index => rectAlignedCorners[index]);
  28443. const [cornerAlignedC, cornerAlignedD] = indexes.map(index => {
  28444. const mappedIndex = index + 2;
  28445. if (mappedIndex < 4) return rectAlignedCorners[mappedIndex];
  28446. return rectAlignedCorners[mappedIndex - 4];
  28447. });
  28448. // const midAligned = {
  28449. // x: cornerAlignedA.x + (cornerAlignedB.x - cornerAlignedA.x) * .5,
  28450. // y: cornerAlignedA.y + (cornerAlignedB.y - cornerAlignedA.y) * .5
  28451. // };
  28452. const midAnchorAligned = {
  28453. x: cornerAlignedC.x + (cornerAlignedD.x - cornerAlignedC.x) * 0.5,
  28454. y: cornerAlignedC.y + (cornerAlignedD.y - cornerAlignedC.y) * 0.5
  28455. };
  28456. const screenTargetPosition = mapImagePointToEditorPoint(mid);
  28457. vectorAdd(screenTargetPosition, translation);
  28458. const imageTargetPosition = mapEditorPointToImagePoint(screenTargetPosition);
  28459. const imageTargetTranslation = vectorCreate(imageTargetPosition.x - mid.x, imageTargetPosition.y - mid.y);
  28460. // if (shapeCurrent.flipX) imageTargetTranslation.x = -imageTargetTranslation.x;
  28461. // if (shapeCurrent.flipY) imageTargetTranslation.y = -imageTargetTranslation.y;
  28462. const imageTargetTranslationAligned = vectorRotate(vectorClone(imageTargetTranslation), -rectRotation);
  28463. // const imageTargetPositionAligned = vectorCreate(
  28464. // midAligned.x + imageTargetTranslationAligned.x,
  28465. // midAligned.y + imageTargetTranslationAligned.y,
  28466. // );
  28467. const d = vectorSubtract(vectorClone(cornerAlignedA), cornerAlignedB);
  28468. const f = vectorApply(d, v => 1 - Math.abs(Math.sign(v)));
  28469. const t = vectorCreate(imageTargetTranslationAligned.x * f.x, imageTargetTranslationAligned.y * f.y);
  28470. vectorAdd(cornerAlignedA, t);
  28471. vectorAdd(cornerAlignedB, t);
  28472. const rectAlignedResized = rectCreateFromPoints(rectAlignedCorners);
  28473. // limit rect
  28474. if (shapeAspectRatio) {
  28475. let width = rectAlignedResized.width;
  28476. let height = rectAlignedResized.height;
  28477. if (f.y === 0) {
  28478. height = width / shapeAspectRatio;
  28479. } else {
  28480. width = height * shapeAspectRatio;
  28481. }
  28482. // update size
  28483. rectAlignedResized.width = width;
  28484. rectAlignedResized.height = height;
  28485. // align to anchor
  28486. if (f.y === 0) {
  28487. rectAlignedResized.y = midAnchorAligned.y - height * 0.5;
  28488. } else {
  28489. rectAlignedResized.x = midAnchorAligned.x - width * 0.5;
  28490. }
  28491. }
  28492. // rotate the aligned rectangle around it's original pivot point
  28493. const rr = rectRotate(rectAlignedResized, rectRotation, rectAlignedCenterPosition);
  28494. // now calculate the new center and then rotate the tl and br corners around that center to find their new positions
  28495. const rrc = vectorCenter(rr);
  28496. const p1 = vectorRotate(rr[0], -rectRotation, rrc);
  28497. const p2 = vectorRotate(rr[2], -rectRotation, rrc);
  28498. // if (shapeCurrent.flipX || shapeCurrent.flipY) {
  28499. // vectorsFlip([p1, p2], shapeCurrent.flipX, shapeCurrent.flipY, rectAlignedCenterPosition.x, rectAlignedCenterPosition.y)
  28500. // }
  28501. const rectUpdated = rectCreateFromPoints(p1, p2);
  28502. let props;
  28503. if (shapeIsEllipse(shapeCurrent)) {
  28504. props = ellipseCreateFromRect(rectUpdated);
  28505. } else if (shapeHasSize(shapeCurrent)) {
  28506. props = rectUpdated;
  28507. } else if (hasAutoHeight) {
  28508. props = {
  28509. x: rectUpdated.x,
  28510. y: rectUpdated.y,
  28511. width: rectUpdated.width
  28512. };
  28513. }
  28514. updateShape(shapeCurrent, props, parentRect);
  28515. }
  28516. }
  28517. syncShapes();
  28518. };
  28519. let rotatorInitialPosition;
  28520. const rotateMarkup = (shapeCurrent, shapeOriginComputed, translation, options) => {
  28521. // calculate angle between translated rotation control and origin
  28522. const shapeRect = getMarkupShapeRect(shapeComputeDisplay(shapeDeepCopy(shapeCurrent), parentRect));
  28523. const shapeCenter = rectCenter(shapeRect);
  28524. const p = getImagePointWithScreenTranslation(rotatorInitialPosition, translation);
  28525. let shapeRotation = vectorAngleBetween(p, shapeCenter) + Math.PI / 2;
  28526. if (options.shiftKey) {
  28527. const rotatorSnapInterval = Math.PI / 16;
  28528. shapeRotation = rotatorSnapInterval * Math.round(shapeRotation / rotatorSnapInterval) - contextRotation % rotatorSnapInterval;
  28529. }
  28530. updateShape(shapeCurrent, { rotation: shapeRotation }, parentRect);
  28531. syncShapes();
  28532. };
  28533. const getMarkupItemDraft = () => {
  28534. if (!markup.length) return;
  28535. return markup.find(shapeIsDraft);
  28536. };
  28537. const getMarkupItemDraftIndex = () => {
  28538. if (!markup.length) return;
  28539. return markup.findIndex(shapeIsDraft);
  28540. };
  28541. const addMarkupItemDraft = (shape, sync = true) => {
  28542. if (getMarkupItemDraft()) return;
  28543. shapeMakeDraft(shape);
  28544. return addShape(shape, sync);
  28545. };
  28546. const confirmMarkupItemDraft = () => {
  28547. const markupItem = getMarkupItemDraft();
  28548. if (!markupItem) return;
  28549. shapeMakeFinal(markupItem);
  28550. syncShapes();
  28551. return markupItem;
  28552. };
  28553. const discardMarkupItemDraft = () => {
  28554. if (!getMarkupItemDraft()) return;
  28555. markup.splice(getMarkupItemDraftIndex(), 1);
  28556. syncShapes();
  28557. };
  28558. const createMarkupItem = (props = {}) => ({ id: getUniqueId(), ...props });
  28559. const syncShapes = () => $$invalidate(0, markup);
  28560. const addShape = (shape, sync = true) => {
  28561. markup.push(shape);
  28562. // sync markup array
  28563. if (sync) syncShapes();
  28564. return shape;
  28565. };
  28566. const removeMarkupShapeProps = (shape, props = [], sync = true) => {
  28567. props.forEach(prop => delete shape[prop]);
  28568. // sync markup array
  28569. if (!sync) return;
  28570. syncShapes();
  28571. };
  28572. const updateMarkupShape = (shape, props, sync = true) => {
  28573. // update markup
  28574. shape = Object.assign(shape, props);
  28575. // sync markup array
  28576. if (!sync) return;
  28577. syncShapes();
  28578. };
  28579. const updateMarkupShapeProperty = (shape, name, value, sync = true) => {
  28580. shape[name] = value;
  28581. // sync markup array
  28582. if (!sync) return;
  28583. syncShapes();
  28584. };
  28585. const updateMarkupItemsShapeProperty = (name, value, sync = true) => {
  28586. markup.forEach(shape => updateMarkupShapeProperty(shape, name, value, false));
  28587. // sync markup array
  28588. if (!sync) return;
  28589. syncShapes();
  28590. };
  28591. const updateMarkupShapeItems = (props, sync = true) => {
  28592. markup.forEach(markupItem => updateMarkupShape(markupItem, props, false));
  28593. // sync markup array
  28594. if (!sync) return;
  28595. syncShapes();
  28596. };
  28597. const getActiveMarkupItem = () => [...markup].reverse().find(shapeIsSelected);
  28598. const hasActiveMarkupItem = () => !!getActiveMarkupItem();
  28599. const removeShape = shapeToRemove => {
  28600. if (!beforeRemoveShape(shapeToRemove)) return false;
  28601. $$invalidate(0, markup = markup.filter(shape => shape !== shapeToRemove));
  28602. onremoveshape(shapeToRemove);
  28603. };
  28604. const removeActiveMarkupItem = () => {
  28605. const activeShape = getActiveMarkupItem();
  28606. if (!activeShape) return;
  28607. // get removable markup items,
  28608. const removableShapes = markup.filter(shape => shapeCanRemove(shape) && shapeCanSelect(shape));
  28609. // find index of active shape so we can select the next active shape on removal
  28610. const index = removableShapes.findIndex(shape => shape === activeShape);
  28611. // remove the active ship from the shape array
  28612. const didRemove = removeShape(activeShape);
  28613. if (didRemove === false) return;
  28614. // remember selection
  28615. previousSelectedShape = activeShape;
  28616. // if no more markup items, release active shape
  28617. if (removableShapes.length - 1 <= 0) return blurShapes();
  28618. // select next active markup item
  28619. const indexNext = index - 1 < 0 ? removableShapes.length - 1 : index - 1;
  28620. selectShape(removableShapes[indexNext]);
  28621. };
  28622. let previousSelectedShape = undefined;
  28623. const blurShapes = () => {
  28624. // clear text state cache, when a text shape is blurred the changes are confirmed
  28625. Object.keys(ShapeTextStateCache).forEach(key => ShapeTextStateCache[key] = {});
  28626. // remember shape
  28627. previousSelectedShape = getSelectedShape();
  28628. updateMarkupShapeItems({ isSelected: false, isEditing: false });
  28629. };
  28630. const getSelectedShape = () => markup.find(shapeIsSelected);
  28631. const selectShape = (shape, sync = true) => {
  28632. // can't select draft
  28633. if (shapeIsDraft(shape)) return;
  28634. // get currently selected shape
  28635. const selectedShape = getSelectedShape() || previousSelectedShape;
  28636. // reset previous selected shape
  28637. previousSelectedShape = undefined;
  28638. // if is returned false will cancel select operation
  28639. if (!beforeSelectShape(selectedShape, shape)) return;
  28640. // remove selected state from other markup
  28641. blurShapes();
  28642. // select
  28643. shapeSelect(shape);
  28644. // selected this shape
  28645. onselectshape(shape);
  28646. // sync
  28647. if (!sync) return;
  28648. syncShapes();
  28649. };
  28650. const deselectMarkupItem = markupItem => {
  28651. updateMarkupShape(markupItem, { isSelected: false, isEditing: false });
  28652. };
  28653. const editMarkupItem = markupItem => {
  28654. updateMarkupShape(markupItem, { isSelected: true, isEditing: true });
  28655. };
  28656. const finishEditMarkupItem = markupItem => {
  28657. updateMarkupShape(markupItem, { isSelected: true, isEditing: false });
  28658. };
  28659. const removeMarkupItems = shapesToRemove => {
  28660. const shapesToRemoveFiltered = shapesToRemove.filter(beforeRemoveShape);
  28661. $$invalidate(0, markup = markup.filter(shape => !shapesToRemoveFiltered.includes(shape)));
  28662. return shapesToRemoveFiltered;
  28663. };
  28664. const getTextShapeRect = shape => {
  28665. const size = textSize(shape.text, shape);
  28666. return rectCreate(
  28667. shape.x,
  28668. shape.y,
  28669. shape.width
  28670. ? Math.min(shape.width, size.width)
  28671. : size.width,
  28672. shape.height
  28673. ? Math.min(shape.height, size.height)
  28674. : size.height
  28675. );
  28676. };
  28677. const getMarkupShapeRect = shape => {
  28678. // has own rect
  28679. if (shapeHasSize(shape)) return rectCreateFromAny(shape);
  28680. if (shapeIsEllipse(shape)) return rectCreateFromEllipse(shape);
  28681. // calculate the size on canvas
  28682. const rect = getTextShapeRect(shape);
  28683. rect.width = Math.max(MIN_TEXT_MARKUP_WIDTH, shape.width || rect.width);
  28684. return rect;
  28685. };
  28686. const getShapesNearPosition = (position, range = 0) => [...markup].// reverse the array, want to select from top to bottom
  28687. reverse().map(shape => ({ shape, priority: 1 })).// can't select paths
  28688. filter(result => shapeCanSelect(result.shape)).// find markup near pointer
  28689. filter(result => {
  28690. // get shape
  28691. const { shape } = result;
  28692. // we need to know where the shape will end up
  28693. const computedShape = shapeComputeDisplay(shapeDeepCopy(shape), parentRect);
  28694. // add stroke width to range
  28695. const r = range + (computedShape.strokeWidth || 0);
  28696. // test if clicked in rect
  28697. if (shapeIsRect(computedShape)) {
  28698. return circleOverlapsWithRect(position, r, computedShape, shape.rotation);
  28699. } else if (shapeIsText(computedShape)) {
  28700. const shapeRect = getMarkupShapeRect(computedShape);
  28701. const isPositionInBounds = circleOverlapsWithRect(position, r, shapeRect, shape.rotation);
  28702. let isPositionInVisual = false;
  28703. if (isPositionInBounds && !shapeIsSelected(shape)) {
  28704. const visualRect = getTextShapeRect(computedShape);
  28705. if (shape.textAlign === "right" && !shape.flipX) {
  28706. visualRect.x = shapeRect.x + shapeRect.width - visualRect.width;
  28707. }
  28708. if (shape.textAlign === "center") {
  28709. visualRect.x = shapeRect.x + shapeRect.width * 0.5 - visualRect.width * 0.5;
  28710. }
  28711. isPositionInVisual = circleOverlapsWithRect(position, r, visualRect, shape.rotation, rectCenter(shapeRect));
  28712. if (!isPositionInVisual) result.priority = -1;
  28713. }
  28714. return isPositionInBounds;
  28715. } else // test if is ellipse
  28716. if (shapeIsEllipse(computedShape)) {
  28717. return circleOverlapsWithEllipse(position, r, computedShape, shape.rotation, shape.flipX, shape.flipY);
  28718. } else // test if clicked on line
  28719. if (shapeIsLine(computedShape)) {
  28720. // radius around click position, test if line intersects
  28721. return circleOverlapsWithLine(position, Math.max(16, r), shapeLineGetStartPoint(computedShape), shapeLineGetEndPoint(computedShape)); // always increase range when selecting lines
  28722. } else if (shapeIsPath(computedShape)) {
  28723. // radius around click position, test if line intersects
  28724. return circleOverlapsWithPath(position, Math.max(16, r), computedShape.points); // always increase range when selecting lines
  28725. }
  28726. return false;
  28727. }).sort((a, b) => {
  28728. if (a.priority < b.priority) return 1;
  28729. if (a.priority > b.priority) return -1;
  28730. return 0;
  28731. });
  28732. const getShapesBetweenPoints = (shapes, a, b, range = 0) => {
  28733. // make sure range is not negative
  28734. const r = Math.abs(range);
  28735. // eraseLine should be in image space
  28736. const eraseLine = lineExtend(lineCreate(a, b), r);
  28737. // create line polygon
  28738. const erasePoly = lineExtrude(eraseLine, r);
  28739. // loop over shapes and find intersecting shapes
  28740. return shapes.// .filter(shapeCanErase)
  28741. filter(shape => {
  28742. const computedShape = shapeComputeDisplay(shapeDeepCopy(shape), parentRect);
  28743. // if shape is line or path
  28744. if (shapeIsLine(computedShape) || shapeIsPath(computedShape)) {
  28745. const points = computedShape.points
  28746. ? [...computedShape.points]
  28747. : [
  28748. shapeLineGetStartPoint(computedShape),
  28749. shapeLineGetEndPoint(computedShape)
  28750. ];
  28751. return !!linePointsIntersection(eraseLine, points);
  28752. }
  28753. // else turn into polygon and compare polygons
  28754. return polyIntersectsWithPoly(erasePoly, shapeToPoly(computedShape));
  28755. });
  28756. };
  28757. //
  28758. // Generic interaction
  28759. //
  28760. let interactionTimer = undefined;
  28761. let interactionTarget = undefined;
  28762. let interactionShape = undefined;
  28763. let interactionShapeOrigin = undefined;
  28764. let interactionShapeOriginComputed = undefined;
  28765. let isInteracting = false;
  28766. const handleInteractionStart = e => {
  28767. const { origin } = e.detail;
  28768. interactionShape = undefined;
  28769. interactionShapeOrigin = undefined;
  28770. interactionShapeOriginComputed = undefined;
  28771. interactionTarget = undefined;
  28772. clearTimeout(interactionTimer);
  28773. interactionTimer = setTimeout(() => $$invalidate(99, isInteracting = true), 250);
  28774. // if is editing text
  28775. const draft = getMarkupItemDraft();
  28776. if (draft) confirmMarkupItemDraft();
  28777. // test if target is a shape, if not, run interaction handler
  28778. const point = mapEditorPointToImagePoint(vectorClone(origin));
  28779. const foundShapes = getShapesNearPosition(point, selectRadius);
  28780. const targettedMarkupItem = foundShapes.length && foundShapes.shift().shape;
  28781. // check if markup was targetted
  28782. if (targettedMarkupItem && shapeIsSelected(targettedMarkupItem)) {
  28783. interactionShape = targettedMarkupItem;
  28784. // create a deep copy so we can check on end interaction if the shape was changed
  28785. interactionShapeOrigin = shapeDeepCopy(interactionShape);
  28786. // clone shape we're interacting with so we can update it properly
  28787. interactionShapeOriginComputed = shapeComputeDisplay(shapeDeepCopy(interactionShape), parentRect);
  28788. return;
  28789. }
  28790. // set target
  28791. interactionTarget = targettedMarkupItem;
  28792. // started interacting
  28793. const didStartInteraction = oninteractionstart(e);
  28794. // drag current targetted it as fallback interaction, helps make sticker interaction easier
  28795. if (!didStartInteraction && targettedMarkupItem) {
  28796. selectShape(targettedMarkupItem);
  28797. interactionShape = targettedMarkupItem;
  28798. // create a deep copy so we can check on end interaction if the shape was changed
  28799. interactionShapeOrigin = shapeDeepCopy(interactionShape);
  28800. // clone shape we're interacting with so we can update it properly
  28801. interactionShapeOriginComputed = shapeComputeDisplay(shapeDeepCopy(interactionShape), parentRect);
  28802. }
  28803. };
  28804. const handleInteractionUpdate = e => {
  28805. // is interacting with shape
  28806. if (interactionShape) {
  28807. // prevent moving if not allowed
  28808. if (!shapeCanMove(interactionShape)) return;
  28809. // prevent moving if is editing text
  28810. if (shapeIsTextEditing(interactionShape)) return;
  28811. return translateShape(interactionShape, interactionShapeOriginComputed, e.detail.translation);
  28812. }
  28813. oninteractionupdate(e);
  28814. };
  28815. const handleInteractionRelease = e => {
  28816. clearTimeout(interactionTimer);
  28817. $$invalidate(99, isInteracting = false);
  28818. // test if is text and if we double tapped, if so, switch to text edit mode
  28819. if (interactionShape) {
  28820. if (interactionShape.isEditing) {
  28821. handleTextCancel();
  28822. } else if (e.detail.isDoubleTap && shapeIsText(interactionShape) && shapeCanInput(interactionShape) !== false) {
  28823. editMarkupItem(interactionShape);
  28824. }
  28825. return;
  28826. }
  28827. oninteractionrelease(e);
  28828. };
  28829. const handleInteractionEnd = e => {
  28830. const isSelectInteraction = interactionTarget && e.detail.isTap;
  28831. // shape remains active so user can resize, rotate
  28832. if (interactionShape) {
  28833. if (!shapeEqual(interactionShape, interactionShapeOrigin)) onupdateshape(interactionShape);
  28834. interactionShape = undefined;
  28835. return;
  28836. }
  28837. // can we deselect the current shape?
  28838. const currentSelectedShape = getSelectedShape();
  28839. const allowDeselectShape = currentSelectedShape
  28840. ? beforeDeselectShape(currentSelectedShape, interactionTarget)
  28841. : true;
  28842. if (allowDeselectShape) {
  28843. blurShapes();
  28844. }
  28845. oninteractionend(e);
  28846. if (allowDeselectShape && isSelectInteraction) {
  28847. selectShape(interactionTarget);
  28848. }
  28849. };
  28850. //
  28851. // Shape manipulation
  28852. //
  28853. const getMarkupShapePoints = shape => {
  28854. let points;
  28855. if (shapeIsRect(shape)) {
  28856. const center = rectCenter(shape);
  28857. points = rectGetCorners(shape);
  28858. if (shape.flipX || shape.flipY) vectorsFlip(points, shape.flipX, shape.flipY, center.x, center.y);
  28859. points = vectorsRotate(points, shape.rotation, center.x, center.y);
  28860. } else if (shapeIsEllipse(shape)) {
  28861. const center = shape;
  28862. points = rectGetCorners(rectCreateFromEllipse(shape));
  28863. if (shape.flipX || shape.flipY) vectorsFlip(points, shape.flipX, shape.flipY, center.x, center.y);
  28864. points = vectorsRotate(points, shape.rotation, center.x, center.y);
  28865. } else if (shapeIsLine(shape)) {
  28866. points = [shapeLineGetStartPoint(shape), shapeLineGetEndPoint(shape)];
  28867. } else if (shapeIsPath(shape)) {
  28868. points = [...shape.points];
  28869. } else if (shapeIsText(shape)) {
  28870. const rect = getMarkupShapeRect(shape);
  28871. rect.width = Math.max(MIN_TEXT_MARKUP_WIDTH, rect.width);
  28872. const center = rectCenter(rect);
  28873. points = rectGetCorners(rect);
  28874. if (shape.flipX || shape.flipY) vectorsFlip(points, shape.flipX, shape.flipY, center.x, center.y);
  28875. points = vectorsRotate(points, shape.rotation, center.x, center.y);
  28876. }
  28877. return points;
  28878. };
  28879. const getShapeRotationPoint = shape => {
  28880. const points = getMarkupShapePoints(shape);
  28881. let origin;
  28882. let dir;
  28883. if (shape.flipY) {
  28884. origin = vectorCenter([points[0], points[1]]);
  28885. dir = vectorNormalize(vectorCreate(points[1].x - points[2].x, points[1].y - points[2].y));
  28886. } else {
  28887. origin = vectorCenter([points[2], points[3]]);
  28888. dir = vectorNormalize(vectorCreate(points[2].x - points[1].x, points[2].y - points[1].y));
  28889. }
  28890. vectorMultiply(dir, ROTATION_CONTROL_OFFSET / contextScale);
  28891. return { origin, dir };
  28892. };
  28893. const getShapeRotationPointOnScreen = shape => {
  28894. const markupPoint = getShapeRotationPoint(shape);
  28895. const screenPosition = mapImagePointToEditorPoint({
  28896. x: markupPoint.origin.x + markupPoint.dir.x,
  28897. y: markupPoint.origin.y + markupPoint.dir.y
  28898. });
  28899. const screenOrigin = mapImagePointToEditorPoint(markupPoint.origin);
  28900. return {
  28901. origin: screenOrigin,
  28902. position: screenPosition
  28903. };
  28904. };
  28905. // draw shape manipulator edges
  28906. let shapeManipulatorUid = `markup-manipulator-segment`;
  28907. const claimManipulatorLines = () => {
  28908. $$invalidate(42, ui = ui.map(shape => {
  28909. if (shape.id !== shapeManipulatorUid) return shape;
  28910. shape._group = uid;
  28911. return shape;
  28912. }));
  28913. };
  28914. const shouldManipulateLines = () => !!ui.find(segment => segment._group === uid);
  28915. const redrawManipulatorLines = opacity => {
  28916. // get current line opacity
  28917. const current = ui.find(segment => segment.id === shapeManipulatorUid);
  28918. const manipulatorOpacity = current ? Math.max(current.opacity, opacity) : opacity;
  28919. // create manipulator outline segments
  28920. const segments = [];
  28921. const shadowOpacity = 0.1 * manipulatorOpacity;
  28922. const lineOpacity = manipulatorOpacity;
  28923. const strokeColorShadow = [0, 0, 0];
  28924. const strokeColor = [1, 1, 1];
  28925. const strokeWidth = 1.5;
  28926. const pathClose = shapeIsPath(activeMarkup) || shapeIsLine(activeMarkup)
  28927. ? false
  28928. : true;
  28929. // shadows
  28930. segments.push({
  28931. id: shapeManipulatorUid,
  28932. points: shapeActiveScreenPoints.map(p => vectorCreate(p.x + 1, p.y + 1)),
  28933. pathClose,
  28934. strokeColor: strokeColorShadow,
  28935. strokeWidth: 2,
  28936. opacity: shadowOpacity,
  28937. _group: uid
  28938. });
  28939. if (shapeManipulatorRotationPoint) {
  28940. // add rotator line shadow
  28941. segments.push({
  28942. id: shapeManipulatorUid,
  28943. points: [
  28944. vectorCreate(shapeManipulatorRotationPoint.origin.x + 1, shapeManipulatorRotationPoint.origin.y + 1),
  28945. vectorCreate(shapeManipulatorRotationPoint.position.x + 1, shapeManipulatorRotationPoint.position.y + 1)
  28946. ],
  28947. strokeColor: strokeColorShadow,
  28948. strokeWidth: 2,
  28949. opacity: shadowOpacity,
  28950. _group: uid
  28951. });
  28952. }
  28953. // lines
  28954. segments.push({
  28955. id: shapeManipulatorUid,
  28956. points: shapeActiveScreenPoints,
  28957. pathClose,
  28958. strokeColor,
  28959. strokeWidth,
  28960. opacity: lineOpacity,
  28961. _group: uid
  28962. });
  28963. if (shapeManipulatorRotationPoint) {
  28964. // add rotator line
  28965. segments.push({
  28966. id: shapeManipulatorUid,
  28967. points: [
  28968. {
  28969. x: shapeManipulatorRotationPoint.origin.x,
  28970. y: shapeManipulatorRotationPoint.origin.y
  28971. },
  28972. {
  28973. x: shapeManipulatorRotationPoint.position.x,
  28974. y: shapeManipulatorRotationPoint.position.y
  28975. }
  28976. ],
  28977. strokeColor,
  28978. strokeWidth,
  28979. opacity: lineOpacity,
  28980. _group: uid
  28981. });
  28982. }
  28983. // replace existing segments
  28984. $$invalidate(42, ui = [...ui.filter(guide => guide.id !== shapeManipulatorUid), ...segments]);
  28985. };
  28986. const removeMarkupManipulatorLines = () => {
  28987. $$invalidate(42, ui = ui.filter(guide => guide.opacity === 0 && guide.id !== shapeManipulatorUid));
  28988. };
  28989. onDestroy(() => {
  28990. // clean up invisible lines
  28991. removeMarkupManipulatorLines();
  28992. });
  28993. const handleManipulatorResizeGrab = e => {
  28994. $$invalidate(99, isInteracting = true);
  28995. interactionShape = activeMarkup;
  28996. interactionShapeOriginComputed = activeMarkupComputed;
  28997. };
  28998. const handleManipulatorResizeDrag = e => {
  28999. const { translation, indexes, shiftKey } = e.detail;
  29000. resizeMarkup(interactionShape, interactionShapeOriginComputed, indexes, translation, { shiftKey });
  29001. };
  29002. const handleManipulatorResizeEnd = e => {
  29003. selectShape(interactionShape);
  29004. interactionShape = undefined;
  29005. $$invalidate(99, isInteracting = false);
  29006. onupdateshape(activeMarkup);
  29007. };
  29008. const handleManipulatorRotateGrab = e => {
  29009. rotatorInitialPosition = getShapeRotationPoint(activeMarkupComputed).origin;
  29010. $$invalidate(99, isInteracting = true);
  29011. interactionShape = activeMarkup;
  29012. interactionShapeOriginComputed = activeMarkupComputed;
  29013. };
  29014. const handleManipulatorRotateDrag = e => {
  29015. const { translation, shiftKey } = e.detail;
  29016. rotateMarkup(interactionShape, interactionShapeOriginComputed, translation, { shiftKey });
  29017. };
  29018. const handleManipulatorRotateEnd = () => {
  29019. selectShape(interactionShape);
  29020. interactionShape = undefined;
  29021. $$invalidate(99, isInteracting = false);
  29022. onupdateshape(activeMarkup);
  29023. };
  29024. //
  29025. // Keyboard
  29026. //
  29027. const handleKey = e => {
  29028. // only handle key input if a shape has been selected
  29029. if (!hasActiveMarkupItem()) return;
  29030. // get key type
  29031. const { key } = e;
  29032. // if is escape deselect active item
  29033. if ((/escape/i).test(key)) {
  29034. return deselectMarkupItem(activeMarkup);
  29035. }
  29036. // if is tab, select next markup item
  29037. /*
  29038. if (/arrow/i.test(key)) {
  29039. const success = e.shiftKey
  29040. ? selectPreviousMarkupItem(activeMarkup)
  29041. : selectNextMarkupItem(activeMarkup);
  29042. if (success) {
  29043. e.preventDefault();
  29044. e.stopPropagation();
  29045. }
  29046. }
  29047. */
  29048. // if is remove active
  29049. if ((/backspace/i).test(key) && !(/input|textarea/i).test(e.target.nodeName)) {
  29050. // prevent back navigation on Firefox
  29051. e.preventDefault();
  29052. // remove the item
  29053. removeActiveMarkupItem();
  29054. }
  29055. };
  29056. //
  29057. // Text input
  29058. //
  29059. let textInput;
  29060. const getTextShapeOriginSnapshot = () => ({ ...activeMarkup });
  29061. const handleTextInput = () => {
  29062. const value = shapeIsTextLine(activeMarkup)
  29063. ? filterNewlines(textInput.value)
  29064. : textInput.value;
  29065. const canInput = shapeCanInput(activeMarkup, value);
  29066. const text = canInput === true ? value : canInput;
  29067. let x = textShapeDisplayOrigin.x;
  29068. let y = textShapeDisplayOrigin.y;
  29069. // if does not have height we need to adjust offset if is rotated
  29070. if (!activeMarkup.height) {
  29071. // draw origin rect
  29072. const originRotatedRect = rectRotate({ ...textRectDisplayOrigin }, activeMarkup.rotation);
  29073. // draw current rect
  29074. const size = textSize(text, activeMarkupComputed);
  29075. const currentRotatedRect = rectRotate({ x, y, ...size }, activeMarkup.rotation);
  29076. const [originTopLeft, ,originBottomRight] = originRotatedRect;
  29077. const [currentTopLeft, ,currentBottomRight] = currentRotatedRect;
  29078. let a = originTopLeft;
  29079. let b = currentTopLeft;
  29080. // if flipped we need to 'extend' the text field in the opposite direction
  29081. if (activeMarkup.flipX) {
  29082. a = originBottomRight;
  29083. b = currentBottomRight;
  29084. }
  29085. // move
  29086. const d = vectorSubtract(vectorClone(a), b);
  29087. x += d.x;
  29088. y += d.y;
  29089. }
  29090. updateMarkupShape(activeMarkup, {
  29091. x: isString(textShapeOrigin.x)
  29092. ? toPercentage(x, parentRect.width)
  29093. : x,
  29094. y: isString(textShapeOrigin.y)
  29095. ? toPercentage(y, parentRect.height)
  29096. : y,
  29097. text
  29098. });
  29099. };
  29100. const getShapeSizeTranslation = (originRect, targetRect, { flipX, flipY, rotation }, anchor = "top left") => {
  29101. let a, b;
  29102. // draw origin rect
  29103. const [originTopLeft, originTopRight, originBottomRight, originBottomLeft] = rectRotate(originRect, rotation);
  29104. // draw target rect
  29105. const [targetTopLeft, targetTopRight, targetBottomRight, targetBottomLeft] = rectRotate(targetRect, rotation);
  29106. if (anchor === "top center") {
  29107. // for now doesn't matter if it's flipped horizontal
  29108. const originMid = vectorCenter(flipY
  29109. ? [originBottomLeft, originBottomRight]
  29110. : [originTopLeft, originTopRight]);
  29111. const targetMid = vectorCenter(flipY
  29112. ? [targetBottomLeft, targetBottomRight]
  29113. : [targetTopLeft, targetTopRight]);
  29114. a = originMid;
  29115. b = targetMid;
  29116. } else if (anchor === "top right" && !flipX || anchor === "top left" && flipX) {
  29117. // tr
  29118. a = flipY ? originBottomRight : originTopRight;
  29119. b = flipY ? targetBottomRight : targetTopRight;
  29120. } else {
  29121. // tl
  29122. a = flipY ? originBottomLeft : originTopLeft;
  29123. b = flipY ? targetBottomLeft : targetTopLeft;
  29124. }
  29125. return vectorSubtract(vectorClone(a), b);
  29126. };
  29127. const translateRelative = (current, position, translation) => vectorCreate(
  29128. isString(current.x)
  29129. ? toPercentage(position.x + translation.x, parentRect.width)
  29130. : position.x + translation.x,
  29131. isString(current.y)
  29132. ? toPercentage(position.y + translation.y, parentRect.height)
  29133. : position.y + translation.y
  29134. );
  29135. const ShapeTextStateCache = {};
  29136. const handleTextSwitchLayout = () => {
  29137. const shapeTextSize = textSize(activeMarkup.text, activeMarkupComputed);
  29138. const isFixedBox = hasProp(activeMarkup, "height");
  29139. const isAutoHeightBox = !isFixedBox && hasProp(activeMarkup, "width");
  29140. // set/get cache entries for this text shapw
  29141. const key = activeMarkup.id;
  29142. let cache = ShapeTextStateCache[key];
  29143. if (!cache) {
  29144. ShapeTextStateCache[key] = {};
  29145. cache = ShapeTextStateCache[key];
  29146. }
  29147. const toAutoWidth = sizeFrom => {
  29148. const { width, ...autoSizeProps } = activeMarkupComputed;
  29149. const sizeTo = textSize(activeMarkup.text, autoSizeProps);
  29150. // this will change dimensions so if rotated we have to calculate new position
  29151. const translation = getShapeSizeTranslation(rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeFrom.width, sizeFrom.height), rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeTo.width, sizeTo.height), activeMarkupComputed, `top ${activeMarkup.textAlign}`);
  29152. // switch to auto mode
  29153. removeMarkupShapeProps(activeMarkup, ["width", "height", "textAlign"]);
  29154. // update position based on size translation
  29155. updateMarkupShape(activeMarkup, {
  29156. ...translateRelative(activeMarkup, activeMarkupComputed, translation)
  29157. });
  29158. };
  29159. const toAutoHeight = sizeFrom => {
  29160. // -> switch to auto height mode
  29161. const sizeTo = sizeCreate(cache.width || activeMarkupComputed.width || shapeTextSize.width, shapeTextSize.height);
  29162. const textAlign = cache.textAlign || "left";
  29163. // this will change dimensions so if rotated we have to calculate new position
  29164. const translation = getShapeSizeTranslation(rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeFrom.width, sizeFrom.height), rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeTo.width, sizeTo.height), activeMarkupComputed, `top ${textAlign}`);
  29165. // switch to auto-height mode
  29166. removeMarkupShapeProps(activeMarkup, ["height"]);
  29167. // update position based on size translation
  29168. updateMarkupShape(activeMarkup, {
  29169. ...translateRelative(activeMarkup, activeMarkupComputed, translation),
  29170. width: isString(activeMarkup.width)
  29171. ? toPercentage(sizeTo.width, parentRect.width)
  29172. : sizeTo.width,
  29173. textAlign
  29174. });
  29175. };
  29176. const toFixedSize = sizeFrom => {
  29177. // this can change dimensions so we need to recalculate position
  29178. const sizeTo = sizeCreate(cache.width || shapeTextSize.width, cache.height || shapeTextSize.height);
  29179. const textAlign = cache.textAlign || "left";
  29180. // this will change dimensions so if rotated we have to calculate new position
  29181. const translation = getShapeSizeTranslation(rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeFrom.width, sizeFrom.height), rectCreate(activeMarkupComputed.x, activeMarkupComputed.y, sizeTo.width, sizeTo.height), activeMarkupComputed, `top ${textAlign}`);
  29182. // switch to fixed box, use stored alignment or default to left text align
  29183. updateMarkupShape(activeMarkup, {
  29184. ...translateRelative(activeMarkup, activeMarkupComputed, translation),
  29185. width: isString(activeMarkup.width)
  29186. ? toPercentage(sizeTo.width, parentRect.width)
  29187. : sizeTo.width,
  29188. height: isString(activeMarkup.width)
  29189. ? toPercentage(sizeTo.height, parentRect.height)
  29190. : sizeTo.height,
  29191. textAlign
  29192. });
  29193. };
  29194. if (isFixedBox) {
  29195. // store size so we can restore it later
  29196. cache.textAlign = activeMarkup.textAlign;
  29197. cache.width = activeMarkupComputed.width;
  29198. cache.height = activeMarkupComputed.height;
  29199. const sizeFrom = sizeCreate(activeMarkupComputed.width, activeMarkupComputed.height);
  29200. if (shapeCanChangeTextLayout(activeMarkup, "auto-height")) {
  29201. toAutoHeight(sizeFrom);
  29202. } else if (shapeCanChangeTextLayout(activeMarkup, "auto-width")) {
  29203. toAutoWidth(sizeFrom);
  29204. }
  29205. } else if (isAutoHeightBox) {
  29206. // store alignment so we can restore it later
  29207. cache.textAlign = activeMarkup.textAlign;
  29208. cache.width = activeMarkupComputed.width;
  29209. // -> switch to auto width
  29210. const sizeFrom = sizeCreate(activeMarkupComputed.width, shapeTextSize.height);
  29211. if (shapeCanChangeTextLayout(activeMarkup, "auto-width")) {
  29212. toAutoWidth(sizeFrom);
  29213. } else if (shapeCanChangeTextLayout(activeMarkup, "fixed-size")) {
  29214. toFixedSize(sizeFrom);
  29215. }
  29216. } else {
  29217. // -> switch to fixed size or auto height
  29218. const sizeFrom = sizeCreate(shapeTextSize.width, shapeTextSize.height);
  29219. if (shapeCanChangeTextLayout(activeMarkup, "fixed-size")) {
  29220. toFixedSize(sizeFrom);
  29221. } else if (shapeCanChangeTextLayout(activeMarkup, "auto-height")) {
  29222. toAutoHeight(sizeFrom);
  29223. }
  29224. }
  29225. };
  29226. const handleEditTextActiveMarkup = () => editMarkupItem(activeMarkup);
  29227. const handleTextInputAttempt = e => {
  29228. const currentValue = e.target.value;
  29229. const selectionStart = e.target.selectionStart;
  29230. const selectionEnd = e.target.selectionEnd;
  29231. const currentValueStart = currentValue.substring(0, selectionStart);
  29232. const currentValueEnd = currentValue.substring(selectionEnd);
  29233. const intendedValue = currentValueStart + e.key + currentValueEnd;
  29234. const filteredValue = shapeCanInput(activeMarkup, intendedValue);
  29235. if (filteredValue !== intendedValue) return e.preventDefault();
  29236. };
  29237. const filterNewlines = value => value.// split on lines so we can create compressed normal line of text
  29238. split(/[\n\r]/g).// rempve spaces around lines
  29239. map(str => str.trim()).// remove empty strings
  29240. filter(str => str.length).// create new line
  29241. join(" ");
  29242. // prevent moving shape when focusing text field, and close field if escape pressed
  29243. const handleTextInputKeyDown = e => {
  29244. if (shapeIsTextLine(activeMarkup) && (/enter/i).test(e.code)) return e.preventDefault();
  29245. if ((/arrow/i).test(e.code)) return e.stopPropagation();
  29246. if ((/escape/i).test(e.key)) return handleTextCancel();
  29247. };
  29248. // handle alt/ctrl/cmd + return
  29249. const handleTextInputKeyUp = e => {
  29250. // get key type
  29251. const { key, ctrlKey, altKey } = e;
  29252. // confirm multi line text elements
  29253. if ((/enter/i).test(key) && ctrlKey | altKey) return handleTextConfirm();
  29254. };
  29255. const handleTextConfirm = () => {
  29256. // if was draft, now need to confirm
  29257. let wasDraft = shapeIsDraft(activeMarkup);
  29258. if (shapeIsDraft(activeMarkup)) confirmMarkupItemDraft();
  29259. // final text input check
  29260. handleTextInput();
  29261. // done
  29262. finishEditMarkupItem(activeMarkup);
  29263. if (wasDraft) onaddshape(activeMarkup); else onupdateshape(activeMarkup);
  29264. };
  29265. const handleTextCancel = () => {
  29266. if (shapeIsDraft(activeMarkup)) {
  29267. discardMarkupItemDraft();
  29268. } else {
  29269. updateMarkupShape(activeMarkup, {
  29270. text: textShapeOrigin.text,
  29271. x: textShapeOrigin.x,
  29272. y: textShapeOrigin.y
  29273. });
  29274. finishEditMarkupItem(activeMarkup);
  29275. }
  29276. };
  29277. //
  29278. // Controls
  29279. //
  29280. const handleFlipX = e => {
  29281. e.stopPropagation();
  29282. const flipX = activeMarkup.flipX || false;
  29283. updateMarkupShapeProperty(activeMarkup, "flipX", !flipX);
  29284. onupdateshape(activeMarkup);
  29285. };
  29286. const handleFlipY = e => {
  29287. e.stopPropagation();
  29288. const flipY = activeMarkup.flipY || false;
  29289. updateMarkupShapeProperty(activeMarkup, "flipY", !flipY);
  29290. onupdateshape(activeMarkup);
  29291. };
  29292. const handleAdjustOpacity = value => {
  29293. updateMarkupShapeProperty(activeMarkup, "opacity", value);
  29294. onupdateshape(activeMarkup);
  29295. };
  29296. const handleRemoveActiveMarkup = e => {
  29297. e.stopPropagation();
  29298. e.target.blur(); // cancels focus of remove button
  29299. removeActiveMarkupItem();
  29300. };
  29301. const handleMoveToFrontActiveMarkup = e => {
  29302. e.stopPropagation();
  29303. // test if is not already at top of stack, if so, exit
  29304. const index = markup.findIndex(shape => shape === activeMarkup);
  29305. if (index === markup.length - 1) return;
  29306. // add to last index
  29307. $$invalidate(0, markup = markup.filter(markupItem => markupItem !== activeMarkup).concat([activeMarkup]));
  29308. onupdateshape(activeMarkup);
  29309. };
  29310. const handleDuplicateActiveMarkup = e => {
  29311. e.stopPropagation();
  29312. // create clone
  29313. const clone = shapeDeepCopy(activeMarkup);
  29314. clone.id = getUniqueId();
  29315. const duplicationOffset = vectorCreate(50, -50);
  29316. // offset
  29317. if (shapeIsLine(clone)) {
  29318. const linePosition = shapeGetPropsPixelValues(clone, ["x1", "y1", "x2", "y2"], parentRect);
  29319. linePosition.x1 += duplicationOffset.x;
  29320. linePosition.y1 += duplicationOffset.y;
  29321. linePosition.x2 += duplicationOffset.x;
  29322. linePosition.y2 += duplicationOffset.y;
  29323. shapeUpdateProps(clone, linePosition, parentRect);
  29324. } else {
  29325. const currentPosition = shapeGetPropsPixelValues(clone, ["x", "y"], parentRect);
  29326. currentPosition.x += 50;
  29327. currentPosition.y -= 50;
  29328. shapeUpdateProps(clone, currentPosition, parentRect);
  29329. }
  29330. // add clone
  29331. markup.push(clone);
  29332. // added
  29333. onaddshape(clone);
  29334. // select clone
  29335. selectShape(clone);
  29336. };
  29337. const getMarkupControlsAnchorPosition = rect => vectorApply(vectorCreate(rect.x + rect.width * 0.5, rect.y), snapToPixel);
  29338. //
  29339. // show & position markup controls panel
  29340. //
  29341. const markupControlsOpacity = spring(0, { stiffness: 0.2, damping: 0.7 });
  29342. component_subscribe($$self, markupControlsOpacity, value => $$invalidate(10, $markupControlsOpacity = value));
  29343. let shapeControlsSize;
  29344. const getShapeControlPositionOnCanvas = position => {
  29345. const left = utilRect.x;
  29346. const top = utilRect.y;
  29347. const right = left + utilRect.width;
  29348. let x = Math.max(position.x - shapeControlsSize.width * 0.5, left);
  29349. let y = Math.max(position.y - shapeControlsSize.height - shapeControlDist, top);
  29350. if (x + shapeControlsSize.width > right) x = right - shapeControlsSize.width;
  29351. return vectorCreate(x, y);
  29352. };
  29353. const TextLayoutChangeIcon = (locale, shape) => {
  29354. const { disableTextLayout = [] } = shape;
  29355. // is fixed size
  29356. if ("height" in shape) {
  29357. if (disableTextLayout.includes("auto-height")) {
  29358. // next is auto-width, no need to set as is empty
  29359. return locale.shapeIconButtonTextLayoutAutoWidth;
  29360. } else {
  29361. // next is auto-height
  29362. return locale.shapeIconButtonTextLayoutAutoHeight;
  29363. }
  29364. } else // is auto-height
  29365. if ("width" in shape) {
  29366. if (disableTextLayout.includes("auto-width")) {
  29367. // next is fixed-size
  29368. return locale.shapeIconButtonTextLayoutFixedSize;
  29369. } else {
  29370. // next is auto-width, no need to set as is empty
  29371. return locale.shapeIconButtonTextLayoutAutoWidth;
  29372. }
  29373. } else // is auto-width
  29374. {
  29375. // next is fixed-size
  29376. if (disableTextLayout.includes("fixed-size")) {
  29377. // next is fixed-size
  29378. return locale.shapeIconButtonTextLayoutAutoHeight;
  29379. } else {
  29380. // next is auto-width, no need to set as is empty
  29381. return locale.shapeIconButtonTextLayoutFixedSize;
  29382. }
  29383. }
  29384. };
  29385. const TextLayoutChangeLabel = (locale, shape) => {
  29386. const { disableTextLayout = [] } = shape;
  29387. // is fixed size
  29388. if ("height" in shape) {
  29389. if (disableTextLayout.includes("auto-height")) {
  29390. // next is auto-width, no need to set as is empty
  29391. return locale.shapeTitleButtonTextLayoutAutoWidth;
  29392. } else {
  29393. // next is auto-height
  29394. return locale.shapeTitleButtonTextLayoutAutoHeight;
  29395. }
  29396. } else // is auto-height
  29397. if ("width" in shape) {
  29398. if (disableTextLayout.includes("auto-width")) {
  29399. // next is fixed-size
  29400. return locale.shapeTitleButtonTextLayoutFixedSize;
  29401. } else {
  29402. // next is auto-width, no need to set as is empty
  29403. return locale.shapeTitleButtonTextLayoutAutoWidth;
  29404. }
  29405. } else // is auto-width
  29406. {
  29407. // next is fixed-size
  29408. if (disableTextLayout.includes("fixed-size")) {
  29409. // next is fixed-size
  29410. return locale.shapeTitleButtonTextLayoutAutoHeight;
  29411. } else {
  29412. // next is auto-width, no need to set as is empty
  29413. return locale.shapeTitleButtonTextLayoutFixedSize;
  29414. }
  29415. }
  29416. };
  29417. const handleNudge = e => {
  29418. const shape = getActiveMarkupItem();
  29419. if (!shape) return;
  29420. if (!shapeCanMove(shape)) return;
  29421. interactionShape = shape;
  29422. interactionShapeOriginComputed = shapeComputeDisplay(shapeDeepCopy(interactionShape), parentRect);
  29423. translateShape(interactionShape, interactionShapeOriginComputed, e.detail);
  29424. };
  29425. // shape navigator
  29426. let showShapeList = false;
  29427. const handleFocusIn = e => {
  29428. $$invalidate(12, showShapeList = true);
  29429. };
  29430. const handleFocusOut = ({ relatedTarget }) => {
  29431. // still in list
  29432. if (relatedTarget && relatedTarget.classList.contains("shape-selector__button")) return;
  29433. $$invalidate(12, showShapeList = false);
  29434. };
  29435. function measure_handler(event) {
  29436. bubble($$self, event);
  29437. }
  29438. const click_handler = (index, e) => selectShape(markup[index]);
  29439. function textarea_binding($$value) {
  29440. binding_callbacks[$$value ? "unshift" : "push"](() => {
  29441. textInput = $$value;
  29442. $$invalidate(11, textInput);
  29443. });
  29444. }
  29445. function textarea_input_handler() {
  29446. textInputText = this.value;
  29447. (((($$invalidate(15, textInputText), $$invalidate(9, shouldRenderTextInput)), $$invalidate(100, activeMarkup)), $$invalidate(109, isTextMarkupSelected)), $$invalidate(0, markup));
  29448. }
  29449. const measure_handler_1 = e => $$invalidate(5, shapeControlsSize = e.detail);
  29450. const interactable_function = e => getEventPositionInEditor(e, rootRect);
  29451. $$self.$$set = $$props => {
  29452. if ("uid" in $$props) $$invalidate(43, uid = $$props.uid);
  29453. if ("ui" in $$props) $$invalidate(42, ui = $$props.ui);
  29454. if ("markup" in $$props) $$invalidate(0, markup = $$props.markup);
  29455. if ("offset" in $$props) $$invalidate(1, offset = $$props.offset);
  29456. if ("contextRotation" in $$props) $$invalidate(44, contextRotation = $$props.contextRotation);
  29457. if ("contextFlipX" in $$props) $$invalidate(45, contextFlipX = $$props.contextFlipX);
  29458. if ("contextFlipY" in $$props) $$invalidate(46, contextFlipY = $$props.contextFlipY);
  29459. if ("contextScale" in $$props) $$invalidate(47, contextScale = $$props.contextScale);
  29460. if ("active" in $$props) $$invalidate(48, active = $$props.active);
  29461. if ("opacity" in $$props) $$invalidate(49, opacity = $$props.opacity);
  29462. if ("parentRect" in $$props) $$invalidate(50, parentRect = $$props.parentRect);
  29463. if ("rootRect" in $$props) $$invalidate(2, rootRect = $$props.rootRect);
  29464. if ("utilRect" in $$props) $$invalidate(51, utilRect = $$props.utilRect);
  29465. if ("oninteractionstart" in $$props) $$invalidate(52, oninteractionstart = $$props.oninteractionstart);
  29466. if ("oninteractionupdate" in $$props) $$invalidate(53, oninteractionupdate = $$props.oninteractionupdate);
  29467. if ("oninteractionrelease" in $$props) $$invalidate(54, oninteractionrelease = $$props.oninteractionrelease);
  29468. if ("oninteractionend" in $$props) $$invalidate(55, oninteractionend = $$props.oninteractionend);
  29469. if ("onaddshape" in $$props) $$invalidate(56, onaddshape = $$props.onaddshape);
  29470. if ("onupdateshape" in $$props) $$invalidate(57, onupdateshape = $$props.onupdateshape);
  29471. if ("onselectshape" in $$props) $$invalidate(58, onselectshape = $$props.onselectshape);
  29472. if ("onremoveshape" in $$props) $$invalidate(59, onremoveshape = $$props.onremoveshape);
  29473. if ("beforeSelectShape" in $$props) $$invalidate(60, beforeSelectShape = $$props.beforeSelectShape);
  29474. if ("beforeDeselectShape" in $$props) $$invalidate(61, beforeDeselectShape = $$props.beforeDeselectShape);
  29475. if ("beforeRemoveShape" in $$props) $$invalidate(62, beforeRemoveShape = $$props.beforeRemoveShape);
  29476. if ("beforeUpdateShape" in $$props) $$invalidate(63, beforeUpdateShape = $$props.beforeUpdateShape);
  29477. if ("willRenderShapeControls" in $$props) $$invalidate(64, willRenderShapeControls = $$props.willRenderShapeControls);
  29478. if ("mapEditorPointToImagePoint" in $$props) $$invalidate(65, mapEditorPointToImagePoint = $$props.mapEditorPointToImagePoint);
  29479. if ("mapImagePointToEditorPoint" in $$props) $$invalidate(66, mapImagePointToEditorPoint = $$props.mapImagePointToEditorPoint);
  29480. if ("eraseRadius" in $$props) $$invalidate(67, eraseRadius = $$props.eraseRadius);
  29481. if ("selectRadius" in $$props) $$invalidate(68, selectRadius = $$props.selectRadius);
  29482. if ("enableButtonFlipVertical" in $$props) $$invalidate(69, enableButtonFlipVertical = $$props.enableButtonFlipVertical);
  29483. if ("enableTapToAddText" in $$props) $$invalidate(70, enableTapToAddText = $$props.enableTapToAddText);
  29484. if ("locale" in $$props) $$invalidate(3, locale = $$props.locale);
  29485. };
  29486. $$self.$$.update = () => {
  29487. if ($$self.$$.dirty[0] & /*markup*/ 1) {
  29488. $$invalidate(100, activeMarkup = markup && (getMarkupItemDraft() || getActiveMarkupItem()));
  29489. }
  29490. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29491. $$invalidate(101, activeShapeId = activeMarkup && !shapeIsDraft(activeMarkup)
  29492. ? activeMarkup.id
  29493. : undefined);
  29494. }
  29495. if ($$self.$$.dirty[0] & /*rootRect*/ 4 | $$self.$$.dirty[1] & /*parentRect*/ 524288 | $$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29496. // rootRect is in there so it recomputes the shape when the editor is resized
  29497. $$invalidate(102, activeMarkupComputed = rootRect && activeMarkup && shapeComputeDisplay(shapeDeepCopy(activeMarkup), parentRect));
  29498. }
  29499. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29500. $$invalidate(103, activeMarkupItemIsDraft = !!(activeMarkup && shapeIsDraft(activeMarkup)));
  29501. }
  29502. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29503. $$invalidate(104, shapeProps = activeMarkup || undefined);
  29504. }
  29505. if ($$self.$$.dirty[1] & /*opacity*/ 262144 | $$self.$$.dirty[3] & /*activeMarkup, activeMarkupComputed*/ 640) {
  29506. // TODO: we use opacity to trigger a redraw of the active points, this should be changed to the image zoom factor in a future release
  29507. // && !shapeIsPath(activeMarkupComputed)
  29508. $$invalidate(105, shapeActivePoints = activeMarkup && opacity && getMarkupShapePoints(activeMarkupComputed) || []);
  29509. }
  29510. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29511. $$invalidate(106, allowResizeControls = activeMarkup && shapeCanResize(activeMarkup) && !shapeIsTextEditing(activeMarkup));
  29512. }
  29513. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29514. $$invalidate(6, allowRotateControls = activeMarkup && shapeCanRotate(activeMarkup) && !shapeIsTextEditing(activeMarkup));
  29515. }
  29516. if ($$self.$$.dirty[3] & /*allowResizeControls, activeMarkup*/ 8320) {
  29517. $$invalidate(13, allowedResizeControls = allowResizeControls && hasProp(activeMarkup, "text") && !activeMarkup.height
  29518. ? "horizontal"
  29519. : allowResizeControls);
  29520. }
  29521. if ($$self.$$.dirty[3] & /*activeMarkup, shapeActivePoints*/ 4224) {
  29522. $$invalidate(7, shouldRenderShapeManipulator = activeMarkup && shapeActivePoints.length > 1);
  29523. }
  29524. if ($$self.$$.dirty[2] & /*mapImagePointToEditorPoint*/ 16 | $$self.$$.dirty[3] & /*shapeActivePoints*/ 4096) {
  29525. $$invalidate(107, shapeActiveScreenPoints = shapeActivePoints.map(mapImagePointToEditorPoint));
  29526. }
  29527. if ($$self.$$.dirty[0] & /*offset*/ 2 | $$self.$$.dirty[3] & /*shapeActiveScreenPoints*/ 16384) {
  29528. $$invalidate(8, shapeManipulatorPoints = shapeActiveScreenPoints.map(point => vectorCreate(point.x - offset.x, point.y - offset.y)));
  29529. }
  29530. if ($$self.$$.dirty[0] & /*shouldRenderShapeManipulator, allowRotateControls*/ 192 | $$self.$$.dirty[1] & /*opacity*/ 262144 | $$self.$$.dirty[3] & /*activeMarkupComputed*/ 512) {
  29531. // TODO: we use opacity to trigger a redraw of the active points, this should be changed to the image zoom factor in a future release
  29532. $$invalidate(108, shapeManipulatorRotationPoint = shouldRenderShapeManipulator && allowRotateControls && opacity && getShapeRotationPointOnScreen(activeMarkupComputed));
  29533. }
  29534. if ($$self.$$.dirty[0] & /*offset*/ 2 | $$self.$$.dirty[3] & /*shapeManipulatorRotationPoint*/ 32768) {
  29535. $$invalidate(14, shapeManipulatorRotationPointPosition = shapeManipulatorRotationPoint && vectorCreate(shapeManipulatorRotationPoint.position.x - offset.x, shapeManipulatorRotationPoint.position.y - offset.y));
  29536. }
  29537. if ($$self.$$.dirty[0] & /*shapeManipulatorPoints*/ 256 | $$self.$$.dirty[1] & /*active, opacity*/ 393216 | $$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29538. if (active) {
  29539. // show when something selected
  29540. if (opacity > 0) {
  29541. claimManipulatorLines();
  29542. // don't draw for line
  29543. const isPathDraft = activeMarkup && shapeIsDraft(activeMarkup) && shapeIsPath(activeMarkup);
  29544. if (shapeManipulatorPoints.length > 2 && !isPathDraft) {
  29545. redrawManipulatorLines(opacity);
  29546. } else {
  29547. removeMarkupManipulatorLines();
  29548. }
  29549. } else // hide when nothing selected
  29550. if (!activeMarkup) {
  29551. redrawManipulatorLines(opacity);
  29552. }
  29553. } else if (shouldManipulateLines()) {
  29554. redrawManipulatorLines(opacity);
  29555. }
  29556. }
  29557. if ($$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29558. $$invalidate(109, isTextMarkupSelected = activeMarkup && shapeIsText(activeMarkup));
  29559. }
  29560. if ($$self.$$.dirty[3] & /*isTextMarkupSelected, activeMarkup*/ 65664) {
  29561. $$invalidate(9, shouldRenderTextInput = isTextMarkupSelected && shapeCanInput(activeMarkup) !== false && activeMarkup.isEditing);
  29562. }
  29563. if ($$self.$$.dirty[0] & /*shouldRenderTextInput*/ 512) {
  29564. $$invalidate(110, textShapeOrigin = shouldRenderTextInput
  29565. ? getTextShapeOriginSnapshot()
  29566. : undefined);
  29567. }
  29568. if ($$self.$$.dirty[1] & /*parentRect*/ 524288 | $$self.$$.dirty[3] & /*textShapeOrigin*/ 131072) {
  29569. $$invalidate(111, textShapeDisplayOrigin = textShapeOrigin && shapeComputeDisplay({ ...textShapeOrigin }, parentRect));
  29570. }
  29571. if ($$self.$$.dirty[3] & /*textShapeDisplayOrigin*/ 262144) {
  29572. $$invalidate(112, textSizeDisplayOrigin = textShapeDisplayOrigin && textSize(textShapeDisplayOrigin.text, textShapeDisplayOrigin));
  29573. }
  29574. if ($$self.$$.dirty[3] & /*textShapeDisplayOrigin, textSizeDisplayOrigin*/ 786432) {
  29575. textRectDisplayOrigin = textShapeDisplayOrigin && rectCreate(textShapeDisplayOrigin.x, textShapeDisplayOrigin.y, textSizeDisplayOrigin.width, textSizeDisplayOrigin.height);
  29576. }
  29577. if ($$self.$$.dirty[0] & /*shouldRenderTextInput*/ 512 | $$self.$$.dirty[3] & /*activeMarkup*/ 128) {
  29578. $$invalidate(15, textInputText = shouldRenderTextInput ? activeMarkup.text : "");
  29579. }
  29580. if ($$self.$$.dirty[0] & /*shouldRenderTextInput*/ 512 | $$self.$$.dirty[3] & /*shapeProps*/ 2048) {
  29581. $$invalidate(16, markupTextInputStyle = shouldRenderTextInput && `
  29582. text-align: ${shapeProps.textAlign || "left"};
  29583. font-family: ${shapeProps.fontFamily || "sans-serif"};
  29584. `);
  29585. }
  29586. if ($$self.$$.dirty[3] & /*activeMarkup, activeMarkupItemIsDraft, controlledMarkupItem*/ 1049728) {
  29587. $$invalidate(113, controlledMarkupItem = activeMarkup && !activeMarkupItemIsDraft
  29588. ? activeMarkup
  29589. : controlledMarkupItem);
  29590. }
  29591. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29592. $$invalidate(114, allowShapeFlip = controlledMarkupItem && shapeCanFlip(controlledMarkupItem));
  29593. }
  29594. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29595. $$invalidate(115, allowShapeChangeTextLayout = controlledMarkupItem && shapeCanChangeTextLayout(controlledMarkupItem));
  29596. }
  29597. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29598. $$invalidate(116, allowShapeDuplicate = controlledMarkupItem && shapeCanDuplicate(controlledMarkupItem));
  29599. }
  29600. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29601. $$invalidate(117, allowShapeRemove = controlledMarkupItem && shapeCanRemove(controlledMarkupItem));
  29602. }
  29603. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29604. $$invalidate(118, allowShapeReorder = controlledMarkupItem && shapeCanReorder(controlledMarkupItem));
  29605. }
  29606. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29607. $$invalidate(119, allowShapeInput = controlledMarkupItem && shapeCanInput(controlledMarkupItem) !== false);
  29608. }
  29609. if ($$self.$$.dirty[3] & /*controlledMarkupItem*/ 1048576) {
  29610. $$invalidate(120, allowShapeAdjustOpacity = controlledMarkupItem && hasProp(controlledMarkupItem, "backgroundImage") && shapeCanStyle(controlledMarkupItem, "opacity"));
  29611. }
  29612. if ($$self.$$.dirty[0] & /*shouldRenderTextInput*/ 512 | $$self.$$.dirty[3] & /*activeMarkup, activeMarkupItemIsDraft, isInteracting*/ 1216) {
  29613. markupControlsOpacity.set(activeMarkup && !activeMarkupItemIsDraft && !isInteracting && !shouldRenderTextInput
  29614. ? 1
  29615. : 0);
  29616. }
  29617. if ($$self.$$.dirty[0] & /*shapeManipulatorPoints*/ 256 | $$self.$$.dirty[3] & /*activeMarkup, activeMarkupItemIsDraft, markupControlsAnchorPosition*/ 268436608) {
  29618. $$invalidate(121, markupControlsAnchorPosition = activeMarkup && !activeMarkupItemIsDraft
  29619. ? getMarkupControlsAnchorPosition(rectCreateFromPoints(shapeManipulatorPoints))
  29620. : markupControlsAnchorPosition);
  29621. }
  29622. if ($$self.$$.dirty[0] & /*shapeControlsSize*/ 32 | $$self.$$.dirty[1] & /*utilRect*/ 1048576 | $$self.$$.dirty[3] & /*markupControlsAnchorPosition*/ 268435456) {
  29623. $$invalidate(122, shapeControlsPosition = markupControlsAnchorPosition && shapeControlsSize && utilRect && getShapeControlPositionOnCanvas(markupControlsAnchorPosition));
  29624. }
  29625. if ($$self.$$.dirty[0] & /*$markupControlsOpacity*/ 1024 | $$self.$$.dirty[3] & /*shapeControlsPosition*/ 536870912) {
  29626. $$invalidate(17, markupControlsStyle = shapeControlsPosition && `transform: translate(${shapeControlsPosition.x}px, ${shapeControlsPosition.y}px);opacity:${$markupControlsOpacity}`);
  29627. }
  29628. if ($$self.$$.dirty[0] & /*locale*/ 8 | $$self.$$.dirty[2] & /*willRenderShapeControls, enableButtonFlipVertical*/ 132 | $$self.$$.dirty[3] & /*activeShapeId, allowShapeAdjustOpacity, activeMarkup, allowShapeFlip, allowShapeReorder, allowShapeDuplicate, allowShapeRemove, allowShapeInput, allowShapeChangeTextLayout*/ 266338688) {
  29629. $$invalidate(18, shapeControls = activeShapeId && willRenderShapeControls(
  29630. [
  29631. allowShapeAdjustOpacity && [
  29632. "div",
  29633. "alpha",
  29634. { class: "PinturaShapeControlsGroup" },
  29635. [
  29636. [
  29637. "Slider",
  29638. "adjust-opacity",
  29639. {
  29640. onchange: handleAdjustOpacity,
  29641. step: 0.01,
  29642. value: hasProp(activeMarkup, "opacity")
  29643. ? activeMarkup.opacity
  29644. : 1,
  29645. label: (value, min, max) => `${Math.round(value / max * 100)}%`,
  29646. min: 0,
  29647. max: 1,
  29648. direction: "x"
  29649. }
  29650. ]
  29651. ]
  29652. ],
  29653. [
  29654. "div",
  29655. "beta",
  29656. { class: "PinturaShapeControlsGroup" },
  29657. [
  29658. allowShapeFlip && [
  29659. "Button",
  29660. "flip-horizontal",
  29661. {
  29662. onclick: handleFlipX,
  29663. label: locale.shapeTitleButtonFlipHorizontal,
  29664. icon: locale.shapeIconButtonFlipHorizontal,
  29665. hideLabel: true
  29666. }
  29667. ],
  29668. allowShapeFlip && enableButtonFlipVertical && [
  29669. "Button",
  29670. "flip-vertical",
  29671. {
  29672. onclick: handleFlipY,
  29673. label: locale.shapeTitleButtonFlipVertical,
  29674. icon: locale.shapeIconButtonFlipVertical,
  29675. hideLabel: true
  29676. }
  29677. ],
  29678. allowShapeReorder && [
  29679. "Button",
  29680. "to-front",
  29681. {
  29682. onclick: handleMoveToFrontActiveMarkup,
  29683. label: locale.shapeTitleButtonMoveToFront,
  29684. icon: locale.shapeIconButtonMoveToFront,
  29685. hideLabel: true
  29686. }
  29687. ],
  29688. allowShapeDuplicate && [
  29689. "Button",
  29690. "duplicate",
  29691. {
  29692. onclick: handleDuplicateActiveMarkup,
  29693. label: locale.shapeTitleButtonDuplicate,
  29694. icon: locale.shapeIconButtonDuplicate,
  29695. hideLabel: true
  29696. }
  29697. ],
  29698. allowShapeRemove && [
  29699. "Button",
  29700. "remove",
  29701. {
  29702. onclick: handleRemoveActiveMarkup,
  29703. label: locale.shapeTitleButtonRemove,
  29704. icon: locale.shapeIconButtonRemove,
  29705. hideLabel: true
  29706. }
  29707. ]
  29708. ].filter(Boolean)
  29709. ],
  29710. allowShapeInput && allowShapeChangeTextLayout && [
  29711. "div",
  29712. "gamma",
  29713. { class: "PinturaShapeControlsGroup" },
  29714. [
  29715. [
  29716. "Button",
  29717. "text-layout",
  29718. {
  29719. onclick: handleTextSwitchLayout,
  29720. label: localize(TextLayoutChangeLabel, locale, activeMarkup),
  29721. icon: localize(TextLayoutChangeIcon, locale, activeMarkup),
  29722. hideLabel: true
  29723. }
  29724. ]
  29725. ]
  29726. ],
  29727. allowShapeInput && [
  29728. "div",
  29729. "delta",
  29730. { class: "PinturaShapeControlsGroup" },
  29731. [
  29732. [
  29733. "Button",
  29734. "edit-text",
  29735. {
  29736. label: locale.shapeLabelInputText,
  29737. onclick: handleEditTextActiveMarkup
  29738. }
  29739. ]
  29740. ]
  29741. ]
  29742. ].filter(Boolean),
  29743. activeShapeId
  29744. ));
  29745. }
  29746. if ($$self.$$.dirty[0] & /*markup, locale*/ 9) {
  29747. $$invalidate(19, shapeNavList = markup.filter(shapeCanSelect).filter(shape => !shapeIsDraft(shape)).map(shape => ({
  29748. id: shape.id,
  29749. color: shapeIsText(shape)
  29750. ? shape.color
  29751. : shapeIsLine(shape)
  29752. ? shape.strokeColor
  29753. : shape.backgroundColor,
  29754. name: shape.name || locale[`shapeLabelTool${capitalizeFirstLetter(shapeGetDescription(shape))}`]
  29755. })));
  29756. }
  29757. };
  29758. return [
  29759. markup,
  29760. offset,
  29761. rootRect,
  29762. locale,
  29763. selectShape,
  29764. shapeControlsSize,
  29765. allowRotateControls,
  29766. shouldRenderShapeManipulator,
  29767. shapeManipulatorPoints,
  29768. shouldRenderTextInput,
  29769. $markupControlsOpacity,
  29770. textInput,
  29771. showShapeList,
  29772. allowedResizeControls,
  29773. shapeManipulatorRotationPointPosition,
  29774. textInputText,
  29775. markupTextInputStyle,
  29776. markupControlsStyle,
  29777. shapeControls,
  29778. shapeNavList,
  29779. keysPressedStored,
  29780. handleInteractionStart,
  29781. handleInteractionUpdate,
  29782. handleInteractionRelease,
  29783. handleInteractionEnd,
  29784. handleManipulatorResizeGrab,
  29785. handleManipulatorResizeDrag,
  29786. handleManipulatorResizeEnd,
  29787. handleManipulatorRotateGrab,
  29788. handleManipulatorRotateDrag,
  29789. handleManipulatorRotateEnd,
  29790. handleKey,
  29791. handleTextInput,
  29792. handleTextInputAttempt,
  29793. handleTextInputKeyDown,
  29794. handleTextInputKeyUp,
  29795. handleTextConfirm,
  29796. handleTextCancel,
  29797. markupControlsOpacity,
  29798. handleNudge,
  29799. handleFocusIn,
  29800. handleFocusOut,
  29801. ui,
  29802. uid,
  29803. contextRotation,
  29804. contextFlipX,
  29805. contextFlipY,
  29806. contextScale,
  29807. active,
  29808. opacity,
  29809. parentRect,
  29810. utilRect,
  29811. oninteractionstart,
  29812. oninteractionupdate,
  29813. oninteractionrelease,
  29814. oninteractionend,
  29815. onaddshape,
  29816. onupdateshape,
  29817. onselectshape,
  29818. onremoveshape,
  29819. beforeSelectShape,
  29820. beforeDeselectShape,
  29821. beforeRemoveShape,
  29822. beforeUpdateShape,
  29823. willRenderShapeControls,
  29824. mapEditorPointToImagePoint,
  29825. mapImagePointToEditorPoint,
  29826. eraseRadius,
  29827. selectRadius,
  29828. enableButtonFlipVertical,
  29829. enableTapToAddText,
  29830. createShape,
  29831. eraseShape,
  29832. getMarkupItemDraft,
  29833. getMarkupItemDraftIndex,
  29834. addMarkupItemDraft,
  29835. confirmMarkupItemDraft,
  29836. discardMarkupItemDraft,
  29837. createMarkupItem,
  29838. syncShapes,
  29839. addShape,
  29840. removeMarkupShapeProps,
  29841. updateMarkupShape,
  29842. updateMarkupShapeProperty,
  29843. updateMarkupItemsShapeProperty,
  29844. updateMarkupShapeItems,
  29845. getActiveMarkupItem,
  29846. hasActiveMarkupItem,
  29847. removeShape,
  29848. removeActiveMarkupItem,
  29849. blurShapes,
  29850. deselectMarkupItem,
  29851. editMarkupItem,
  29852. finishEditMarkupItem,
  29853. removeMarkupItems,
  29854. getTextShapeRect,
  29855. getMarkupShapeRect,
  29856. getShapesNearPosition,
  29857. getShapesBetweenPoints,
  29858. isInteracting,
  29859. activeMarkup,
  29860. activeShapeId,
  29861. activeMarkupComputed,
  29862. activeMarkupItemIsDraft,
  29863. shapeProps,
  29864. shapeActivePoints,
  29865. allowResizeControls,
  29866. shapeActiveScreenPoints,
  29867. shapeManipulatorRotationPoint,
  29868. isTextMarkupSelected,
  29869. textShapeOrigin,
  29870. textShapeDisplayOrigin,
  29871. textSizeDisplayOrigin,
  29872. controlledMarkupItem,
  29873. allowShapeFlip,
  29874. allowShapeChangeTextLayout,
  29875. allowShapeDuplicate,
  29876. allowShapeRemove,
  29877. allowShapeReorder,
  29878. allowShapeInput,
  29879. allowShapeAdjustOpacity,
  29880. markupControlsAnchorPosition,
  29881. shapeControlsPosition,
  29882. measure_handler,
  29883. click_handler,
  29884. textarea_binding,
  29885. textarea_input_handler,
  29886. measure_handler_1,
  29887. interactable_function
  29888. ];
  29889. }
  29890. class ShapeLayoutEditor extends SvelteComponent {
  29891. constructor(options) {
  29892. super();
  29893. init(
  29894. this,
  29895. options,
  29896. instance$f,
  29897. create_fragment$f,
  29898. safe_not_equal,
  29899. {
  29900. uid: 43,
  29901. ui: 42,
  29902. markup: 0,
  29903. offset: 1,
  29904. contextRotation: 44,
  29905. contextFlipX: 45,
  29906. contextFlipY: 46,
  29907. contextScale: 47,
  29908. active: 48,
  29909. opacity: 49,
  29910. parentRect: 50,
  29911. rootRect: 2,
  29912. utilRect: 51,
  29913. oninteractionstart: 52,
  29914. oninteractionupdate: 53,
  29915. oninteractionrelease: 54,
  29916. oninteractionend: 55,
  29917. onaddshape: 56,
  29918. onupdateshape: 57,
  29919. onselectshape: 58,
  29920. onremoveshape: 59,
  29921. beforeSelectShape: 60,
  29922. beforeDeselectShape: 61,
  29923. beforeRemoveShape: 62,
  29924. beforeUpdateShape: 63,
  29925. willRenderShapeControls: 64,
  29926. mapEditorPointToImagePoint: 65,
  29927. mapImagePointToEditorPoint: 66,
  29928. eraseRadius: 67,
  29929. selectRadius: 68,
  29930. enableButtonFlipVertical: 69,
  29931. enableTapToAddText: 70,
  29932. locale: 3,
  29933. createShape: 71,
  29934. eraseShape: 72,
  29935. getMarkupItemDraft: 73,
  29936. getMarkupItemDraftIndex: 74,
  29937. addMarkupItemDraft: 75,
  29938. confirmMarkupItemDraft: 76,
  29939. discardMarkupItemDraft: 77,
  29940. createMarkupItem: 78,
  29941. syncShapes: 79,
  29942. addShape: 80,
  29943. removeMarkupShapeProps: 81,
  29944. updateMarkupShape: 82,
  29945. updateMarkupShapeProperty: 83,
  29946. updateMarkupItemsShapeProperty: 84,
  29947. updateMarkupShapeItems: 85,
  29948. getActiveMarkupItem: 86,
  29949. hasActiveMarkupItem: 87,
  29950. removeShape: 88,
  29951. removeActiveMarkupItem: 89,
  29952. blurShapes: 90,
  29953. selectShape: 4,
  29954. deselectMarkupItem: 91,
  29955. editMarkupItem: 92,
  29956. finishEditMarkupItem: 93,
  29957. removeMarkupItems: 94,
  29958. getTextShapeRect: 95,
  29959. getMarkupShapeRect: 96,
  29960. getShapesNearPosition: 97,
  29961. getShapesBetweenPoints: 98
  29962. },
  29963. [-1, -1, -1, -1, -1, -1]
  29964. );
  29965. }
  29966. get createShape() {
  29967. return this.$$.ctx[71];
  29968. }
  29969. get eraseShape() {
  29970. return this.$$.ctx[72];
  29971. }
  29972. get getMarkupItemDraft() {
  29973. return this.$$.ctx[73];
  29974. }
  29975. get getMarkupItemDraftIndex() {
  29976. return this.$$.ctx[74];
  29977. }
  29978. get addMarkupItemDraft() {
  29979. return this.$$.ctx[75];
  29980. }
  29981. get confirmMarkupItemDraft() {
  29982. return this.$$.ctx[76];
  29983. }
  29984. get discardMarkupItemDraft() {
  29985. return this.$$.ctx[77];
  29986. }
  29987. get createMarkupItem() {
  29988. return this.$$.ctx[78];
  29989. }
  29990. get syncShapes() {
  29991. return this.$$.ctx[79];
  29992. }
  29993. get addShape() {
  29994. return this.$$.ctx[80];
  29995. }
  29996. get removeMarkupShapeProps() {
  29997. return this.$$.ctx[81];
  29998. }
  29999. get updateMarkupShape() {
  30000. return this.$$.ctx[82];
  30001. }
  30002. get updateMarkupShapeProperty() {
  30003. return this.$$.ctx[83];
  30004. }
  30005. get updateMarkupItemsShapeProperty() {
  30006. return this.$$.ctx[84];
  30007. }
  30008. get updateMarkupShapeItems() {
  30009. return this.$$.ctx[85];
  30010. }
  30011. get getActiveMarkupItem() {
  30012. return this.$$.ctx[86];
  30013. }
  30014. get hasActiveMarkupItem() {
  30015. return this.$$.ctx[87];
  30016. }
  30017. get removeShape() {
  30018. return this.$$.ctx[88];
  30019. }
  30020. get removeActiveMarkupItem() {
  30021. return this.$$.ctx[89];
  30022. }
  30023. get blurShapes() {
  30024. return this.$$.ctx[90];
  30025. }
  30026. get selectShape() {
  30027. return this.$$.ctx[4];
  30028. }
  30029. get deselectMarkupItem() {
  30030. return this.$$.ctx[91];
  30031. }
  30032. get editMarkupItem() {
  30033. return this.$$.ctx[92];
  30034. }
  30035. get finishEditMarkupItem() {
  30036. return this.$$.ctx[93];
  30037. }
  30038. get removeMarkupItems() {
  30039. return this.$$.ctx[94];
  30040. }
  30041. get getTextShapeRect() {
  30042. return this.$$.ctx[95];
  30043. }
  30044. get getMarkupShapeRect() {
  30045. return this.$$.ctx[96];
  30046. }
  30047. get getShapesNearPosition() {
  30048. return this.$$.ctx[97];
  30049. }
  30050. get getShapesBetweenPoints() {
  30051. return this.$$.ctx[98];
  30052. }
  30053. }
  30054. /* src/core/ui/components/ShapeStyleControls.svelte generated by Svelte v3.37.0 */
  30055. function get_each_context$2(ctx, list, i) {
  30056. const child_ctx = ctx.slice();
  30057. child_ctx[7] = list[i];
  30058. return child_ctx;
  30059. }
  30060. // (21:12) {#each controls as control (control.id)}
  30061. function create_each_block$2(key_1, ctx) {
  30062. let li;
  30063. let span;
  30064. let t0_value = localize(/*control*/ ctx[7].componentProps.title, /*locale*/ ctx[1]) + "";
  30065. let t0;
  30066. let t1;
  30067. let switch_instance;
  30068. let t2;
  30069. let current;
  30070. const switch_instance_spread_levels = [/*control*/ ctx[7].componentProps];
  30071. var switch_value = /*control*/ ctx[7].component;
  30072. function switch_props(ctx) {
  30073. let switch_instance_props = {};
  30074. for (let i = 0; i < switch_instance_spread_levels.length; i += 1) {
  30075. switch_instance_props = assign(switch_instance_props, switch_instance_spread_levels[i]);
  30076. }
  30077. return { props: switch_instance_props };
  30078. }
  30079. if (switch_value) {
  30080. switch_instance = new switch_value(switch_props());
  30081. }
  30082. return {
  30083. key: key_1,
  30084. first: null,
  30085. c() {
  30086. li = element("li");
  30087. span = element("span");
  30088. t0 = text(t0_value);
  30089. t1 = space();
  30090. if (switch_instance) create_component(switch_instance.$$.fragment);
  30091. t2 = space();
  30092. attr(span, "class", "PinturaShapeStyleLabel");
  30093. attr(li, "class", "PinturaShapeStyle");
  30094. this.first = li;
  30095. },
  30096. m(target, anchor) {
  30097. insert(target, li, anchor);
  30098. append(li, span);
  30099. append(span, t0);
  30100. append(li, t1);
  30101. if (switch_instance) {
  30102. mount_component(switch_instance, li, null);
  30103. }
  30104. append(li, t2);
  30105. current = true;
  30106. },
  30107. p(new_ctx, dirty) {
  30108. ctx = new_ctx;
  30109. if ((!current || dirty & /*controls, locale*/ 3) && t0_value !== (t0_value = localize(/*control*/ ctx[7].componentProps.title, /*locale*/ ctx[1]) + "")) set_data(t0, t0_value);
  30110. const switch_instance_changes = (dirty & /*controls*/ 1)
  30111. ? get_spread_update(switch_instance_spread_levels, [get_spread_object(/*control*/ ctx[7].componentProps)])
  30112. : {};
  30113. if (switch_value !== (switch_value = /*control*/ ctx[7].component)) {
  30114. if (switch_instance) {
  30115. group_outros();
  30116. const old_component = switch_instance;
  30117. transition_out(old_component.$$.fragment, 1, 0, () => {
  30118. destroy_component(old_component, 1);
  30119. });
  30120. check_outros();
  30121. }
  30122. if (switch_value) {
  30123. switch_instance = new switch_value(switch_props());
  30124. create_component(switch_instance.$$.fragment);
  30125. transition_in(switch_instance.$$.fragment, 1);
  30126. mount_component(switch_instance, li, t2);
  30127. } else {
  30128. switch_instance = null;
  30129. }
  30130. } else if (switch_value) {
  30131. switch_instance.$set(switch_instance_changes);
  30132. }
  30133. },
  30134. i(local) {
  30135. if (current) return;
  30136. if (switch_instance) transition_in(switch_instance.$$.fragment, local);
  30137. current = true;
  30138. },
  30139. o(local) {
  30140. if (switch_instance) transition_out(switch_instance.$$.fragment, local);
  30141. current = false;
  30142. },
  30143. d(detaching) {
  30144. if (detaching) detach(li);
  30145. if (switch_instance) destroy_component(switch_instance);
  30146. }
  30147. };
  30148. }
  30149. // (19:4) <Scrollable class="PinturaShapeStyles" elasticity={scrollElasticity}>
  30150. function create_default_slot$5(ctx) {
  30151. let ul;
  30152. let each_blocks = [];
  30153. let each_1_lookup = new Map();
  30154. let current;
  30155. let each_value = /*controls*/ ctx[0];
  30156. const get_key = ctx => /*control*/ ctx[7].id;
  30157. for (let i = 0; i < each_value.length; i += 1) {
  30158. let child_ctx = get_each_context$2(ctx, each_value, i);
  30159. let key = get_key(child_ctx);
  30160. each_1_lookup.set(key, each_blocks[i] = create_each_block$2(key, child_ctx));
  30161. }
  30162. return {
  30163. c() {
  30164. ul = element("ul");
  30165. for (let i = 0; i < each_blocks.length; i += 1) {
  30166. each_blocks[i].c();
  30167. }
  30168. attr(ul, "class", "PinturaShapeStyleList");
  30169. },
  30170. m(target, anchor) {
  30171. insert(target, ul, anchor);
  30172. for (let i = 0; i < each_blocks.length; i += 1) {
  30173. each_blocks[i].m(ul, null);
  30174. }
  30175. current = true;
  30176. },
  30177. p(ctx, dirty) {
  30178. if (dirty & /*controls, localize, locale*/ 3) {
  30179. each_value = /*controls*/ ctx[0];
  30180. group_outros();
  30181. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, ul, outro_and_destroy_block, create_each_block$2, null, get_each_context$2);
  30182. check_outros();
  30183. }
  30184. },
  30185. i(local) {
  30186. if (current) return;
  30187. for (let i = 0; i < each_value.length; i += 1) {
  30188. transition_in(each_blocks[i]);
  30189. }
  30190. current = true;
  30191. },
  30192. o(local) {
  30193. for (let i = 0; i < each_blocks.length; i += 1) {
  30194. transition_out(each_blocks[i]);
  30195. }
  30196. current = false;
  30197. },
  30198. d(detaching) {
  30199. if (detaching) detach(ul);
  30200. for (let i = 0; i < each_blocks.length; i += 1) {
  30201. each_blocks[i].d();
  30202. }
  30203. }
  30204. };
  30205. }
  30206. function create_fragment$e(ctx) {
  30207. let div;
  30208. let scrollable;
  30209. let current;
  30210. scrollable = new Scrollable({
  30211. props: {
  30212. class: "PinturaShapeStyles",
  30213. elasticity: /*scrollElasticity*/ ctx[2],
  30214. $$slots: { default: [create_default_slot$5] },
  30215. $$scope: { ctx }
  30216. }
  30217. });
  30218. return {
  30219. c() {
  30220. div = element("div");
  30221. create_component(scrollable.$$.fragment);
  30222. attr(div, "style", /*style*/ ctx[3]);
  30223. },
  30224. m(target, anchor) {
  30225. insert(target, div, anchor);
  30226. mount_component(scrollable, div, null);
  30227. current = true;
  30228. },
  30229. p(ctx, [dirty]) {
  30230. const scrollable_changes = {};
  30231. if (dirty & /*scrollElasticity*/ 4) scrollable_changes.elasticity = /*scrollElasticity*/ ctx[2];
  30232. if (dirty & /*$$scope, controls, locale*/ 1027) {
  30233. scrollable_changes.$$scope = { dirty, ctx };
  30234. }
  30235. scrollable.$set(scrollable_changes);
  30236. if (!current || dirty & /*style*/ 8) {
  30237. attr(div, "style", /*style*/ ctx[3]);
  30238. }
  30239. },
  30240. i(local) {
  30241. if (current) return;
  30242. transition_in(scrollable.$$.fragment, local);
  30243. current = true;
  30244. },
  30245. o(local) {
  30246. transition_out(scrollable.$$.fragment, local);
  30247. current = false;
  30248. },
  30249. d(detaching) {
  30250. if (detaching) detach(div);
  30251. destroy_component(scrollable);
  30252. }
  30253. };
  30254. }
  30255. function instance$e($$self, $$props, $$invalidate) {
  30256. let style;
  30257. let $opacity;
  30258. let { isActive = false } = $$props;
  30259. let { controls = [] } = $$props;
  30260. let { locale } = $$props;
  30261. let { scrollElasticity } = $$props;
  30262. const opacity = spring(0);
  30263. component_subscribe($$self, opacity, value => $$invalidate(6, $opacity = value));
  30264. $$self.$$set = $$props => {
  30265. if ("isActive" in $$props) $$invalidate(5, isActive = $$props.isActive);
  30266. if ("controls" in $$props) $$invalidate(0, controls = $$props.controls);
  30267. if ("locale" in $$props) $$invalidate(1, locale = $$props.locale);
  30268. if ("scrollElasticity" in $$props) $$invalidate(2, scrollElasticity = $$props.scrollElasticity);
  30269. };
  30270. $$self.$$.update = () => {
  30271. if ($$self.$$.dirty & /*isActive*/ 32) {
  30272. opacity.set(isActive ? 1 : 0);
  30273. }
  30274. if ($$self.$$.dirty & /*$opacity, isActive*/ 96) {
  30275. $$invalidate(3, style = `opacity:${$opacity};${!isActive ? "pointer-events:none;" : ""}${$opacity <= 0 ? "visibility:hidden" : ""}`);
  30276. }
  30277. };
  30278. return [controls, locale, scrollElasticity, style, opacity, isActive, $opacity];
  30279. }
  30280. class ShapeStyleControls extends SvelteComponent {
  30281. constructor(options) {
  30282. super();
  30283. init(this, options, instance$e, create_fragment$e, safe_not_equal, {
  30284. isActive: 5,
  30285. controls: 0,
  30286. locale: 1,
  30287. scrollElasticity: 2
  30288. });
  30289. }
  30290. }
  30291. /* src/core/ui/components/ShapeStyleEditor.svelte generated by Svelte v3.37.0 */
  30292. function get_each_context$1(ctx, list, i) {
  30293. const child_ctx = ctx.slice();
  30294. child_ctx[11] = list[i].key;
  30295. child_ctx[2] = list[i].controls;
  30296. child_ctx[12] = list[i].isActive;
  30297. return child_ctx;
  30298. }
  30299. // (132:4) {#each currentStyleControlSets as { key, controls, isActive }
  30300. function create_each_block$1(key_1, ctx) {
  30301. let first;
  30302. let shapestylecontrols;
  30303. let current;
  30304. shapestylecontrols = new ShapeStyleControls({
  30305. props: {
  30306. isActive: /*isActive*/ ctx[12],
  30307. controls: /*controls*/ ctx[2],
  30308. locale: /*locale*/ ctx[0],
  30309. scrollElasticity: /*scrollElasticity*/ ctx[1]
  30310. }
  30311. });
  30312. return {
  30313. key: key_1,
  30314. first: null,
  30315. c() {
  30316. first = empty();
  30317. create_component(shapestylecontrols.$$.fragment);
  30318. this.first = first;
  30319. },
  30320. m(target, anchor) {
  30321. insert(target, first, anchor);
  30322. mount_component(shapestylecontrols, target, anchor);
  30323. current = true;
  30324. },
  30325. p(new_ctx, dirty) {
  30326. ctx = new_ctx;
  30327. const shapestylecontrols_changes = {};
  30328. if (dirty & /*currentStyleControlSets*/ 8) shapestylecontrols_changes.isActive = /*isActive*/ ctx[12];
  30329. if (dirty & /*currentStyleControlSets*/ 8) shapestylecontrols_changes.controls = /*controls*/ ctx[2];
  30330. if (dirty & /*locale*/ 1) shapestylecontrols_changes.locale = /*locale*/ ctx[0];
  30331. if (dirty & /*scrollElasticity*/ 2) shapestylecontrols_changes.scrollElasticity = /*scrollElasticity*/ ctx[1];
  30332. shapestylecontrols.$set(shapestylecontrols_changes);
  30333. },
  30334. i(local) {
  30335. if (current) return;
  30336. transition_in(shapestylecontrols.$$.fragment, local);
  30337. current = true;
  30338. },
  30339. o(local) {
  30340. transition_out(shapestylecontrols.$$.fragment, local);
  30341. current = false;
  30342. },
  30343. d(detaching) {
  30344. if (detaching) detach(first);
  30345. destroy_component(shapestylecontrols, detaching);
  30346. }
  30347. };
  30348. }
  30349. function create_fragment$d(ctx) {
  30350. let div;
  30351. let each_blocks = [];
  30352. let each_1_lookup = new Map();
  30353. let current;
  30354. let each_value = /*currentStyleControlSets*/ ctx[3];
  30355. const get_key = ctx => /*key*/ ctx[11];
  30356. for (let i = 0; i < each_value.length; i += 1) {
  30357. let child_ctx = get_each_context$1(ctx, each_value, i);
  30358. let key = get_key(child_ctx);
  30359. each_1_lookup.set(key, each_blocks[i] = create_each_block$1(key, child_ctx));
  30360. }
  30361. return {
  30362. c() {
  30363. div = element("div");
  30364. for (let i = 0; i < each_blocks.length; i += 1) {
  30365. each_blocks[i].c();
  30366. }
  30367. attr(div, "class", "PinturaShapeStyleEditor");
  30368. },
  30369. m(target, anchor) {
  30370. insert(target, div, anchor);
  30371. for (let i = 0; i < each_blocks.length; i += 1) {
  30372. each_blocks[i].m(div, null);
  30373. }
  30374. current = true;
  30375. },
  30376. p(ctx, [dirty]) {
  30377. if (dirty & /*currentStyleControlSets, locale, scrollElasticity*/ 11) {
  30378. each_value = /*currentStyleControlSets*/ ctx[3];
  30379. group_outros();
  30380. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, div, outro_and_destroy_block, create_each_block$1, null, get_each_context$1);
  30381. check_outros();
  30382. }
  30383. },
  30384. i(local) {
  30385. if (current) return;
  30386. for (let i = 0; i < each_value.length; i += 1) {
  30387. transition_in(each_blocks[i]);
  30388. }
  30389. current = true;
  30390. },
  30391. o(local) {
  30392. for (let i = 0; i < each_blocks.length; i += 1) {
  30393. transition_out(each_blocks[i]);
  30394. }
  30395. current = false;
  30396. },
  30397. d(detaching) {
  30398. if (detaching) detach(div);
  30399. for (let i = 0; i < each_blocks.length; i += 1) {
  30400. each_blocks[i].d();
  30401. }
  30402. }
  30403. };
  30404. }
  30405. function instance$d($$self, $$props, $$invalidate) {
  30406. let controlKeys;
  30407. let activeControls;
  30408. let currentStyleControlSets;
  30409. let { controls = {} } = $$props;
  30410. let { shape = undefined } = $$props;
  30411. let { onchange } = $$props;
  30412. let { locale } = $$props;
  30413. let { scrollElasticity } = $$props;
  30414. const getShapeControls = shape => {
  30415. const shapeId = shape.id || "tool";
  30416. const activeControls = controlKeys.filter(styleKey => styleKey.split("_").every(styleKey => // shape needs to have the property
  30417. hasProp(shape, styleKey) && // shape needs to be able to style the property
  30418. shapeCanStyle(shape, styleKey))).map(styleKey => {
  30419. const styleKeys = styleKey.split("_");
  30420. const currentValue = styleKeys.length > 1
  30421. ? styleKeys.map(key => shape[key])
  30422. : shape[styleKey];
  30423. let [component, componentProps] = controls[styleKey];
  30424. // is reference to other control
  30425. if (isString(component)) {
  30426. // exif if not a valid default control
  30427. if (!controls[component]) return;
  30428. // create component based on reference
  30429. const componentCustomProps = { ...componentProps };
  30430. [component, componentProps] = controls[component];
  30431. componentProps = {
  30432. ...componentProps,
  30433. ...componentCustomProps
  30434. };
  30435. }
  30436. const options = isFunction(componentProps.options)
  30437. ? componentProps.options(shape)
  30438. : componentProps.options;
  30439. return {
  30440. id: `${shapeId}_${styleKey}`,
  30441. component,
  30442. componentProps: {
  30443. ...componentProps,
  30444. // set the options prop
  30445. options,
  30446. // defaults
  30447. locale,
  30448. value: currentValue,
  30449. optionLabelClass: "PinturaButtonLabel",
  30450. onchange: detail => {
  30451. const value = isObject(detail) && !isArray(detail)
  30452. ? detail.value
  30453. : detail;
  30454. // allow custom changes
  30455. if (componentProps.onchange) componentProps.onchange(value, shape);
  30456. // internal change
  30457. const props = styleKeys.length > 1
  30458. ? styleKeys.reduce(
  30459. (prev, key, index) => {
  30460. return {
  30461. ...prev,
  30462. [key]: Array.isArray(value) ? value[index] : value
  30463. };
  30464. },
  30465. {}
  30466. )
  30467. : { [styleKey]: value };
  30468. onchange(props);
  30469. }
  30470. }
  30471. };
  30472. }).filter(Boolean);
  30473. return activeControls;
  30474. };
  30475. const styleControlSets = [];
  30476. const getStyleControlSets = (key, controls) => {
  30477. let controlSet = styleControlSets.find(controlSet => controlSet.key === key);
  30478. if (!controlSet) {
  30479. // create
  30480. controlSet = { key, controls };
  30481. // add
  30482. styleControlSets.push(controlSet);
  30483. }
  30484. // hide all
  30485. styleControlSets.forEach(controlSet => controlSet.isActive = false);
  30486. // update active controls
  30487. controlSet.controls = controls;
  30488. // show active
  30489. controlSet.isActive = true;
  30490. return styleControlSets;
  30491. };
  30492. $$self.$$set = $$props => {
  30493. if ("controls" in $$props) $$invalidate(2, controls = $$props.controls);
  30494. if ("shape" in $$props) $$invalidate(4, shape = $$props.shape);
  30495. if ("onchange" in $$props) $$invalidate(5, onchange = $$props.onchange);
  30496. if ("locale" in $$props) $$invalidate(0, locale = $$props.locale);
  30497. if ("scrollElasticity" in $$props) $$invalidate(1, scrollElasticity = $$props.scrollElasticity);
  30498. };
  30499. $$self.$$.update = () => {
  30500. if ($$self.$$.dirty & /*controls*/ 4) {
  30501. // finds the controls needed to style the selected shape
  30502. $$invalidate(6, controlKeys = Object.keys(controls).filter(key => controls[key]));
  30503. }
  30504. if ($$self.$$.dirty & /*shape, controlKeys*/ 80) {
  30505. $$invalidate(7, activeControls = shape && controlKeys && shapeCanStyle(shape)
  30506. ? getShapeControls(shape)
  30507. : []);
  30508. }
  30509. if ($$self.$$.dirty & /*shape, activeControls*/ 144) {
  30510. $$invalidate(3, currentStyleControlSets = shape
  30511. ? getStyleControlSets(Object.keys(shape).join("_"), activeControls)
  30512. : []);
  30513. }
  30514. };
  30515. return [
  30516. locale,
  30517. scrollElasticity,
  30518. controls,
  30519. currentStyleControlSets,
  30520. shape,
  30521. onchange,
  30522. controlKeys,
  30523. activeControls
  30524. ];
  30525. }
  30526. class ShapeStyleEditor extends SvelteComponent {
  30527. constructor(options) {
  30528. super();
  30529. init(this, options, instance$d, create_fragment$d, safe_not_equal, {
  30530. controls: 2,
  30531. shape: 4,
  30532. onchange: 5,
  30533. locale: 0,
  30534. scrollElasticity: 1
  30535. });
  30536. }
  30537. }
  30538. /* src/core/ui/components/DragButton.svelte generated by Svelte v3.37.0 */
  30539. function create_fragment$c(ctx) {
  30540. let button;
  30541. let mounted;
  30542. let dispose;
  30543. return {
  30544. c() {
  30545. button = element("button");
  30546. attr(button, "class", "PinturaDragButton");
  30547. attr(button, "title", /*title*/ ctx[1]);
  30548. button.disabled = /*disabled*/ ctx[2];
  30549. },
  30550. m(target, anchor) {
  30551. insert(target, button, anchor);
  30552. button.innerHTML = /*html*/ ctx[0];
  30553. /*button_binding*/ ctx[9](button);
  30554. if (!mounted) {
  30555. dispose = listen(button, "pointerdown", /*handleDown*/ ctx[4]);
  30556. mounted = true;
  30557. }
  30558. },
  30559. p(ctx, [dirty]) {
  30560. if (dirty & /*html*/ 1) button.innerHTML = /*html*/ ctx[0];
  30561. if (dirty & /*title*/ 2) {
  30562. attr(button, "title", /*title*/ ctx[1]);
  30563. }
  30564. if (dirty & /*disabled*/ 4) {
  30565. button.disabled = /*disabled*/ ctx[2];
  30566. }
  30567. },
  30568. i: noop,
  30569. o: noop,
  30570. d(detaching) {
  30571. if (detaching) detach(button);
  30572. /*button_binding*/ ctx[9](null);
  30573. mounted = false;
  30574. dispose();
  30575. }
  30576. };
  30577. }
  30578. function instance$c($$self, $$props, $$invalidate) {
  30579. let { html } = $$props;
  30580. let { title } = $$props;
  30581. let { onclick } = $$props;
  30582. let { disabled = false } = $$props;
  30583. let { ongrab = noop$1 } = $$props;
  30584. let { ondrag = noop$1 } = $$props;
  30585. let { ondrop = noop$1 } = $$props;
  30586. let element;
  30587. const isOverButton = e => vectorDistanceSquared(downPosition, vectorCreate(e.pageX, e.pageY)) < 256;
  30588. let downPosition;
  30589. const handleDown = e => {
  30590. downPosition = vectorCreate(e.pageX, e.pageY);
  30591. ongrab(e);
  30592. document.documentElement.addEventListener("pointermove", handleMove);
  30593. document.documentElement.addEventListener("pointerup", handleUp);
  30594. };
  30595. const handleUp = e => {
  30596. document.documentElement.removeEventListener("pointermove", handleMove);
  30597. document.documentElement.removeEventListener("pointerup", handleUp);
  30598. const upPosition = vectorCreate(e.pageX, e.pageY);
  30599. // must have moved enough distance to drop
  30600. if (vectorDistanceSquared(downPosition, upPosition) < 32) return onclick(e);
  30601. // cant drop in button /
  30602. if (isOverButton(e)) return;
  30603. // was dragging
  30604. ondrop(e);
  30605. };
  30606. const handleMove = e => {
  30607. // must have moved enough distance from button
  30608. if (isOverButton(e)) return;
  30609. // dragging out of button
  30610. ondrag(e);
  30611. };
  30612. function button_binding($$value) {
  30613. binding_callbacks[$$value ? "unshift" : "push"](() => {
  30614. element = $$value;
  30615. $$invalidate(3, element);
  30616. });
  30617. }
  30618. $$self.$$set = $$props => {
  30619. if ("html" in $$props) $$invalidate(0, html = $$props.html);
  30620. if ("title" in $$props) $$invalidate(1, title = $$props.title);
  30621. if ("onclick" in $$props) $$invalidate(5, onclick = $$props.onclick);
  30622. if ("disabled" in $$props) $$invalidate(2, disabled = $$props.disabled);
  30623. if ("ongrab" in $$props) $$invalidate(6, ongrab = $$props.ongrab);
  30624. if ("ondrag" in $$props) $$invalidate(7, ondrag = $$props.ondrag);
  30625. if ("ondrop" in $$props) $$invalidate(8, ondrop = $$props.ondrop);
  30626. };
  30627. return [
  30628. html,
  30629. title,
  30630. disabled,
  30631. element,
  30632. handleDown,
  30633. onclick,
  30634. ongrab,
  30635. ondrag,
  30636. ondrop,
  30637. button_binding
  30638. ];
  30639. }
  30640. class DragButton extends SvelteComponent {
  30641. constructor(options) {
  30642. super();
  30643. init(this, options, instance$c, create_fragment$c, safe_not_equal, {
  30644. html: 0,
  30645. title: 1,
  30646. onclick: 5,
  30647. disabled: 2,
  30648. ongrab: 6,
  30649. ondrag: 7,
  30650. ondrop: 8
  30651. });
  30652. }
  30653. }
  30654. /* src/core/ui/components/ShapePresetsList.svelte generated by Svelte v3.37.0 */
  30655. function get_each_context(ctx, list, i) {
  30656. const child_ctx = ctx.slice();
  30657. child_ctx[14] = list[i];
  30658. return child_ctx;
  30659. }
  30660. // (25:4) {#each presets as preset (preset.id)}
  30661. function create_each_block(key_1, ctx) {
  30662. let li;
  30663. let dragbutton;
  30664. let t;
  30665. let didMountPresetThumb_action;
  30666. let current;
  30667. let mounted;
  30668. let dispose;
  30669. function func() {
  30670. return /*func*/ ctx[10](/*preset*/ ctx[14]);
  30671. }
  30672. function func_1(...args) {
  30673. return /*func_1*/ ctx[11](/*preset*/ ctx[14], ...args);
  30674. }
  30675. function func_2(...args) {
  30676. return /*func_2*/ ctx[12](/*preset*/ ctx[14], ...args);
  30677. }
  30678. function func_3(...args) {
  30679. return /*func_3*/ ctx[13](/*preset*/ ctx[14], ...args);
  30680. }
  30681. dragbutton = new DragButton({
  30682. props: {
  30683. onclick: func,
  30684. ongrab: func_1,
  30685. ondrag: func_2,
  30686. ondrop: func_3,
  30687. disabled: /*disabled*/ ctx[1] || /*preset*/ ctx[14].disabled,
  30688. title: /*preset*/ ctx[14].title,
  30689. html: /*preset*/ ctx[14].thumb
  30690. }
  30691. });
  30692. return {
  30693. key: key_1,
  30694. first: null,
  30695. c() {
  30696. li = element("li");
  30697. create_component(dragbutton.$$.fragment);
  30698. t = space();
  30699. attr(li, "class", "PinturaShapePreset");
  30700. attr(li, "style", /*style*/ ctx[6]);
  30701. this.first = li;
  30702. },
  30703. m(target, anchor) {
  30704. insert(target, li, anchor);
  30705. mount_component(dragbutton, li, null);
  30706. append(li, t);
  30707. current = true;
  30708. if (!mounted) {
  30709. dispose = action_destroyer(didMountPresetThumb_action = /*didMountPresetThumb*/ ctx[8].call(null, li, /*preset*/ ctx[14]));
  30710. mounted = true;
  30711. }
  30712. },
  30713. p(new_ctx, dirty) {
  30714. ctx = new_ctx;
  30715. const dragbutton_changes = {};
  30716. if (dirty & /*onclickpreset, presets*/ 5) dragbutton_changes.onclick = func;
  30717. if (dirty & /*ongrabpreset, presets*/ 9) dragbutton_changes.ongrab = func_1;
  30718. if (dirty & /*ondragpreset, presets*/ 17) dragbutton_changes.ondrag = func_2;
  30719. if (dirty & /*ondroppreset, presets*/ 33) dragbutton_changes.ondrop = func_3;
  30720. if (dirty & /*disabled, presets*/ 3) dragbutton_changes.disabled = /*disabled*/ ctx[1] || /*preset*/ ctx[14].disabled;
  30721. if (dirty & /*presets*/ 1) dragbutton_changes.title = /*preset*/ ctx[14].title;
  30722. if (dirty & /*presets*/ 1) dragbutton_changes.html = /*preset*/ ctx[14].thumb;
  30723. dragbutton.$set(dragbutton_changes);
  30724. if (!current || dirty & /*style*/ 64) {
  30725. attr(li, "style", /*style*/ ctx[6]);
  30726. }
  30727. if (didMountPresetThumb_action && is_function(didMountPresetThumb_action.update) && dirty & /*presets*/ 1) didMountPresetThumb_action.update.call(null, /*preset*/ ctx[14]);
  30728. },
  30729. i(local) {
  30730. if (current) return;
  30731. transition_in(dragbutton.$$.fragment, local);
  30732. current = true;
  30733. },
  30734. o(local) {
  30735. transition_out(dragbutton.$$.fragment, local);
  30736. current = false;
  30737. },
  30738. d(detaching) {
  30739. if (detaching) detach(li);
  30740. destroy_component(dragbutton);
  30741. mounted = false;
  30742. dispose();
  30743. }
  30744. };
  30745. }
  30746. function create_fragment$b(ctx) {
  30747. let ul;
  30748. let each_blocks = [];
  30749. let each_1_lookup = new Map();
  30750. let current;
  30751. let each_value = /*presets*/ ctx[0];
  30752. const get_key = ctx => /*preset*/ ctx[14].id;
  30753. for (let i = 0; i < each_value.length; i += 1) {
  30754. let child_ctx = get_each_context(ctx, each_value, i);
  30755. let key = get_key(child_ctx);
  30756. each_1_lookup.set(key, each_blocks[i] = create_each_block(key, child_ctx));
  30757. }
  30758. return {
  30759. c() {
  30760. ul = element("ul");
  30761. for (let i = 0; i < each_blocks.length; i += 1) {
  30762. each_blocks[i].c();
  30763. }
  30764. attr(ul, "class", "PinturaShapePresetsList");
  30765. },
  30766. m(target, anchor) {
  30767. insert(target, ul, anchor);
  30768. for (let i = 0; i < each_blocks.length; i += 1) {
  30769. each_blocks[i].m(ul, null);
  30770. }
  30771. current = true;
  30772. },
  30773. p(ctx, [dirty]) {
  30774. if (dirty & /*style, presets, onclickpreset, ongrabpreset, ondragpreset, ondroppreset, disabled*/ 127) {
  30775. each_value = /*presets*/ ctx[0];
  30776. group_outros();
  30777. each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, ul, outro_and_destroy_block, create_each_block, null, get_each_context);
  30778. check_outros();
  30779. }
  30780. },
  30781. i(local) {
  30782. if (current) return;
  30783. for (let i = 0; i < each_value.length; i += 1) {
  30784. transition_in(each_blocks[i]);
  30785. }
  30786. current = true;
  30787. },
  30788. o(local) {
  30789. for (let i = 0; i < each_blocks.length; i += 1) {
  30790. transition_out(each_blocks[i]);
  30791. }
  30792. current = false;
  30793. },
  30794. d(detaching) {
  30795. if (detaching) detach(ul);
  30796. for (let i = 0; i < each_blocks.length; i += 1) {
  30797. each_blocks[i].d();
  30798. }
  30799. }
  30800. };
  30801. }
  30802. function instance$b($$self, $$props, $$invalidate) {
  30803. let style;
  30804. let $anim;
  30805. let { presets } = $$props;
  30806. let { disabled = undefined } = $$props;
  30807. let { onclickpreset } = $$props;
  30808. let { ongrabpreset = undefined } = $$props;
  30809. let { ondragpreset = undefined } = $$props;
  30810. let { ondroppreset = undefined } = $$props;
  30811. const anim = tweened(0, { duration: 300 });
  30812. component_subscribe($$self, anim, value => $$invalidate(9, $anim = value));
  30813. const didMountPresetThumb = (element, item) => item.mount && item.mount(element.firstChild, item);
  30814. onMount(() => anim.set(1));
  30815. const func = preset => onclickpreset(preset.id);
  30816. const func_1 = (preset, e) => ongrabpreset && ongrabpreset(preset.id, e);
  30817. const func_2 = (preset, e) => ondragpreset && ondragpreset(preset.id, e);
  30818. const func_3 = (preset, e) => ondroppreset && ondroppreset(preset.id, e);
  30819. $$self.$$set = $$props => {
  30820. if ("presets" in $$props) $$invalidate(0, presets = $$props.presets);
  30821. if ("disabled" in $$props) $$invalidate(1, disabled = $$props.disabled);
  30822. if ("onclickpreset" in $$props) $$invalidate(2, onclickpreset = $$props.onclickpreset);
  30823. if ("ongrabpreset" in $$props) $$invalidate(3, ongrabpreset = $$props.ongrabpreset);
  30824. if ("ondragpreset" in $$props) $$invalidate(4, ondragpreset = $$props.ondragpreset);
  30825. if ("ondroppreset" in $$props) $$invalidate(5, ondroppreset = $$props.ondroppreset);
  30826. };
  30827. $$self.$$.update = () => {
  30828. if ($$self.$$.dirty & /*$anim*/ 512) {
  30829. $$invalidate(6, style = `opacity:${$anim}`);
  30830. }
  30831. };
  30832. return [
  30833. presets,
  30834. disabled,
  30835. onclickpreset,
  30836. ongrabpreset,
  30837. ondragpreset,
  30838. ondroppreset,
  30839. style,
  30840. anim,
  30841. didMountPresetThumb,
  30842. $anim,
  30843. func,
  30844. func_1,
  30845. func_2,
  30846. func_3
  30847. ];
  30848. }
  30849. class ShapePresetsList extends SvelteComponent {
  30850. constructor(options) {
  30851. super();
  30852. init(this, options, instance$b, create_fragment$b, safe_not_equal, {
  30853. presets: 0,
  30854. disabled: 1,
  30855. onclickpreset: 2,
  30856. ongrabpreset: 3,
  30857. ondragpreset: 4,
  30858. ondroppreset: 5
  30859. });
  30860. }
  30861. }
  30862. var isSVGMarkup = (str) => /<svg /.test(str);
  30863. /* src/core/ui/components/ShapePresetsPalette.svelte generated by Svelte v3.37.0 */
  30864. function create_if_block_6(ctx) {
  30865. let dynamiccomponenttree;
  30866. let current;
  30867. dynamiccomponenttree = new DynamicComponentTree_1({
  30868. props: { items: /*presetToolbar*/ ctx[13] }
  30869. });
  30870. return {
  30871. c() {
  30872. create_component(dynamiccomponenttree.$$.fragment);
  30873. },
  30874. m(target, anchor) {
  30875. mount_component(dynamiccomponenttree, target, anchor);
  30876. current = true;
  30877. },
  30878. p(ctx, dirty) {
  30879. const dynamiccomponenttree_changes = {};
  30880. if (dirty & /*presetToolbar*/ 8192) dynamiccomponenttree_changes.items = /*presetToolbar*/ ctx[13];
  30881. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  30882. },
  30883. i(local) {
  30884. if (current) return;
  30885. transition_in(dynamiccomponenttree.$$.fragment, local);
  30886. current = true;
  30887. },
  30888. o(local) {
  30889. transition_out(dynamiccomponenttree.$$.fragment, local);
  30890. current = false;
  30891. },
  30892. d(detaching) {
  30893. destroy_component(dynamiccomponenttree, detaching);
  30894. }
  30895. };
  30896. }
  30897. // (171:4) {#if shouldRenderPresets}
  30898. function create_if_block$1(ctx) {
  30899. let current_block_type_index;
  30900. let if_block;
  30901. let if_block_anchor;
  30902. let current;
  30903. const if_block_creators = [create_if_block_1$1, create_else_block$1];
  30904. const if_blocks = [];
  30905. function select_block_type_1(ctx, dirty) {
  30906. if (/*shouldGroupPresets*/ ctx[7]) return 0;
  30907. return 1;
  30908. }
  30909. current_block_type_index = select_block_type_1(ctx);
  30910. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  30911. return {
  30912. c() {
  30913. if_block.c();
  30914. if_block_anchor = empty();
  30915. },
  30916. m(target, anchor) {
  30917. if_blocks[current_block_type_index].m(target, anchor);
  30918. insert(target, if_block_anchor, anchor);
  30919. current = true;
  30920. },
  30921. p(ctx, dirty) {
  30922. let previous_block_index = current_block_type_index;
  30923. current_block_type_index = select_block_type_1(ctx);
  30924. if (current_block_type_index === previous_block_index) {
  30925. if_blocks[current_block_type_index].p(ctx, dirty);
  30926. } else {
  30927. group_outros();
  30928. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  30929. if_blocks[previous_block_index] = null;
  30930. });
  30931. check_outros();
  30932. if_block = if_blocks[current_block_type_index];
  30933. if (!if_block) {
  30934. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  30935. if_block.c();
  30936. } else {
  30937. if_block.p(ctx, dirty);
  30938. }
  30939. transition_in(if_block, 1);
  30940. if_block.m(if_block_anchor.parentNode, if_block_anchor);
  30941. }
  30942. },
  30943. i(local) {
  30944. if (current) return;
  30945. transition_in(if_block);
  30946. current = true;
  30947. },
  30948. o(local) {
  30949. transition_out(if_block);
  30950. current = false;
  30951. },
  30952. d(detaching) {
  30953. if_blocks[current_block_type_index].d(detaching);
  30954. if (detaching) detach(if_block_anchor);
  30955. }
  30956. };
  30957. }
  30958. // (221:8) {:else}
  30959. function create_else_block$1(ctx) {
  30960. let div;
  30961. let t;
  30962. let scrollable;
  30963. let current;
  30964. let if_block = /*presetToolbar*/ ctx[13] && create_if_block_5$1(ctx);
  30965. scrollable = new Scrollable({
  30966. props: {
  30967. scrollAutoCancel: /*shouldRenderPresets*/ ctx[6],
  30968. elasticity: /*scrollElasticity*/ ctx[0],
  30969. $$slots: { default: [create_default_slot_4] },
  30970. $$scope: { ctx }
  30971. }
  30972. });
  30973. return {
  30974. c() {
  30975. div = element("div");
  30976. if (if_block) if_block.c();
  30977. t = space();
  30978. create_component(scrollable.$$.fragment);
  30979. attr(div, "class", "PinturaShapePresetsFlat");
  30980. },
  30981. m(target, anchor) {
  30982. insert(target, div, anchor);
  30983. if (if_block) if_block.m(div, null);
  30984. append(div, t);
  30985. mount_component(scrollable, div, null);
  30986. current = true;
  30987. },
  30988. p(ctx, dirty) {
  30989. if (/*presetToolbar*/ ctx[13]) {
  30990. if (if_block) {
  30991. if_block.p(ctx, dirty);
  30992. if (dirty & /*presetToolbar*/ 8192) {
  30993. transition_in(if_block, 1);
  30994. }
  30995. } else {
  30996. if_block = create_if_block_5$1(ctx);
  30997. if_block.c();
  30998. transition_in(if_block, 1);
  30999. if_block.m(div, t);
  31000. }
  31001. } else if (if_block) {
  31002. group_outros();
  31003. transition_out(if_block, 1, 1, () => {
  31004. if_block = null;
  31005. });
  31006. check_outros();
  31007. }
  31008. const scrollable_changes = {};
  31009. if (dirty & /*shouldRenderPresets*/ 64) scrollable_changes.scrollAutoCancel = /*shouldRenderPresets*/ ctx[6];
  31010. if (dirty & /*scrollElasticity*/ 1) scrollable_changes.elasticity = /*scrollElasticity*/ ctx[0];
  31011. if (dirty & /*$$scope, presetsMapped, onaddpreset, ongrabpreset, ondragpreset, ondroppreset*/ 536870974) {
  31012. scrollable_changes.$$scope = { dirty, ctx };
  31013. }
  31014. scrollable.$set(scrollable_changes);
  31015. },
  31016. i(local) {
  31017. if (current) return;
  31018. transition_in(if_block);
  31019. transition_in(scrollable.$$.fragment, local);
  31020. current = true;
  31021. },
  31022. o(local) {
  31023. transition_out(if_block);
  31024. transition_out(scrollable.$$.fragment, local);
  31025. current = false;
  31026. },
  31027. d(detaching) {
  31028. if (detaching) detach(div);
  31029. if (if_block) if_block.d();
  31030. destroy_component(scrollable);
  31031. }
  31032. };
  31033. }
  31034. // (173:8) {#if shouldGroupPresets}
  31035. function create_if_block_1$1(ctx) {
  31036. let div1;
  31037. let div0;
  31038. let t0;
  31039. let tablist;
  31040. let t1;
  31041. let tabpanels;
  31042. let current;
  31043. let if_block = /*presetToolbar*/ ctx[13] && create_if_block_4$1(ctx);
  31044. const tablist_spread_levels = [
  31045. { class: "PinturaControlList" },
  31046. { tabs: /*tabs*/ ctx[8] },
  31047. /*tabsConfig*/ ctx[11],
  31048. { layout: "compact" }
  31049. ];
  31050. let tablist_props = {
  31051. $$slots: {
  31052. default: [
  31053. create_default_slot_2,
  31054. ({ tab }) => ({ 28: tab }),
  31055. ({ tab }) => tab ? 268435456 : 0
  31056. ]
  31057. },
  31058. $$scope: { ctx }
  31059. };
  31060. for (let i = 0; i < tablist_spread_levels.length; i += 1) {
  31061. tablist_props = assign(tablist_props, tablist_spread_levels[i]);
  31062. }
  31063. tablist = new TabList({ props: tablist_props });
  31064. tablist.$on("select", /*select_handler*/ ctx[18]);
  31065. const tabpanels_spread_levels = [
  31066. { class: "PinturaControlPanels" },
  31067. { panelClass: "PinturaControlPanel" },
  31068. { panels: /*panels*/ ctx[12] },
  31069. /*tabsConfig*/ ctx[11]
  31070. ];
  31071. let tabpanels_props = {
  31072. $$slots: {
  31073. default: [
  31074. create_default_slot$4,
  31075. ({ panel, panelIsActive }) => ({ 26: panel, 27: panelIsActive }),
  31076. ({ panel, panelIsActive }) => (panel ? 67108864 : 0) | (panelIsActive ? 134217728 : 0)
  31077. ]
  31078. },
  31079. $$scope: { ctx }
  31080. };
  31081. for (let i = 0; i < tabpanels_spread_levels.length; i += 1) {
  31082. tabpanels_props = assign(tabpanels_props, tabpanels_spread_levels[i]);
  31083. }
  31084. tabpanels = new TabPanels({ props: tabpanels_props });
  31085. return {
  31086. c() {
  31087. div1 = element("div");
  31088. div0 = element("div");
  31089. if (if_block) if_block.c();
  31090. t0 = space();
  31091. create_component(tablist.$$.fragment);
  31092. t1 = space();
  31093. create_component(tabpanels.$$.fragment);
  31094. attr(div0, "class", "PinturaShapePresetsGroups");
  31095. attr(div1, "class", "PinturaShapePresetsGrouped");
  31096. },
  31097. m(target, anchor) {
  31098. insert(target, div1, anchor);
  31099. append(div1, div0);
  31100. if (if_block) if_block.m(div0, null);
  31101. append(div0, t0);
  31102. mount_component(tablist, div0, null);
  31103. append(div1, t1);
  31104. mount_component(tabpanels, div1, null);
  31105. current = true;
  31106. },
  31107. p(ctx, dirty) {
  31108. if (/*presetToolbar*/ ctx[13]) {
  31109. if (if_block) {
  31110. if_block.p(ctx, dirty);
  31111. if (dirty & /*presetToolbar*/ 8192) {
  31112. transition_in(if_block, 1);
  31113. }
  31114. } else {
  31115. if_block = create_if_block_4$1(ctx);
  31116. if_block.c();
  31117. transition_in(if_block, 1);
  31118. if_block.m(div0, t0);
  31119. }
  31120. } else if (if_block) {
  31121. group_outros();
  31122. transition_out(if_block, 1, 1, () => {
  31123. if_block = null;
  31124. });
  31125. check_outros();
  31126. }
  31127. const tablist_changes = (dirty & /*tabs, tabsConfig*/ 2304)
  31128. ? get_spread_update(tablist_spread_levels, [
  31129. tablist_spread_levels[0],
  31130. dirty & /*tabs*/ 256 && { tabs: /*tabs*/ ctx[8] },
  31131. dirty & /*tabsConfig*/ 2048 && get_spread_object(/*tabsConfig*/ ctx[11]),
  31132. tablist_spread_levels[3]
  31133. ])
  31134. : {};
  31135. if (dirty & /*$$scope, tab*/ 805306368) {
  31136. tablist_changes.$$scope = { dirty, ctx };
  31137. }
  31138. tablist.$set(tablist_changes);
  31139. const tabpanels_changes = (dirty & /*panels, tabsConfig*/ 6144)
  31140. ? get_spread_update(tabpanels_spread_levels, [
  31141. tabpanels_spread_levels[0],
  31142. tabpanels_spread_levels[1],
  31143. dirty & /*panels*/ 4096 && { panels: /*panels*/ ctx[12] },
  31144. dirty & /*tabsConfig*/ 2048 && get_spread_object(/*tabsConfig*/ ctx[11])
  31145. ])
  31146. : {};
  31147. if (dirty & /*$$scope, panelIsActive, shouldRenderPresets, scrollElasticity, presetTabs, panel, onaddpreset, ongrabpreset, ondragpreset, ondroppreset*/ 738198623) {
  31148. tabpanels_changes.$$scope = { dirty, ctx };
  31149. }
  31150. tabpanels.$set(tabpanels_changes);
  31151. },
  31152. i(local) {
  31153. if (current) return;
  31154. transition_in(if_block);
  31155. transition_in(tablist.$$.fragment, local);
  31156. transition_in(tabpanels.$$.fragment, local);
  31157. current = true;
  31158. },
  31159. o(local) {
  31160. transition_out(if_block);
  31161. transition_out(tablist.$$.fragment, local);
  31162. transition_out(tabpanels.$$.fragment, local);
  31163. current = false;
  31164. },
  31165. d(detaching) {
  31166. if (detaching) detach(div1);
  31167. if (if_block) if_block.d();
  31168. destroy_component(tablist);
  31169. destroy_component(tabpanels);
  31170. }
  31171. };
  31172. }
  31173. // (224:16) {#if presetToolbar}
  31174. function create_if_block_5$1(ctx) {
  31175. let dynamiccomponenttree;
  31176. let current;
  31177. dynamiccomponenttree = new DynamicComponentTree_1({
  31178. props: { items: /*presetToolbar*/ ctx[13] }
  31179. });
  31180. return {
  31181. c() {
  31182. create_component(dynamiccomponenttree.$$.fragment);
  31183. },
  31184. m(target, anchor) {
  31185. mount_component(dynamiccomponenttree, target, anchor);
  31186. current = true;
  31187. },
  31188. p(ctx, dirty) {
  31189. const dynamiccomponenttree_changes = {};
  31190. if (dirty & /*presetToolbar*/ 8192) dynamiccomponenttree_changes.items = /*presetToolbar*/ ctx[13];
  31191. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  31192. },
  31193. i(local) {
  31194. if (current) return;
  31195. transition_in(dynamiccomponenttree.$$.fragment, local);
  31196. current = true;
  31197. },
  31198. o(local) {
  31199. transition_out(dynamiccomponenttree.$$.fragment, local);
  31200. current = false;
  31201. },
  31202. d(detaching) {
  31203. destroy_component(dynamiccomponenttree, detaching);
  31204. }
  31205. };
  31206. }
  31207. // (228:16) <Scrollable scrollAutoCancel={shouldRenderPresets} elasticity={scrollElasticity}>
  31208. function create_default_slot_4(ctx) {
  31209. let shapepresetslist;
  31210. let current;
  31211. shapepresetslist = new ShapePresetsList({
  31212. props: {
  31213. presets: /*presetsMapped*/ ctx[5],
  31214. onclickpreset: /*onaddpreset*/ ctx[1],
  31215. ongrabpreset: /*ongrabpreset*/ ctx[2],
  31216. ondragpreset: /*ondragpreset*/ ctx[3],
  31217. ondroppreset: /*ondroppreset*/ ctx[4]
  31218. }
  31219. });
  31220. return {
  31221. c() {
  31222. create_component(shapepresetslist.$$.fragment);
  31223. },
  31224. m(target, anchor) {
  31225. mount_component(shapepresetslist, target, anchor);
  31226. current = true;
  31227. },
  31228. p(ctx, dirty) {
  31229. const shapepresetslist_changes = {};
  31230. if (dirty & /*presetsMapped*/ 32) shapepresetslist_changes.presets = /*presetsMapped*/ ctx[5];
  31231. if (dirty & /*onaddpreset*/ 2) shapepresetslist_changes.onclickpreset = /*onaddpreset*/ ctx[1];
  31232. if (dirty & /*ongrabpreset*/ 4) shapepresetslist_changes.ongrabpreset = /*ongrabpreset*/ ctx[2];
  31233. if (dirty & /*ondragpreset*/ 8) shapepresetslist_changes.ondragpreset = /*ondragpreset*/ ctx[3];
  31234. if (dirty & /*ondroppreset*/ 16) shapepresetslist_changes.ondroppreset = /*ondroppreset*/ ctx[4];
  31235. shapepresetslist.$set(shapepresetslist_changes);
  31236. },
  31237. i(local) {
  31238. if (current) return;
  31239. transition_in(shapepresetslist.$$.fragment, local);
  31240. current = true;
  31241. },
  31242. o(local) {
  31243. transition_out(shapepresetslist.$$.fragment, local);
  31244. current = false;
  31245. },
  31246. d(detaching) {
  31247. destroy_component(shapepresetslist, detaching);
  31248. }
  31249. };
  31250. }
  31251. // (176:20) {#if presetToolbar}
  31252. function create_if_block_4$1(ctx) {
  31253. let dynamiccomponenttree;
  31254. let current;
  31255. dynamiccomponenttree = new DynamicComponentTree_1({
  31256. props: { items: /*presetToolbar*/ ctx[13] }
  31257. });
  31258. return {
  31259. c() {
  31260. create_component(dynamiccomponenttree.$$.fragment);
  31261. },
  31262. m(target, anchor) {
  31263. mount_component(dynamiccomponenttree, target, anchor);
  31264. current = true;
  31265. },
  31266. p(ctx, dirty) {
  31267. const dynamiccomponenttree_changes = {};
  31268. if (dirty & /*presetToolbar*/ 8192) dynamiccomponenttree_changes.items = /*presetToolbar*/ ctx[13];
  31269. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  31270. },
  31271. i(local) {
  31272. if (current) return;
  31273. transition_in(dynamiccomponenttree.$$.fragment, local);
  31274. current = true;
  31275. },
  31276. o(local) {
  31277. transition_out(dynamiccomponenttree.$$.fragment, local);
  31278. current = false;
  31279. },
  31280. d(detaching) {
  31281. destroy_component(dynamiccomponenttree, detaching);
  31282. }
  31283. };
  31284. }
  31285. // (188:24) {#if tab.icon}
  31286. function create_if_block_3$1(ctx) {
  31287. let icon;
  31288. let current;
  31289. icon = new Icon({
  31290. props: {
  31291. $$slots: { default: [create_default_slot_3] },
  31292. $$scope: { ctx }
  31293. }
  31294. });
  31295. return {
  31296. c() {
  31297. create_component(icon.$$.fragment);
  31298. },
  31299. m(target, anchor) {
  31300. mount_component(icon, target, anchor);
  31301. current = true;
  31302. },
  31303. p(ctx, dirty) {
  31304. const icon_changes = {};
  31305. if (dirty & /*$$scope, tab*/ 805306368) {
  31306. icon_changes.$$scope = { dirty, ctx };
  31307. }
  31308. icon.$set(icon_changes);
  31309. },
  31310. i(local) {
  31311. if (current) return;
  31312. transition_in(icon.$$.fragment, local);
  31313. current = true;
  31314. },
  31315. o(local) {
  31316. transition_out(icon.$$.fragment, local);
  31317. current = false;
  31318. },
  31319. d(detaching) {
  31320. destroy_component(icon, detaching);
  31321. }
  31322. };
  31323. }
  31324. // (189:28) <Icon>
  31325. function create_default_slot_3(ctx) {
  31326. let g;
  31327. let raw_value = /*tab*/ ctx[28].icon + "";
  31328. return {
  31329. c() {
  31330. g = svg_element("g");
  31331. },
  31332. m(target, anchor) {
  31333. insert(target, g, anchor);
  31334. g.innerHTML = raw_value;
  31335. },
  31336. p(ctx, dirty) {
  31337. if (dirty & /*tab*/ 268435456 && raw_value !== (raw_value = /*tab*/ ctx[28].icon + "")) g.innerHTML = raw_value; },
  31338. d(detaching) {
  31339. if (detaching) detach(g);
  31340. }
  31341. };
  31342. }
  31343. // (191:24) {#if !tab.hideLabel}
  31344. function create_if_block_2$1(ctx) {
  31345. let span;
  31346. let t_value = /*tab*/ ctx[28].label + "";
  31347. let t;
  31348. return {
  31349. c() {
  31350. span = element("span");
  31351. t = text(t_value);
  31352. },
  31353. m(target, anchor) {
  31354. insert(target, span, anchor);
  31355. append(span, t);
  31356. },
  31357. p(ctx, dirty) {
  31358. if (dirty & /*tab*/ 268435456 && t_value !== (t_value = /*tab*/ ctx[28].label + "")) set_data(t, t_value);
  31359. },
  31360. d(detaching) {
  31361. if (detaching) detach(span);
  31362. }
  31363. };
  31364. }
  31365. // (180:20) <TabList class="PinturaControlList" {tabs} {...tabsConfig} layout="compact" on:select={({ detail }) => (tabSelected = detail)} let:tab >
  31366. function create_default_slot_2(ctx) {
  31367. let t;
  31368. let if_block1_anchor;
  31369. let current;
  31370. let if_block0 = /*tab*/ ctx[28].icon && create_if_block_3$1(ctx);
  31371. let if_block1 = !/*tab*/ ctx[28].hideLabel && create_if_block_2$1(ctx);
  31372. return {
  31373. c() {
  31374. if (if_block0) if_block0.c();
  31375. t = space();
  31376. if (if_block1) if_block1.c();
  31377. if_block1_anchor = empty();
  31378. },
  31379. m(target, anchor) {
  31380. if (if_block0) if_block0.m(target, anchor);
  31381. insert(target, t, anchor);
  31382. if (if_block1) if_block1.m(target, anchor);
  31383. insert(target, if_block1_anchor, anchor);
  31384. current = true;
  31385. },
  31386. p(ctx, dirty) {
  31387. if (/*tab*/ ctx[28].icon) {
  31388. if (if_block0) {
  31389. if_block0.p(ctx, dirty);
  31390. if (dirty & /*tab*/ 268435456) {
  31391. transition_in(if_block0, 1);
  31392. }
  31393. } else {
  31394. if_block0 = create_if_block_3$1(ctx);
  31395. if_block0.c();
  31396. transition_in(if_block0, 1);
  31397. if_block0.m(t.parentNode, t);
  31398. }
  31399. } else if (if_block0) {
  31400. group_outros();
  31401. transition_out(if_block0, 1, 1, () => {
  31402. if_block0 = null;
  31403. });
  31404. check_outros();
  31405. }
  31406. if (!/*tab*/ ctx[28].hideLabel) {
  31407. if (if_block1) {
  31408. if_block1.p(ctx, dirty);
  31409. } else {
  31410. if_block1 = create_if_block_2$1(ctx);
  31411. if_block1.c();
  31412. if_block1.m(if_block1_anchor.parentNode, if_block1_anchor);
  31413. }
  31414. } else if (if_block1) {
  31415. if_block1.d(1);
  31416. if_block1 = null;
  31417. }
  31418. },
  31419. i(local) {
  31420. if (current) return;
  31421. transition_in(if_block0);
  31422. current = true;
  31423. },
  31424. o(local) {
  31425. transition_out(if_block0);
  31426. current = false;
  31427. },
  31428. d(detaching) {
  31429. if (if_block0) if_block0.d(detaching);
  31430. if (detaching) detach(t);
  31431. if (if_block1) if_block1.d(detaching);
  31432. if (detaching) detach(if_block1_anchor);
  31433. }
  31434. };
  31435. }
  31436. // (205:20) <Scrollable scroll={panelIsActive ? { scrollOffset: 0, animate: false } : undefined} scrollAutoCancel={shouldRenderPresets} elasticity={scrollElasticity} >
  31437. function create_default_slot_1$1(ctx) {
  31438. let shapepresetslist;
  31439. let current;
  31440. shapepresetslist = new ShapePresetsList({
  31441. props: {
  31442. presets: /*presetTabs*/ ctx[10][/*panel*/ ctx[26]].items,
  31443. disabled: /*presetTabs*/ ctx[10][/*panel*/ ctx[26]].disabled,
  31444. onclickpreset: /*onaddpreset*/ ctx[1],
  31445. ongrabpreset: /*ongrabpreset*/ ctx[2],
  31446. ondragpreset: /*ondragpreset*/ ctx[3],
  31447. ondroppreset: /*ondroppreset*/ ctx[4]
  31448. }
  31449. });
  31450. return {
  31451. c() {
  31452. create_component(shapepresetslist.$$.fragment);
  31453. },
  31454. m(target, anchor) {
  31455. mount_component(shapepresetslist, target, anchor);
  31456. current = true;
  31457. },
  31458. p(ctx, dirty) {
  31459. const shapepresetslist_changes = {};
  31460. if (dirty & /*presetTabs, panel*/ 67109888) shapepresetslist_changes.presets = /*presetTabs*/ ctx[10][/*panel*/ ctx[26]].items;
  31461. if (dirty & /*presetTabs, panel*/ 67109888) shapepresetslist_changes.disabled = /*presetTabs*/ ctx[10][/*panel*/ ctx[26]].disabled;
  31462. if (dirty & /*onaddpreset*/ 2) shapepresetslist_changes.onclickpreset = /*onaddpreset*/ ctx[1];
  31463. if (dirty & /*ongrabpreset*/ 4) shapepresetslist_changes.ongrabpreset = /*ongrabpreset*/ ctx[2];
  31464. if (dirty & /*ondragpreset*/ 8) shapepresetslist_changes.ondragpreset = /*ondragpreset*/ ctx[3];
  31465. if (dirty & /*ondroppreset*/ 16) shapepresetslist_changes.ondroppreset = /*ondroppreset*/ ctx[4];
  31466. shapepresetslist.$set(shapepresetslist_changes);
  31467. },
  31468. i(local) {
  31469. if (current) return;
  31470. transition_in(shapepresetslist.$$.fragment, local);
  31471. current = true;
  31472. },
  31473. o(local) {
  31474. transition_out(shapepresetslist.$$.fragment, local);
  31475. current = false;
  31476. },
  31477. d(detaching) {
  31478. destroy_component(shapepresetslist, detaching);
  31479. }
  31480. };
  31481. }
  31482. // (197:16) <TabPanels class="PinturaControlPanels" panelClass="PinturaControlPanel" {panels} {...tabsConfig} let:panel let:panelIsActive >
  31483. function create_default_slot$4(ctx) {
  31484. let scrollable;
  31485. let current;
  31486. scrollable = new Scrollable({
  31487. props: {
  31488. scroll: /*panelIsActive*/ ctx[27]
  31489. ? { scrollOffset: 0, animate: false }
  31490. : undefined,
  31491. scrollAutoCancel: /*shouldRenderPresets*/ ctx[6],
  31492. elasticity: /*scrollElasticity*/ ctx[0],
  31493. $$slots: { default: [create_default_slot_1$1] },
  31494. $$scope: { ctx }
  31495. }
  31496. });
  31497. return {
  31498. c() {
  31499. create_component(scrollable.$$.fragment);
  31500. },
  31501. m(target, anchor) {
  31502. mount_component(scrollable, target, anchor);
  31503. current = true;
  31504. },
  31505. p(ctx, dirty) {
  31506. const scrollable_changes = {};
  31507. if (dirty & /*panelIsActive*/ 134217728) scrollable_changes.scroll = /*panelIsActive*/ ctx[27]
  31508. ? { scrollOffset: 0, animate: false }
  31509. : undefined;
  31510. if (dirty & /*shouldRenderPresets*/ 64) scrollable_changes.scrollAutoCancel = /*shouldRenderPresets*/ ctx[6];
  31511. if (dirty & /*scrollElasticity*/ 1) scrollable_changes.elasticity = /*scrollElasticity*/ ctx[0];
  31512. if (dirty & /*$$scope, presetTabs, panel, onaddpreset, ongrabpreset, ondragpreset, ondroppreset*/ 603980830) {
  31513. scrollable_changes.$$scope = { dirty, ctx };
  31514. }
  31515. scrollable.$set(scrollable_changes);
  31516. },
  31517. i(local) {
  31518. if (current) return;
  31519. transition_in(scrollable.$$.fragment, local);
  31520. current = true;
  31521. },
  31522. o(local) {
  31523. transition_out(scrollable.$$.fragment, local);
  31524. current = false;
  31525. },
  31526. d(detaching) {
  31527. destroy_component(scrollable, detaching);
  31528. }
  31529. };
  31530. }
  31531. function create_fragment$a(ctx) {
  31532. let div;
  31533. let current_block_type_index;
  31534. let if_block;
  31535. let current;
  31536. const if_block_creators = [create_if_block$1, create_if_block_6];
  31537. const if_blocks = [];
  31538. function select_block_type(ctx, dirty) {
  31539. if (/*shouldRenderPresets*/ ctx[6]) return 0;
  31540. if (/*presetToolbar*/ ctx[13]) return 1;
  31541. return -1;
  31542. }
  31543. if (~(current_block_type_index = select_block_type(ctx))) {
  31544. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  31545. }
  31546. return {
  31547. c() {
  31548. div = element("div");
  31549. if (if_block) if_block.c();
  31550. attr(div, "class", "PinturaShapePresetsPalette");
  31551. },
  31552. m(target, anchor) {
  31553. insert(target, div, anchor);
  31554. if (~current_block_type_index) {
  31555. if_blocks[current_block_type_index].m(div, null);
  31556. }
  31557. current = true;
  31558. },
  31559. p(ctx, [dirty]) {
  31560. let previous_block_index = current_block_type_index;
  31561. current_block_type_index = select_block_type(ctx);
  31562. if (current_block_type_index === previous_block_index) {
  31563. if (~current_block_type_index) {
  31564. if_blocks[current_block_type_index].p(ctx, dirty);
  31565. }
  31566. } else {
  31567. if (if_block) {
  31568. group_outros();
  31569. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  31570. if_blocks[previous_block_index] = null;
  31571. });
  31572. check_outros();
  31573. }
  31574. if (~current_block_type_index) {
  31575. if_block = if_blocks[current_block_type_index];
  31576. if (!if_block) {
  31577. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  31578. if_block.c();
  31579. } else {
  31580. if_block.p(ctx, dirty);
  31581. }
  31582. transition_in(if_block, 1);
  31583. if_block.m(div, null);
  31584. } else {
  31585. if_block = null;
  31586. }
  31587. }
  31588. },
  31589. i(local) {
  31590. if (current) return;
  31591. transition_in(if_block);
  31592. current = true;
  31593. },
  31594. o(local) {
  31595. transition_out(if_block);
  31596. current = false;
  31597. },
  31598. d(detaching) {
  31599. if (detaching) detach(div);
  31600. if (~current_block_type_index) {
  31601. if_blocks[current_block_type_index].d();
  31602. }
  31603. }
  31604. };
  31605. }
  31606. function instance$a($$self, $$props, $$invalidate) {
  31607. let presetsMapped;
  31608. let shouldRenderPresets;
  31609. let shouldGroupPresets;
  31610. let tabs;
  31611. let presetTabs;
  31612. let tabSelected;
  31613. let tabsConfig;
  31614. let panels;
  31615. let presetToolbar;
  31616. let { locale } = $$props;
  31617. let { presets } = $$props;
  31618. let { scrollElasticity } = $$props;
  31619. let { enableSelectImage = true } = $$props;
  31620. let { willRenderPresetToolbar = passthrough } = $$props;
  31621. let { onaddpreset = noop$1 } = $$props;
  31622. let { ongrabpreset = undefined } = $$props;
  31623. let { ondragpreset = undefined } = $$props;
  31624. let { ondroppreset = undefined } = $$props;
  31625. const uid = `presets-${getUniqueId()}`;
  31626. const isPresetGroup = item => isArray(item) && isString(item[0]) && isArray(item[1]);
  31627. const getPresetThumb = (value, alt = "") => {
  31628. // could be svg
  31629. if (isSVGMarkup(value)) return value;
  31630. // test if is emoji
  31631. if (isEmoji(value)) return getEmojiSVG(value, alt);
  31632. // must be URL
  31633. return `<img src="${value}" alt="${alt}"/>`;
  31634. };
  31635. const getAltFromSrc = src => getFilenameWithoutExtension(getFilenameFromURL(src));
  31636. const excludedStickerItemProps = ["src", "alt", "thumb", "shape", "id", "mount", "disabled"];
  31637. const mapPreset = item => {
  31638. let id = item;
  31639. let src;
  31640. let shape;
  31641. let shapeProps;
  31642. let thumb;
  31643. let alt;
  31644. let mount;
  31645. let disabled;
  31646. // if item is a string, it's either an emoji or a URL
  31647. if (isString(item)) {
  31648. // is emoji
  31649. if (isEmoji(item)) {
  31650. src = item;
  31651. alt = item;
  31652. thumb = getPresetThumb(src, alt);
  31653. } else // must be URL
  31654. {
  31655. src = item;
  31656. alt = getAltFromSrc(src);
  31657. thumb = getPresetThumb(src, alt);
  31658. }
  31659. } else {
  31660. // set custom thumbnail if defined
  31661. src = item.src;
  31662. alt = item.alt || (isString(src)
  31663. ? getAltFromSrc(src)
  31664. : isString(item.thumb)
  31665. ? getAltFromSrc(item.thumb)
  31666. : undefined);
  31667. thumb = getPresetThumb(item.thumb || src, alt);
  31668. shape = item.shape;
  31669. mount = item.mount;
  31670. disabled = item.disabled;
  31671. shapeProps = Object.keys(item).reduce(
  31672. (prev, curr) => {
  31673. if (excludedStickerItemProps.includes(curr)) return prev;
  31674. prev[curr] = item[curr];
  31675. return prev;
  31676. },
  31677. {}
  31678. );
  31679. }
  31680. return {
  31681. id,
  31682. src,
  31683. thumb,
  31684. shape,
  31685. shapeProps,
  31686. alt,
  31687. title: alt,
  31688. mount,
  31689. disabled
  31690. };
  31691. };
  31692. const mapPresets = items => items.map(item => {
  31693. if (isPresetGroup(item)) {
  31694. return {
  31695. ...item[2],
  31696. id: `${uid}-${item[0].toLowerCase()}`,
  31697. label: item[0],
  31698. items: mapPresets(item[1])
  31699. };
  31700. }
  31701. return mapPreset(item);
  31702. });
  31703. const select_handler = ({ detail }) => $$invalidate(9, tabSelected = detail);
  31704. $$self.$$set = $$props => {
  31705. if ("locale" in $$props) $$invalidate(14, locale = $$props.locale);
  31706. if ("presets" in $$props) $$invalidate(15, presets = $$props.presets);
  31707. if ("scrollElasticity" in $$props) $$invalidate(0, scrollElasticity = $$props.scrollElasticity);
  31708. if ("enableSelectImage" in $$props) $$invalidate(16, enableSelectImage = $$props.enableSelectImage);
  31709. if ("willRenderPresetToolbar" in $$props) $$invalidate(17, willRenderPresetToolbar = $$props.willRenderPresetToolbar);
  31710. if ("onaddpreset" in $$props) $$invalidate(1, onaddpreset = $$props.onaddpreset);
  31711. if ("ongrabpreset" in $$props) $$invalidate(2, ongrabpreset = $$props.ongrabpreset);
  31712. if ("ondragpreset" in $$props) $$invalidate(3, ondragpreset = $$props.ondragpreset);
  31713. if ("ondroppreset" in $$props) $$invalidate(4, ondroppreset = $$props.ondroppreset);
  31714. };
  31715. $$self.$$.update = () => {
  31716. if ($$self.$$.dirty & /*presets*/ 32768) {
  31717. $$invalidate(5, presetsMapped = mapPresets(presets));
  31718. }
  31719. if ($$self.$$.dirty & /*presetsMapped*/ 32) {
  31720. //
  31721. // handle file input
  31722. //
  31723. $$invalidate(6, shouldRenderPresets = presetsMapped.length);
  31724. }
  31725. if ($$self.$$.dirty & /*shouldRenderPresets, presetsMapped*/ 96) {
  31726. $$invalidate(7, shouldGroupPresets = shouldRenderPresets && presetsMapped.some(preset => !!preset.items));
  31727. }
  31728. if ($$self.$$.dirty & /*shouldGroupPresets, presetsMapped*/ 160) {
  31729. $$invalidate(8, tabs = shouldGroupPresets && presetsMapped);
  31730. }
  31731. if ($$self.$$.dirty & /*shouldGroupPresets, presetsMapped*/ 160) {
  31732. $$invalidate(10, presetTabs = shouldGroupPresets && presetsMapped.reduce(
  31733. (prev, curr) => {
  31734. prev[curr.id] = curr;
  31735. return prev;
  31736. },
  31737. {}
  31738. ));
  31739. }
  31740. if ($$self.$$.dirty & /*tabSelected, tabs*/ 768) {
  31741. $$invalidate(9, tabSelected = tabSelected || tabs && (tabs.find(tab => !tab.disabled) || {}).id);
  31742. }
  31743. if ($$self.$$.dirty & /*tabSelected*/ 512) {
  31744. $$invalidate(11, tabsConfig = { name: uid, selected: tabSelected });
  31745. }
  31746. if ($$self.$$.dirty & /*tabs*/ 256) {
  31747. $$invalidate(12, panels = tabs && tabs.map(tab => tab.id));
  31748. }
  31749. if ($$self.$$.dirty & /*locale, willRenderPresetToolbar, enableSelectImage, onaddpreset*/ 212994) {
  31750. $$invalidate(13, presetToolbar = locale && willRenderPresetToolbar([
  31751. enableSelectImage && [
  31752. "Button",
  31753. "browse",
  31754. {
  31755. label: locale.shapeLabelButtonSelectSticker,
  31756. icon: locale.shapeIconButtonSelectSticker,
  31757. onclick: () => {
  31758. // create file input box
  31759. const fileInput = h("input", {
  31760. type: "file",
  31761. accept: "image/*",
  31762. onchange: () => {
  31763. const [file] = fileInput.files;
  31764. if (!file) return;
  31765. onaddpreset(file);
  31766. }
  31767. });
  31768. // open browse window
  31769. fileInput.click();
  31770. }
  31771. }
  31772. ]
  31773. ]));
  31774. }
  31775. };
  31776. return [
  31777. scrollElasticity,
  31778. onaddpreset,
  31779. ongrabpreset,
  31780. ondragpreset,
  31781. ondroppreset,
  31782. presetsMapped,
  31783. shouldRenderPresets,
  31784. shouldGroupPresets,
  31785. tabs,
  31786. tabSelected,
  31787. presetTabs,
  31788. tabsConfig,
  31789. panels,
  31790. presetToolbar,
  31791. locale,
  31792. presets,
  31793. enableSelectImage,
  31794. willRenderPresetToolbar,
  31795. select_handler
  31796. ];
  31797. }
  31798. class ShapePresetsPalette extends SvelteComponent {
  31799. constructor(options) {
  31800. super();
  31801. init(this, options, instance$a, create_fragment$a, safe_not_equal, {
  31802. locale: 14,
  31803. presets: 15,
  31804. scrollElasticity: 0,
  31805. enableSelectImage: 16,
  31806. willRenderPresetToolbar: 17,
  31807. onaddpreset: 1,
  31808. ongrabpreset: 2,
  31809. ondragpreset: 3,
  31810. ondroppreset: 4
  31811. });
  31812. }
  31813. }
  31814. var createPingDispatcher = (node) => (type, data) => {
  31815. node.dispatchEvent(createPing(type, data));
  31816. };
  31817. /* src/core/ui/components/ShapeUtil.svelte generated by Svelte v3.37.0 */
  31818. function create_if_block_5(ctx) {
  31819. let shapelayouteditor;
  31820. let updating_markup;
  31821. let updating_ui;
  31822. let current;
  31823. const shapelayouteditor_spread_levels = [
  31824. { locale: /*locale*/ ctx[4] },
  31825. { uid: /*utilKey*/ ctx[13] },
  31826. { parentRect: /*$parentRect*/ ctx[23] },
  31827. { rootRect: /*$rootRect*/ ctx[31] },
  31828. { utilRect: /*$utilRect*/ ctx[25] },
  31829. { offset: /*markupOffset*/ ctx[33] },
  31830. {
  31831. contextScale: /*$presentationScalar*/ ctx[42]
  31832. },
  31833. {
  31834. contextRotation: /*imageRotation*/ ctx[16]
  31835. },
  31836. { contextFlipX: /*imageFlipX*/ ctx[17] },
  31837. { contextFlipY: /*imageFlipY*/ ctx[18] },
  31838. { active: /*$isActive*/ ctx[24] },
  31839. { opacity: /*$isActiveFraction*/ ctx[28] },
  31840. { eraseRadius: /*toolEraseRadius*/ ctx[34] },
  31841. {
  31842. selectRadius: /*toolSelectRadius*/ ctx[6]
  31843. },
  31844. {
  31845. enableButtonFlipVertical: /*enableButtonFlipVertical*/ ctx[8]
  31846. },
  31847. {
  31848. mapEditorPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[14]
  31849. },
  31850. {
  31851. mapImagePointToEditorPoint: /*mapImagePointToScreenPoint*/ ctx[15]
  31852. },
  31853. {
  31854. enableTapToAddText: /*enableTapToAddText*/ ctx[11]
  31855. },
  31856. {
  31857. oninteractionstart: /*handleInteractionStart*/ ctx[54]
  31858. },
  31859. {
  31860. oninteractionupdate: /*handleInteractionUpdate*/ ctx[55]
  31861. },
  31862. {
  31863. oninteractionrelease: /*handleInteractionRelease*/ ctx[56]
  31864. },
  31865. {
  31866. oninteractionend: /*handleInteractionEnd*/ ctx[57]
  31867. },
  31868. { onaddshape: /*func_1*/ ctx[89] },
  31869. { onselectshape: /*func_2*/ ctx[90] },
  31870. { onupdateshape: /*func_3*/ ctx[91] },
  31871. { onremoveshape: /*func_4*/ ctx[92] },
  31872. /*layoutEditorHooks*/ ctx[39]
  31873. ];
  31874. function shapelayouteditor_markup_binding(value) {
  31875. /*shapelayouteditor_markup_binding*/ ctx[94](value);
  31876. }
  31877. function shapelayouteditor_ui_binding(value) {
  31878. /*shapelayouteditor_ui_binding*/ ctx[95](value);
  31879. }
  31880. let shapelayouteditor_props = {};
  31881. for (let i = 0; i < shapelayouteditor_spread_levels.length; i += 1) {
  31882. shapelayouteditor_props = assign(shapelayouteditor_props, shapelayouteditor_spread_levels[i]);
  31883. }
  31884. if (/*$shapes*/ ctx[26] !== void 0) {
  31885. shapelayouteditor_props.markup = /*$shapes*/ ctx[26];
  31886. }
  31887. if (/*$imageOverlayMarkup*/ ctx[41] !== void 0) {
  31888. shapelayouteditor_props.ui = /*$imageOverlayMarkup*/ ctx[41];
  31889. }
  31890. shapelayouteditor = new ShapeLayoutEditor({ props: shapelayouteditor_props });
  31891. /*shapelayouteditor_binding*/ ctx[93](shapelayouteditor);
  31892. binding_callbacks.push(() => bind(shapelayouteditor, "markup", shapelayouteditor_markup_binding));
  31893. binding_callbacks.push(() => bind(shapelayouteditor, "ui", shapelayouteditor_ui_binding));
  31894. return {
  31895. c() {
  31896. create_component(shapelayouteditor.$$.fragment);
  31897. },
  31898. m(target, anchor) {
  31899. mount_component(shapelayouteditor, target, anchor);
  31900. current = true;
  31901. },
  31902. p(ctx, dirty) {
  31903. const shapelayouteditor_changes = (dirty[0] & /*locale, utilKey, $parentRect, $utilRect, imageRotation, imageFlipX, imageFlipY, $isActive, $isActiveFraction, toolSelectRadius, enableButtonFlipVertical, mapScreenPointToImagePoint, mapImagePointToScreenPoint, enableTapToAddText*/ 327674192 | dirty[1] & /*$rootRect, markupOffset, $presentationScalar, toolEraseRadius, handleInteractionStart, handleInteractionUpdate, handleInteractionRelease, handleInteractionEnd, ping, layoutEditorHooks*/ 125831469 | dirty[2] & /*handleMarkupUpdate*/ 4)
  31904. ? get_spread_update(shapelayouteditor_spread_levels, [
  31905. dirty[0] & /*locale*/ 16 && { locale: /*locale*/ ctx[4] },
  31906. dirty[0] & /*utilKey*/ 8192 && { uid: /*utilKey*/ ctx[13] },
  31907. dirty[0] & /*$parentRect*/ 8388608 && { parentRect: /*$parentRect*/ ctx[23] },
  31908. dirty[1] & /*$rootRect*/ 1 && { rootRect: /*$rootRect*/ ctx[31] },
  31909. dirty[0] & /*$utilRect*/ 33554432 && { utilRect: /*$utilRect*/ ctx[25] },
  31910. dirty[1] & /*markupOffset*/ 4 && { offset: /*markupOffset*/ ctx[33] },
  31911. dirty[1] & /*$presentationScalar*/ 2048 && {
  31912. contextScale: /*$presentationScalar*/ ctx[42]
  31913. },
  31914. dirty[0] & /*imageRotation*/ 65536 && {
  31915. contextRotation: /*imageRotation*/ ctx[16]
  31916. },
  31917. dirty[0] & /*imageFlipX*/ 131072 && { contextFlipX: /*imageFlipX*/ ctx[17] },
  31918. dirty[0] & /*imageFlipY*/ 262144 && { contextFlipY: /*imageFlipY*/ ctx[18] },
  31919. dirty[0] & /*$isActive*/ 16777216 && { active: /*$isActive*/ ctx[24] },
  31920. dirty[0] & /*$isActiveFraction*/ 268435456 && { opacity: /*$isActiveFraction*/ ctx[28] },
  31921. dirty[1] & /*toolEraseRadius*/ 8 && { eraseRadius: /*toolEraseRadius*/ ctx[34] },
  31922. dirty[0] & /*toolSelectRadius*/ 64 && {
  31923. selectRadius: /*toolSelectRadius*/ ctx[6]
  31924. },
  31925. dirty[0] & /*enableButtonFlipVertical*/ 256 && {
  31926. enableButtonFlipVertical: /*enableButtonFlipVertical*/ ctx[8]
  31927. },
  31928. dirty[0] & /*mapScreenPointToImagePoint*/ 16384 && {
  31929. mapEditorPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[14]
  31930. },
  31931. dirty[0] & /*mapImagePointToScreenPoint*/ 32768 && {
  31932. mapImagePointToEditorPoint: /*mapImagePointToScreenPoint*/ ctx[15]
  31933. },
  31934. dirty[0] & /*enableTapToAddText*/ 2048 && {
  31935. enableTapToAddText: /*enableTapToAddText*/ ctx[11]
  31936. },
  31937. dirty[1] & /*handleInteractionStart*/ 8388608 && {
  31938. oninteractionstart: /*handleInteractionStart*/ ctx[54]
  31939. },
  31940. dirty[1] & /*handleInteractionUpdate*/ 16777216 && {
  31941. oninteractionupdate: /*handleInteractionUpdate*/ ctx[55]
  31942. },
  31943. dirty[1] & /*handleInteractionRelease*/ 33554432 && {
  31944. oninteractionrelease: /*handleInteractionRelease*/ ctx[56]
  31945. },
  31946. dirty[1] & /*handleInteractionEnd*/ 67108864 && {
  31947. oninteractionend: /*handleInteractionEnd*/ ctx[57]
  31948. },
  31949. dirty[1] & /*ping*/ 32 | dirty[2] & /*handleMarkupUpdate*/ 4 && { onaddshape: /*func_1*/ ctx[89] },
  31950. dirty[1] & /*ping*/ 32 && { onselectshape: /*func_2*/ ctx[90] },
  31951. dirty[1] & /*ping*/ 32 | dirty[2] & /*handleMarkupUpdate*/ 4 && { onupdateshape: /*func_3*/ ctx[91] },
  31952. dirty[1] & /*ping*/ 32 | dirty[2] & /*handleMarkupUpdate*/ 4 && { onremoveshape: /*func_4*/ ctx[92] },
  31953. dirty[1] & /*layoutEditorHooks*/ 256 && get_spread_object(/*layoutEditorHooks*/ ctx[39])
  31954. ])
  31955. : {};
  31956. if (!updating_markup && dirty[0] & /*$shapes*/ 67108864) {
  31957. updating_markup = true;
  31958. shapelayouteditor_changes.markup = /*$shapes*/ ctx[26];
  31959. add_flush_callback(() => updating_markup = false);
  31960. }
  31961. if (!updating_ui && dirty[1] & /*$imageOverlayMarkup*/ 1024) {
  31962. updating_ui = true;
  31963. shapelayouteditor_changes.ui = /*$imageOverlayMarkup*/ ctx[41];
  31964. add_flush_callback(() => updating_ui = false);
  31965. }
  31966. shapelayouteditor.$set(shapelayouteditor_changes);
  31967. },
  31968. i(local) {
  31969. if (current) return;
  31970. transition_in(shapelayouteditor.$$.fragment, local);
  31971. current = true;
  31972. },
  31973. o(local) {
  31974. transition_out(shapelayouteditor.$$.fragment, local);
  31975. current = false;
  31976. },
  31977. d(detaching) {
  31978. /*shapelayouteditor_binding*/ ctx[93](null);
  31979. destroy_component(shapelayouteditor, detaching);
  31980. }
  31981. };
  31982. }
  31983. // (559:4)
  31984. function create_main_slot(ctx) {
  31985. let div;
  31986. let current;
  31987. let mounted;
  31988. let dispose;
  31989. let if_block = /*shouldRenderShapeEditor*/ ctx[32] && create_if_block_5(ctx);
  31990. return {
  31991. c() {
  31992. div = element("div");
  31993. if (if_block) if_block.c();
  31994. attr(div, "slot", "main");
  31995. set_style(div, "cursor", "crosshair");
  31996. },
  31997. m(target, anchor) {
  31998. insert(target, div, anchor);
  31999. if (if_block) if_block.m(div, null);
  32000. /*div_binding*/ ctx[96](div);
  32001. current = true;
  32002. if (!mounted) {
  32003. dispose = [
  32004. action_destroyer(dropable.call(null, div)),
  32005. listen(div, "dropfiles", function () {
  32006. if (is_function(/*enablePresetDropImage*/ ctx[10]
  32007. ? /*handleDropFiles*/ ctx[63]
  32008. : noop$1)) (/*enablePresetDropImage*/ ctx[10]
  32009. ? /*handleDropFiles*/ ctx[63]
  32010. : noop$1).apply(this, arguments);
  32011. }),
  32012. action_destroyer(measurable.call(null, div)),
  32013. listen(div, "measure", /*measure_handler_1*/ ctx[87])
  32014. ];
  32015. mounted = true;
  32016. }
  32017. },
  32018. p(new_ctx, dirty) {
  32019. ctx = new_ctx;
  32020. if (/*shouldRenderShapeEditor*/ ctx[32]) {
  32021. if (if_block) {
  32022. if_block.p(ctx, dirty);
  32023. if (dirty[1] & /*shouldRenderShapeEditor*/ 2) {
  32024. transition_in(if_block, 1);
  32025. }
  32026. } else {
  32027. if_block = create_if_block_5(ctx);
  32028. if_block.c();
  32029. transition_in(if_block, 1);
  32030. if_block.m(div, null);
  32031. }
  32032. } else if (if_block) {
  32033. group_outros();
  32034. transition_out(if_block, 1, 1, () => {
  32035. if_block = null;
  32036. });
  32037. check_outros();
  32038. }
  32039. },
  32040. i(local) {
  32041. if (current) return;
  32042. transition_in(if_block);
  32043. current = true;
  32044. },
  32045. o(local) {
  32046. transition_out(if_block);
  32047. current = false;
  32048. },
  32049. d(detaching) {
  32050. if (detaching) detach(div);
  32051. if (if_block) if_block.d();
  32052. /*div_binding*/ ctx[96](null);
  32053. mounted = false;
  32054. run_all(dispose);
  32055. }
  32056. };
  32057. }
  32058. // (681:38)
  32059. function create_if_block_4(ctx) {
  32060. let shapepresetspalette;
  32061. let current;
  32062. shapepresetspalette = new ShapePresetsPalette({
  32063. props: {
  32064. locale: /*locale*/ ctx[4],
  32065. presets: /*shapePresets*/ ctx[12],
  32066. enableSelectImage: /*enablePresetSelectImage*/ ctx[9],
  32067. willRenderPresetToolbar: /*runWillRenderPresetToolbarHook*/ ctx[38],
  32068. onaddpreset: /*handleAddPreset*/ ctx[62],
  32069. ongrabpreset: /*handleGrabPreset*/ ctx[59],
  32070. ondragpreset: /*handleDragPreset*/ ctx[60],
  32071. ondroppreset: /*handleDropPreset*/ ctx[61],
  32072. scrollElasticity: /*computedScrollElasticity*/ ctx[37]
  32073. }
  32074. });
  32075. return {
  32076. c() {
  32077. create_component(shapepresetspalette.$$.fragment);
  32078. },
  32079. m(target, anchor) {
  32080. mount_component(shapepresetspalette, target, anchor);
  32081. current = true;
  32082. },
  32083. p(ctx, dirty) {
  32084. const shapepresetspalette_changes = {};
  32085. if (dirty[0] & /*locale*/ 16) shapepresetspalette_changes.locale = /*locale*/ ctx[4];
  32086. if (dirty[0] & /*shapePresets*/ 4096) shapepresetspalette_changes.presets = /*shapePresets*/ ctx[12];
  32087. if (dirty[0] & /*enablePresetSelectImage*/ 512) shapepresetspalette_changes.enableSelectImage = /*enablePresetSelectImage*/ ctx[9];
  32088. if (dirty[1] & /*runWillRenderPresetToolbarHook*/ 128) shapepresetspalette_changes.willRenderPresetToolbar = /*runWillRenderPresetToolbarHook*/ ctx[38];
  32089. if (dirty[1] & /*computedScrollElasticity*/ 64) shapepresetspalette_changes.scrollElasticity = /*computedScrollElasticity*/ ctx[37];
  32090. shapepresetspalette.$set(shapepresetspalette_changes);
  32091. },
  32092. i(local) {
  32093. if (current) return;
  32094. transition_in(shapepresetspalette.$$.fragment, local);
  32095. current = true;
  32096. },
  32097. o(local) {
  32098. transition_out(shapepresetspalette.$$.fragment, local);
  32099. current = false;
  32100. },
  32101. d(detaching) {
  32102. destroy_component(shapepresetspalette, detaching);
  32103. }
  32104. };
  32105. }
  32106. // (616:8) {#if shouldRenderControls}
  32107. function create_if_block(ctx) {
  32108. let div;
  32109. let current_block_type_index;
  32110. let if_block0;
  32111. let t;
  32112. let if_block1_anchor;
  32113. let current;
  32114. const if_block_creators = [create_if_block_3, create_else_block];
  32115. const if_blocks = [];
  32116. function select_block_type_1(ctx, dirty) {
  32117. if (/*shouldRenderPresets*/ ctx[35]) return 0;
  32118. return 1;
  32119. }
  32120. current_block_type_index = select_block_type_1(ctx);
  32121. if_block0 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  32122. let if_block1 = /*showToolbar*/ ctx[22] && create_if_block_1(ctx);
  32123. return {
  32124. c() {
  32125. div = element("div");
  32126. if_block0.c();
  32127. t = space();
  32128. if (if_block1) if_block1.c();
  32129. if_block1_anchor = empty();
  32130. attr(div, "class", "PinturaControlPanels");
  32131. },
  32132. m(target, anchor) {
  32133. insert(target, div, anchor);
  32134. if_blocks[current_block_type_index].m(div, null);
  32135. insert(target, t, anchor);
  32136. if (if_block1) if_block1.m(target, anchor);
  32137. insert(target, if_block1_anchor, anchor);
  32138. current = true;
  32139. },
  32140. p(ctx, dirty) {
  32141. let previous_block_index = current_block_type_index;
  32142. current_block_type_index = select_block_type_1(ctx);
  32143. if (current_block_type_index === previous_block_index) {
  32144. if_blocks[current_block_type_index].p(ctx, dirty);
  32145. } else {
  32146. group_outros();
  32147. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  32148. if_blocks[previous_block_index] = null;
  32149. });
  32150. check_outros();
  32151. if_block0 = if_blocks[current_block_type_index];
  32152. if (!if_block0) {
  32153. if_block0 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  32154. if_block0.c();
  32155. } else {
  32156. if_block0.p(ctx, dirty);
  32157. }
  32158. transition_in(if_block0, 1);
  32159. if_block0.m(div, null);
  32160. }
  32161. if (/*showToolbar*/ ctx[22]) {
  32162. if (if_block1) {
  32163. if_block1.p(ctx, dirty);
  32164. if (dirty[0] & /*showToolbar*/ 4194304) {
  32165. transition_in(if_block1, 1);
  32166. }
  32167. } else {
  32168. if_block1 = create_if_block_1(ctx);
  32169. if_block1.c();
  32170. transition_in(if_block1, 1);
  32171. if_block1.m(if_block1_anchor.parentNode, if_block1_anchor);
  32172. }
  32173. } else if (if_block1) {
  32174. group_outros();
  32175. transition_out(if_block1, 1, 1, () => {
  32176. if_block1 = null;
  32177. });
  32178. check_outros();
  32179. }
  32180. },
  32181. i(local) {
  32182. if (current) return;
  32183. transition_in(if_block0);
  32184. transition_in(if_block1);
  32185. current = true;
  32186. },
  32187. o(local) {
  32188. transition_out(if_block0);
  32189. transition_out(if_block1);
  32190. current = false;
  32191. },
  32192. d(detaching) {
  32193. if (detaching) detach(div);
  32194. if_blocks[current_block_type_index].d();
  32195. if (detaching) detach(t);
  32196. if (if_block1) if_block1.d(detaching);
  32197. if (detaching) detach(if_block1_anchor);
  32198. }
  32199. };
  32200. }
  32201. // (632:16) {:else}
  32202. function create_else_block(ctx) {
  32203. let div;
  32204. let shapestyleeditor;
  32205. let current;
  32206. shapestyleeditor = new ShapeStyleEditor({
  32207. props: {
  32208. locale: /*locale*/ ctx[4],
  32209. shape: /*markupShapeSelected*/ ctx[27],
  32210. onchange: /*handleUpdateSelectedMarkupShape*/ ctx[58],
  32211. controls: /*shapeControls*/ ctx[7],
  32212. scrollElasticity: /*computedScrollElasticity*/ ctx[37]
  32213. }
  32214. });
  32215. return {
  32216. c() {
  32217. div = element("div");
  32218. create_component(shapestyleeditor.$$.fragment);
  32219. attr(div, "class", "PinturaControlPanel");
  32220. },
  32221. m(target, anchor) {
  32222. insert(target, div, anchor);
  32223. mount_component(shapestyleeditor, div, null);
  32224. current = true;
  32225. },
  32226. p(ctx, dirty) {
  32227. const shapestyleeditor_changes = {};
  32228. if (dirty[0] & /*locale*/ 16) shapestyleeditor_changes.locale = /*locale*/ ctx[4];
  32229. if (dirty[0] & /*markupShapeSelected*/ 134217728) shapestyleeditor_changes.shape = /*markupShapeSelected*/ ctx[27];
  32230. if (dirty[0] & /*shapeControls*/ 128) shapestyleeditor_changes.controls = /*shapeControls*/ ctx[7];
  32231. if (dirty[1] & /*computedScrollElasticity*/ 64) shapestyleeditor_changes.scrollElasticity = /*computedScrollElasticity*/ ctx[37];
  32232. shapestyleeditor.$set(shapestyleeditor_changes);
  32233. },
  32234. i(local) {
  32235. if (current) return;
  32236. transition_in(shapestyleeditor.$$.fragment, local);
  32237. current = true;
  32238. },
  32239. o(local) {
  32240. transition_out(shapestyleeditor.$$.fragment, local);
  32241. current = false;
  32242. },
  32243. d(detaching) {
  32244. if (detaching) detach(div);
  32245. destroy_component(shapestyleeditor);
  32246. }
  32247. };
  32248. }
  32249. // (618:16) {#if shouldRenderPresets}
  32250. function create_if_block_3(ctx) {
  32251. let div;
  32252. let shapepresetspalette;
  32253. let current;
  32254. shapepresetspalette = new ShapePresetsPalette({
  32255. props: {
  32256. locale: /*locale*/ ctx[4],
  32257. presets: /*shapePresets*/ ctx[12],
  32258. enableSelectImage: /*enablePresetSelectImage*/ ctx[9],
  32259. willRenderPresetToolbar: /*runWillRenderPresetToolbarHook*/ ctx[38],
  32260. onaddpreset: /*handleAddPreset*/ ctx[62],
  32261. ongrabpreset: /*handleGrabPreset*/ ctx[59],
  32262. ondragpreset: /*handleDragPreset*/ ctx[60],
  32263. ondroppreset: /*handleDropPreset*/ ctx[61],
  32264. scrollElasticity: /*computedScrollElasticity*/ ctx[37]
  32265. }
  32266. });
  32267. return {
  32268. c() {
  32269. div = element("div");
  32270. create_component(shapepresetspalette.$$.fragment);
  32271. attr(div, "class", "PinturaControlPanel");
  32272. },
  32273. m(target, anchor) {
  32274. insert(target, div, anchor);
  32275. mount_component(shapepresetspalette, div, null);
  32276. current = true;
  32277. },
  32278. p(ctx, dirty) {
  32279. const shapepresetspalette_changes = {};
  32280. if (dirty[0] & /*locale*/ 16) shapepresetspalette_changes.locale = /*locale*/ ctx[4];
  32281. if (dirty[0] & /*shapePresets*/ 4096) shapepresetspalette_changes.presets = /*shapePresets*/ ctx[12];
  32282. if (dirty[0] & /*enablePresetSelectImage*/ 512) shapepresetspalette_changes.enableSelectImage = /*enablePresetSelectImage*/ ctx[9];
  32283. if (dirty[1] & /*runWillRenderPresetToolbarHook*/ 128) shapepresetspalette_changes.willRenderPresetToolbar = /*runWillRenderPresetToolbarHook*/ ctx[38];
  32284. if (dirty[1] & /*computedScrollElasticity*/ 64) shapepresetspalette_changes.scrollElasticity = /*computedScrollElasticity*/ ctx[37];
  32285. shapepresetspalette.$set(shapepresetspalette_changes);
  32286. },
  32287. i(local) {
  32288. if (current) return;
  32289. transition_in(shapepresetspalette.$$.fragment, local);
  32290. current = true;
  32291. },
  32292. o(local) {
  32293. transition_out(shapepresetspalette.$$.fragment, local);
  32294. current = false;
  32295. },
  32296. d(detaching) {
  32297. if (detaching) detach(div);
  32298. destroy_component(shapepresetspalette);
  32299. }
  32300. };
  32301. }
  32302. // (645:12) {#if showToolbar}
  32303. function create_if_block_1(ctx) {
  32304. let scrollable;
  32305. let current;
  32306. scrollable = new Scrollable({
  32307. props: {
  32308. class: "PinturaControlListScroller",
  32309. elasticity: /*computedScrollElasticity*/ ctx[37],
  32310. $$slots: { default: [create_default_slot$3] },
  32311. $$scope: { ctx }
  32312. }
  32313. });
  32314. return {
  32315. c() {
  32316. create_component(scrollable.$$.fragment);
  32317. },
  32318. m(target, anchor) {
  32319. mount_component(scrollable, target, anchor);
  32320. current = true;
  32321. },
  32322. p(ctx, dirty) {
  32323. const scrollable_changes = {};
  32324. if (dirty[1] & /*computedScrollElasticity*/ 64) scrollable_changes.elasticity = /*computedScrollElasticity*/ ctx[37];
  32325. if (dirty[0] & /*locale, toolsFiltered, toolActive*/ 2097169 | dirty[3] & /*$$scope*/ 4194304) {
  32326. scrollable_changes.$$scope = { dirty, ctx };
  32327. }
  32328. scrollable.$set(scrollable_changes);
  32329. },
  32330. i(local) {
  32331. if (current) return;
  32332. transition_in(scrollable.$$.fragment, local);
  32333. current = true;
  32334. },
  32335. o(local) {
  32336. transition_out(scrollable.$$.fragment, local);
  32337. current = false;
  32338. },
  32339. d(detaching) {
  32340. destroy_component(scrollable, detaching);
  32341. }
  32342. };
  32343. }
  32344. // (663:28) {#if option.icon}
  32345. function create_if_block_2(ctx) {
  32346. let icon;
  32347. let current;
  32348. icon = new Icon({
  32349. props: {
  32350. $$slots: { default: [create_default_slot_1] },
  32351. $$scope: { ctx }
  32352. }
  32353. });
  32354. return {
  32355. c() {
  32356. create_component(icon.$$.fragment);
  32357. },
  32358. m(target, anchor) {
  32359. mount_component(icon, target, anchor);
  32360. current = true;
  32361. },
  32362. p(ctx, dirty) {
  32363. const icon_changes = {};
  32364. if (dirty[0] & /*locale*/ 16 | dirty[3] & /*$$scope, option*/ 6291456) {
  32365. icon_changes.$$scope = { dirty, ctx };
  32366. }
  32367. icon.$set(icon_changes);
  32368. },
  32369. i(local) {
  32370. if (current) return;
  32371. transition_in(icon.$$.fragment, local);
  32372. current = true;
  32373. },
  32374. o(local) {
  32375. transition_out(icon.$$.fragment, local);
  32376. current = false;
  32377. },
  32378. d(detaching) {
  32379. destroy_component(icon, detaching);
  32380. }
  32381. };
  32382. }
  32383. // (664:32) <Icon >
  32384. function create_default_slot_1(ctx) {
  32385. let g;
  32386. let raw_value = (isFunction(/*option*/ ctx[114].icon)
  32387. ? /*option*/ ctx[114].icon(/*locale*/ ctx[4])
  32388. : /*option*/ ctx[114].icon) + "";
  32389. return {
  32390. c() {
  32391. g = svg_element("g");
  32392. },
  32393. m(target, anchor) {
  32394. insert(target, g, anchor);
  32395. g.innerHTML = raw_value;
  32396. },
  32397. p(ctx, dirty) {
  32398. if (dirty[0] & /*locale*/ 16 | dirty[3] & /*option*/ 2097152 && raw_value !== (raw_value = (isFunction(/*option*/ ctx[114].icon)
  32399. ? /*option*/ ctx[114].icon(/*locale*/ ctx[4])
  32400. : /*option*/ ctx[114].icon) + "")) g.innerHTML = raw_value; },
  32401. d(detaching) {
  32402. if (detaching) detach(g);
  32403. }
  32404. };
  32405. }
  32406. // (662:24)
  32407. function create_option_slot$1(ctx) {
  32408. let div;
  32409. let t0;
  32410. let span;
  32411. let t1_value = (isFunction(/*option*/ ctx[114].label)
  32412. ? /*option*/ ctx[114].label(/*locale*/ ctx[4])
  32413. : /*option*/ ctx[114].label) + "";
  32414. let t1;
  32415. let current;
  32416. let if_block = /*option*/ ctx[114].icon && create_if_block_2(ctx);
  32417. return {
  32418. c() {
  32419. div = element("div");
  32420. if (if_block) if_block.c();
  32421. t0 = space();
  32422. span = element("span");
  32423. t1 = text(t1_value);
  32424. attr(div, "slot", "option");
  32425. },
  32426. m(target, anchor) {
  32427. insert(target, div, anchor);
  32428. if (if_block) if_block.m(div, null);
  32429. append(div, t0);
  32430. append(div, span);
  32431. append(span, t1);
  32432. current = true;
  32433. },
  32434. p(ctx, dirty) {
  32435. if (/*option*/ ctx[114].icon) {
  32436. if (if_block) {
  32437. if_block.p(ctx, dirty);
  32438. if (dirty[3] & /*option*/ 2097152) {
  32439. transition_in(if_block, 1);
  32440. }
  32441. } else {
  32442. if_block = create_if_block_2(ctx);
  32443. if_block.c();
  32444. transition_in(if_block, 1);
  32445. if_block.m(div, t0);
  32446. }
  32447. } else if (if_block) {
  32448. group_outros();
  32449. transition_out(if_block, 1, 1, () => {
  32450. if_block = null;
  32451. });
  32452. check_outros();
  32453. }
  32454. if ((!current || dirty[0] & /*locale*/ 16 | dirty[3] & /*option*/ 2097152) && t1_value !== (t1_value = (isFunction(/*option*/ ctx[114].label)
  32455. ? /*option*/ ctx[114].label(/*locale*/ ctx[4])
  32456. : /*option*/ ctx[114].label) + "")) set_data(t1, t1_value);
  32457. },
  32458. i(local) {
  32459. if (current) return;
  32460. transition_in(if_block);
  32461. current = true;
  32462. },
  32463. o(local) {
  32464. transition_out(if_block);
  32465. current = false;
  32466. },
  32467. d(detaching) {
  32468. if (detaching) detach(div);
  32469. if (if_block) if_block.d();
  32470. }
  32471. };
  32472. }
  32473. // (646:16) <Scrollable class="PinturaControlListScroller" elasticity={computedScrollElasticity} >
  32474. function create_default_slot$3(ctx) {
  32475. let radiogroup;
  32476. let current;
  32477. radiogroup = new RadioGroup({
  32478. props: {
  32479. locale: /*locale*/ ctx[4],
  32480. class: "PinturaControlList",
  32481. optionClass: "PinturaControlListOption",
  32482. layout: "row",
  32483. options: /*toolsFiltered*/ ctx[21],
  32484. selectedIndex: /*toolsFiltered*/ ctx[21].findIndex(/*func*/ ctx[88]),
  32485. onchange: /*updateActiveTool*/ ctx[53],
  32486. $$slots: {
  32487. option: [
  32488. create_option_slot$1,
  32489. ({ option }) => ({ 114: option }),
  32490. ({ option }) => [0, 0, 0, option ? 2097152 : 0]
  32491. ]
  32492. },
  32493. $$scope: { ctx }
  32494. }
  32495. });
  32496. return {
  32497. c() {
  32498. create_component(radiogroup.$$.fragment);
  32499. },
  32500. m(target, anchor) {
  32501. mount_component(radiogroup, target, anchor);
  32502. current = true;
  32503. },
  32504. p(ctx, dirty) {
  32505. const radiogroup_changes = {};
  32506. if (dirty[0] & /*locale*/ 16) radiogroup_changes.locale = /*locale*/ ctx[4];
  32507. if (dirty[0] & /*toolsFiltered*/ 2097152) radiogroup_changes.options = /*toolsFiltered*/ ctx[21];
  32508. if (dirty[0] & /*toolsFiltered, toolActive*/ 2097153) radiogroup_changes.selectedIndex = /*toolsFiltered*/ ctx[21].findIndex(/*func*/ ctx[88]);
  32509. if (dirty[0] & /*locale*/ 16 | dirty[3] & /*$$scope, option*/ 6291456) {
  32510. radiogroup_changes.$$scope = { dirty, ctx };
  32511. }
  32512. radiogroup.$set(radiogroup_changes);
  32513. },
  32514. i(local) {
  32515. if (current) return;
  32516. transition_in(radiogroup.$$.fragment, local);
  32517. current = true;
  32518. },
  32519. o(local) {
  32520. transition_out(radiogroup.$$.fragment, local);
  32521. current = false;
  32522. },
  32523. d(detaching) {
  32524. destroy_component(radiogroup, detaching);
  32525. }
  32526. };
  32527. }
  32528. // (615:4)
  32529. function create_footer_slot$2(ctx) {
  32530. let div;
  32531. let current_block_type_index;
  32532. let if_block;
  32533. let current;
  32534. const if_block_creators = [create_if_block, create_if_block_4];
  32535. const if_blocks = [];
  32536. function select_block_type(ctx, dirty) {
  32537. if (/*shouldRenderControls*/ ctx[30]) return 0;
  32538. if (/*shouldRenderPresets*/ ctx[35]) return 1;
  32539. return -1;
  32540. }
  32541. if (~(current_block_type_index = select_block_type(ctx))) {
  32542. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  32543. }
  32544. return {
  32545. c() {
  32546. div = element("div");
  32547. if (if_block) if_block.c();
  32548. attr(div, "slot", "footer");
  32549. attr(div, "style", /*footerStyle*/ ctx[40]);
  32550. },
  32551. m(target, anchor) {
  32552. insert(target, div, anchor);
  32553. if (~current_block_type_index) {
  32554. if_blocks[current_block_type_index].m(div, null);
  32555. }
  32556. current = true;
  32557. },
  32558. p(ctx, dirty) {
  32559. let previous_block_index = current_block_type_index;
  32560. current_block_type_index = select_block_type(ctx);
  32561. if (current_block_type_index === previous_block_index) {
  32562. if (~current_block_type_index) {
  32563. if_blocks[current_block_type_index].p(ctx, dirty);
  32564. }
  32565. } else {
  32566. if (if_block) {
  32567. group_outros();
  32568. transition_out(if_blocks[previous_block_index], 1, 1, () => {
  32569. if_blocks[previous_block_index] = null;
  32570. });
  32571. check_outros();
  32572. }
  32573. if (~current_block_type_index) {
  32574. if_block = if_blocks[current_block_type_index];
  32575. if (!if_block) {
  32576. if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
  32577. if_block.c();
  32578. } else {
  32579. if_block.p(ctx, dirty);
  32580. }
  32581. transition_in(if_block, 1);
  32582. if_block.m(div, null);
  32583. } else {
  32584. if_block = null;
  32585. }
  32586. }
  32587. if (!current || dirty[1] & /*footerStyle*/ 512) {
  32588. attr(div, "style", /*footerStyle*/ ctx[40]);
  32589. }
  32590. },
  32591. i(local) {
  32592. if (current) return;
  32593. transition_in(if_block);
  32594. current = true;
  32595. },
  32596. o(local) {
  32597. transition_out(if_block);
  32598. current = false;
  32599. },
  32600. d(detaching) {
  32601. if (detaching) detach(div);
  32602. if (~current_block_type_index) {
  32603. if_blocks[current_block_type_index].d();
  32604. }
  32605. }
  32606. };
  32607. }
  32608. function create_fragment$9(ctx) {
  32609. let util;
  32610. let current;
  32611. util = new Util({
  32612. props: {
  32613. $$slots: {
  32614. footer: [create_footer_slot$2],
  32615. main: [create_main_slot]
  32616. },
  32617. $$scope: { ctx }
  32618. }
  32619. });
  32620. util.$on("measure", /*measure_handler*/ ctx[97]);
  32621. return {
  32622. c() {
  32623. create_component(util.$$.fragment);
  32624. },
  32625. m(target, anchor) {
  32626. mount_component(util, target, anchor);
  32627. current = true;
  32628. },
  32629. p(ctx, dirty) {
  32630. const util_changes = {};
  32631. if (dirty[0] & /*locale, toolsFiltered, toolActive, showToolbar, shapePresets, enablePresetSelectImage, markupShapeSelected, shapeControls, shouldRenderControls, pingHub, enablePresetDropImage, utilKey, $parentRect, $utilRect, imageRotation, imageFlipX, imageFlipY, $isActive, $isActiveFraction, toolSelectRadius, enableButtonFlipVertical, mapScreenPointToImagePoint, mapImagePointToScreenPoint, enableTapToAddText, markupEditor, $shapes*/ 2146959313 | dirty[1] & /*footerStyle, computedScrollElasticity, runWillRenderPresetToolbarHook, shouldRenderPresets, $rootRect, markupOffset, $presentationScalar, toolEraseRadius, ping, layoutEditorHooks, $imageOverlayMarkup, shouldRenderShapeEditor*/ 4095 | dirty[3] & /*$$scope*/ 4194304) {
  32632. util_changes.$$scope = { dirty, ctx };
  32633. }
  32634. util.$set(util_changes);
  32635. },
  32636. i(local) {
  32637. if (current) return;
  32638. transition_in(util.$$.fragment, local);
  32639. current = true;
  32640. },
  32641. o(local) {
  32642. transition_out(util.$$.fragment, local);
  32643. current = false;
  32644. },
  32645. d(detaching) {
  32646. destroy_component(util, detaching);
  32647. }
  32648. };
  32649. }
  32650. function instance$9($$self, $$props, $$invalidate) {
  32651. let toolsFiltered;
  32652. let hasShapeControls;
  32653. let showToolbar;
  32654. let hasTools;
  32655. let hasActiveTool;
  32656. let shouldRenderControls;
  32657. let shouldRenderShapeEditor;
  32658. let markupOffset;
  32659. let markupShapeKeys;
  32660. let markupSelected;
  32661. let markupToolShape;
  32662. let markupToolStylesComputed;
  32663. let markupShapeSelected;
  32664. let toolEraseRadius;
  32665. let shouldRenderPresets;
  32666. let shouldStickToImage;
  32667. let ping;
  32668. let computedScrollElasticity;
  32669. let runWillRenderPresetToolbarHook;
  32670. let layoutEditorHooks;
  32671. let footerStyle;
  32672. let $parentRect,
  32673. $$unsubscribe_parentRect = noop,
  32674. $$subscribe_parentRect = () => ($$unsubscribe_parentRect(), $$unsubscribe_parentRect = subscribe(parentRect, $$value => $$invalidate(23, $parentRect = $$value)), parentRect);
  32675. let $rootRect;
  32676. let $isActive,
  32677. $$unsubscribe_isActive = noop,
  32678. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(24, $isActive = $$value)), isActive);
  32679. let $imagePreviewModifiers;
  32680. let $isVisible,
  32681. $$unsubscribe_isVisible = noop,
  32682. $$subscribe_isVisible = () => ($$unsubscribe_isVisible(), $$unsubscribe_isVisible = subscribe(isVisible, $$value => $$invalidate(78, $isVisible = $$value)), isVisible);
  32683. let $utilRect;
  32684. let $stageRect;
  32685. let $shapes,
  32686. $$unsubscribe_shapes = noop,
  32687. $$subscribe_shapes = () => ($$unsubscribe_shapes(), $$unsubscribe_shapes = subscribe(shapes, $$value => $$invalidate(26, $shapes = $$value)), shapes);
  32688. let $shapePreprocessor;
  32689. let $isActiveFraction,
  32690. $$unsubscribe_isActiveFraction = noop,
  32691. $$subscribe_isActiveFraction = () => ($$unsubscribe_isActiveFraction(), $$unsubscribe_isActiveFraction = subscribe(isActiveFraction, $$value => $$invalidate(28, $isActiveFraction = $$value)), isActiveFraction);
  32692. let $imageCropRect;
  32693. let $env;
  32694. let $animation;
  32695. let $footerOffset;
  32696. let $imageOverlayMarkup;
  32697. let $presentationScalar;
  32698. $$self.$$.on_destroy.push(() => $$unsubscribe_parentRect());
  32699. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  32700. $$self.$$.on_destroy.push(() => $$unsubscribe_isVisible());
  32701. $$self.$$.on_destroy.push(() => $$unsubscribe_shapes());
  32702. $$self.$$.on_destroy.push(() => $$unsubscribe_isActiveFraction());
  32703. let { isActive } = $$props;
  32704. $$subscribe_isActive();
  32705. let { isActiveFraction } = $$props;
  32706. $$subscribe_isActiveFraction();
  32707. let { isVisible } = $$props;
  32708. $$subscribe_isVisible();
  32709. let { stores } = $$props;
  32710. let { locale = {} } = $$props;
  32711. let { shapes } = $$props;
  32712. $$subscribe_shapes();
  32713. let { tools = [] } = $$props;
  32714. let { toolShapes = [] } = $$props;
  32715. let { toolActive = undefined } = $$props;
  32716. let { toolSelectRadius = undefined } = $$props;
  32717. let { shapeControls = {} } = $$props;
  32718. let { enableButtonFlipVertical = false } = $$props;
  32719. let { enablePresetSelectImage = true } = $$props;
  32720. let { enablePresetDropImage = true } = $$props;
  32721. let { enableSelectToolToAddShape = false } = $$props;
  32722. let { enableTapToAddText = false } = $$props;
  32723. let { willRenderPresetToolbar = undefined } = $$props;
  32724. let { shapePresets = [] } = $$props;
  32725. let { utilKey } = $$props;
  32726. let { mapScreenPointToImagePoint } = $$props;
  32727. let { mapImagePointToScreenPoint } = $$props;
  32728. let { imageRotation = 0 } = $$props;
  32729. let { imageFlipX = false } = $$props;
  32730. let { imageFlipY = false } = $$props;
  32731. let { parentRect } = $$props;
  32732. $$subscribe_parentRect();
  32733. let { hooks = {} } = $$props;
  32734. const { env, animation, history, rootRect, stageRect, utilRect, elasticityMultiplier, scrollElasticity, imageOverlayMarkup, imagePreviewModifiers, imageCropRect, presentationScalar, shapePreprocessor, // for panning / scaling the image
  32735. imagePresentationScale, imagePresentationPan } = stores;
  32736. component_subscribe($$self, env, value => $$invalidate(84, $env = value));
  32737. component_subscribe($$self, animation, value => $$invalidate(85, $animation = value));
  32738. component_subscribe($$self, rootRect, value => $$invalidate(31, $rootRect = value));
  32739. component_subscribe($$self, stageRect, value => $$invalidate(79, $stageRect = value));
  32740. component_subscribe($$self, utilRect, value => $$invalidate(25, $utilRect = value));
  32741. component_subscribe($$self, imageOverlayMarkup, value => $$invalidate(41, $imageOverlayMarkup = value));
  32742. component_subscribe($$self, imagePreviewModifiers, value => $$invalidate(76, $imagePreviewModifiers = value));
  32743. component_subscribe($$self, imageCropRect, value => $$invalidate(101, $imageCropRect = value));
  32744. component_subscribe($$self, presentationScalar, value => $$invalidate(42, $presentationScalar = value));
  32745. component_subscribe($$self, shapePreprocessor, value => $$invalidate(83, $shapePreprocessor = value));
  32746. const updateActiveTool = ({ value }, event) => {
  32747. $$invalidate(0, toolActive = value);
  32748. // if is keyboard navigating or should add shape
  32749. if (enableSelectToolToAddShape || isConfirmKey(event.key)) {
  32750. AddToolDefaultShape(value);
  32751. }
  32752. };
  32753. const AddToolDefaultShape = tool => {
  32754. const [shape, options] = toolShapes[tool];
  32755. let isRelative = options.position === "relative";
  32756. let shapeToAdd;
  32757. const size = isRelative ? "20%" : $parentRect.width * 0.2;
  32758. const x = isRelative ? "0%" : 0;
  32759. const y = isRelative ? "0%" : 0;
  32760. if (shapeIsRect(shape) || shapeIsText(shape)) {
  32761. shapeToAdd = shapeDeepCopy(shape);
  32762. shapeToAdd.x = x;
  32763. shapeToAdd.y = y;
  32764. shapeUpdateProps(shapeToAdd, { width: size, height: size }, $parentRect);
  32765. } else if (shapeIsEllipse(shape)) {
  32766. shapeToAdd = shapeDeepCopy(shape);
  32767. shapeToAdd.x = x;
  32768. shapeToAdd.y = y;
  32769. shapeUpdateProps(shapeToAdd, { rx: size, ry: size }, $parentRect);
  32770. } else if (shapeIsLine(shape)) {
  32771. shapeToAdd = shapeDeepCopy(shape);
  32772. shapeToAdd.x1 = x;
  32773. shapeToAdd.y1 = y;
  32774. shapeToAdd.x2 = x;
  32775. shapeToAdd.y2 = y;
  32776. }
  32777. if (!shapeToAdd) return;
  32778. Promise.resolve().then(() => {
  32779. addShape(createShapeAtPosition(shapeToAdd, undefined, size));
  32780. });
  32781. };
  32782. const mapScreenEventToImagePoint = e => mapScreenPointToImagePoint(getEventPositionInEditor(e, $rootRect));
  32783. // A reference to the markup editor, we need this so we can call exported functions
  32784. let markupEditor;
  32785. // the current tool styles
  32786. let markupToolStyles = {};
  32787. //
  32788. // Create new shape
  32789. //
  32790. let interactionHandler;
  32791. const handleInteractionStart = e => {
  32792. if (toolActive === "eraser") {
  32793. interactionHandler = markupEditor.eraseShape();
  32794. } else if (toolActive && toolShapes[toolActive]) {
  32795. const [shape, options] = toolShapes[toolActive];
  32796. interactionHandler = markupEditor.createShape({ ...shape, ...markupToolStylesComputed }, options);
  32797. } else {
  32798. interactionHandler = undefined;
  32799. }
  32800. if (!interactionHandler) return false;
  32801. interactionHandler.start(e);
  32802. return true;
  32803. };
  32804. const handleInteractionUpdate = e => {
  32805. if (!interactionHandler) return false;
  32806. interactionHandler.update(e);
  32807. return true;
  32808. };
  32809. const handleInteractionRelease = e => {
  32810. if (!interactionHandler) return false;
  32811. interactionHandler.release(e);
  32812. return true;
  32813. };
  32814. const handleInteractionEnd = e => {
  32815. if (!interactionHandler) return false;
  32816. interactionHandler.end(e);
  32817. interactionHandler = undefined;
  32818. return true;
  32819. };
  32820. const blurOnToolSwitch = () => {
  32821. if (!markupEditor) return;
  32822. markupEditor.blurShapes();
  32823. };
  32824. function handleUpdateSelectedMarkupShape(props) {
  32825. // remember style for when creating or styling other element
  32826. Object.keys(props).forEach(key => $$invalidate(72, markupToolStyles[key] = props[key], markupToolStyles));
  32827. // it's possible we're only updating default styles
  32828. if (!markupSelected) return;
  32829. // update element
  32830. markupEditor.updateMarkupShape(markupSelected, props);
  32831. // update markup style
  32832. handleMarkupUpdate();
  32833. }
  32834. const createShapeAtPosition = (shape, position, size) => {
  32835. // position defaults to crop center
  32836. let positionIsCenter = false;
  32837. if (!position) {
  32838. // is centering to stage
  32839. positionIsCenter = true;
  32840. // calculate image or rect position
  32841. position = shouldStickToImage
  32842. ? mapScreenPointToImagePoint(rectCenter($stageRect))
  32843. : rectCenter($imageCropRect);
  32844. }
  32845. // adjust offset if parent rect is image crop rect
  32846. position.x -= $parentRect.x || 0;
  32847. position.y -= $parentRect.y || 0;
  32848. // de-flip shape
  32849. if (imageFlipX || imageFlipY) {
  32850. shape.flipX = imageFlipX;
  32851. shape.flipY = imageFlipY;
  32852. }
  32853. // reposition if there's already shapes at position and shape isn't full screen
  32854. const shapesAlreadyAtPosition = markupEditor.getShapesNearPosition(position);
  32855. if (positionIsCenter && shapesAlreadyAtPosition.length) {
  32856. const dist = Math.min($imageCropRect.width, $imageCropRect.height) * 0.1;
  32857. position.x += Math.round(-dist + Math.random() * dist * 2);
  32858. position.y += Math.round(-dist + Math.random() * dist * 2);
  32859. }
  32860. // de-rotate shape
  32861. if (imageRotation !== 0) {
  32862. if (imageFlipX && imageFlipY) shape.rotation = -imageRotation; else if (imageFlipX) shape.rotation = imageRotation; else if (imageFlipY) shape.rotation = imageRotation; else shape.rotation = -imageRotation;
  32863. }
  32864. if (hasProp(shape, "width") && hasProp(shape, "height")) {
  32865. const { width, height } = shapeGetPropsPixelValues(shape, ["width", "height"], $parentRect);
  32866. shapeUpdateProps(
  32867. shape,
  32868. {
  32869. x: position.x - width * 0.5,
  32870. y: position.y - height * 0.5
  32871. },
  32872. $parentRect
  32873. );
  32874. } else if (shapeIsEllipse(shape)) {
  32875. shapeUpdateProps(shape, { x: position.x, y: position.y }, $parentRect);
  32876. } else if (shapeIsLine(shape)) {
  32877. const { x1, y1, x2, y2 } = shapeGetPropsPixelValues(shape, ["x1", "y1", "x2", "y2"], $parentRect);
  32878. const dist = vectorDistance(vectorCreate(x1, y1), vectorCreate(x2, y2));
  32879. const l = dist || isString(size)
  32880. ? toPixelValue(size, $parentRect.width)
  32881. : size;
  32882. shapeUpdateProps(
  32883. shape,
  32884. {
  32885. x1: position.x - l,
  32886. y1: position.y + l,
  32887. x2: position.x + l,
  32888. y2: position.y - l
  32889. },
  32890. $parentRect
  32891. );
  32892. }
  32893. return shape;
  32894. };
  32895. const addPreset = (preset, position) => {
  32896. const shape = createShapeAtPosition(shapeCreateFromPreset(preset, $imageCropRect), position);
  32897. return addShape(shape);
  32898. };
  32899. const addShape = shape => {
  32900. const { beforeAddShape = () => true } = hooks;
  32901. if (!beforeAddShape(shape)) return;
  32902. markupEditor.addShape(shape);
  32903. markupEditor.selectShape(shape);
  32904. history.write();
  32905. return shape;
  32906. };
  32907. let dragCancelled = false;
  32908. const handleGrabPreset = () => {
  32909. dragCancelled = false;
  32910. };
  32911. const handleDragPreset = (preset, e) => {
  32912. if (dragCancelled) return;
  32913. const { beforeAddShape = () => true } = hooks;
  32914. const position = mapScreenEventToImagePoint(e);
  32915. // create or update if is inside image
  32916. const draft = markupEditor.getMarkupItemDraft();
  32917. const inCropRect = rectContainsPoint($imageCropRect, {
  32918. // adjust offset if parent rect is image crop rect
  32919. x: position.x + ($parentRect.x || 0),
  32920. y: position.y + ($parentRect.y || 0)
  32921. });
  32922. // remove draft if not dragging inside image
  32923. if (draft && !inCropRect) markupEditor.discardMarkupItemDraft();
  32924. // stop here if we're not in the crop rect
  32925. if (!inCropRect) return;
  32926. // create draft shape
  32927. if (!draft) {
  32928. const shape = createShapeAtPosition(shapeCreateFromPreset(preset, $imageCropRect), position);
  32929. if (!beforeAddShape(shape)) {
  32930. dragCancelled = true;
  32931. e.preventDefault();
  32932. return;
  32933. }
  32934. shapeMakeDraft(shape);
  32935. markupEditor.addShape(shape);
  32936. return;
  32937. }
  32938. // center shape on pointer if it has dimensions
  32939. if (shapeIsRect(draft)) {
  32940. position.x -= draft.width * 0.5;
  32941. position.y -= draft.height * 0.5;
  32942. }
  32943. // update the draft shape
  32944. markupEditor.updateMarkupShape(draft, position);
  32945. };
  32946. const handleDropPreset = (_, e) => {
  32947. if (dragCancelled) return;
  32948. const position = mapScreenEventToImagePoint(e);
  32949. if (!rectContainsPoint($imageCropRect, {
  32950. x: position.x + ($parentRect.x || 0),
  32951. y: position.y + ($parentRect.y || 0)
  32952. })) {
  32953. markupEditor.discardMarkupItemDraft();
  32954. return;
  32955. }
  32956. // confirm shape
  32957. const shape = markupEditor.confirmMarkupItemDraft();
  32958. markupEditor.selectShape(shape);
  32959. // update history
  32960. history.write();
  32961. };
  32962. const handleAddPreset = preset => addPreset(preset);
  32963. const handleAddFiles = (files, position) => files.forEach(file => addPreset(file, position));
  32964. const handleDropFiles = e => handleAddFiles(e.detail.resources, mapScreenEventToImagePoint(e.detail.event));
  32965. //
  32966. // Zoom
  32967. //
  32968. // const handleWheel = (e) => {
  32969. // // don't run default actions, prevent other actions from running
  32970. // e.preventDefault();
  32971. // e.stopPropagation();
  32972. // // convert wheel delta to scalar
  32973. // const delta = getWheelDelta(e);
  32974. // const scalar = 1 + (delta / 100);
  32975. // // update image zoom
  32976. // imagePresentationScale.update(v => v * scalar)
  32977. // }
  32978. // on:wheel|nonpassive={handleWheel}
  32979. //
  32980. // History
  32981. //
  32982. const handleMarkupUpdate = () => history.write();
  32983. // used to fire ping events from
  32984. let pingHub;
  32985. //
  32986. // Footer style
  32987. //
  32988. const footerOffset = spring($animation ? 20 : 0);
  32989. component_subscribe($$self, footerOffset, value => $$invalidate(86, $footerOffset = value));
  32990. function measure_handler_1(event) {
  32991. bubble($$self, event);
  32992. }
  32993. const func = option => option[0] === toolActive;
  32994. const func_1 = shape => {
  32995. ping("addshape", shape);
  32996. handleMarkupUpdate();
  32997. };
  32998. const func_2 = shape => {
  32999. ping("selectshape", shape);
  33000. };
  33001. const func_3 = shape => {
  33002. ping("updateshape", shape);
  33003. handleMarkupUpdate();
  33004. };
  33005. const func_4 = shape => {
  33006. ping("removeshape", shape);
  33007. handleMarkupUpdate();
  33008. };
  33009. function shapelayouteditor_binding($$value) {
  33010. binding_callbacks[$$value ? "unshift" : "push"](() => {
  33011. markupEditor = $$value;
  33012. $$invalidate(29, markupEditor);
  33013. });
  33014. }
  33015. function shapelayouteditor_markup_binding(value) {
  33016. $shapes = value;
  33017. shapes.set($shapes);
  33018. }
  33019. function shapelayouteditor_ui_binding(value) {
  33020. $imageOverlayMarkup = value;
  33021. imageOverlayMarkup.set($imageOverlayMarkup);
  33022. }
  33023. function div_binding($$value) {
  33024. binding_callbacks[$$value ? "unshift" : "push"](() => {
  33025. pingHub = $$value;
  33026. $$invalidate(20, pingHub);
  33027. });
  33028. }
  33029. function measure_handler(event) {
  33030. bubble($$self, event);
  33031. }
  33032. $$self.$$set = $$props => {
  33033. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(1, isActive = $$props.isActive));
  33034. if ("isActiveFraction" in $$props) $$subscribe_isActiveFraction($$invalidate(2, isActiveFraction = $$props.isActiveFraction));
  33035. if ("isVisible" in $$props) $$subscribe_isVisible($$invalidate(3, isVisible = $$props.isVisible));
  33036. if ("stores" in $$props) $$invalidate(66, stores = $$props.stores);
  33037. if ("locale" in $$props) $$invalidate(4, locale = $$props.locale);
  33038. if ("shapes" in $$props) $$subscribe_shapes($$invalidate(5, shapes = $$props.shapes));
  33039. if ("tools" in $$props) $$invalidate(67, tools = $$props.tools);
  33040. if ("toolShapes" in $$props) $$invalidate(68, toolShapes = $$props.toolShapes);
  33041. if ("toolActive" in $$props) $$invalidate(0, toolActive = $$props.toolActive);
  33042. if ("toolSelectRadius" in $$props) $$invalidate(6, toolSelectRadius = $$props.toolSelectRadius);
  33043. if ("shapeControls" in $$props) $$invalidate(7, shapeControls = $$props.shapeControls);
  33044. if ("enableButtonFlipVertical" in $$props) $$invalidate(8, enableButtonFlipVertical = $$props.enableButtonFlipVertical);
  33045. if ("enablePresetSelectImage" in $$props) $$invalidate(9, enablePresetSelectImage = $$props.enablePresetSelectImage);
  33046. if ("enablePresetDropImage" in $$props) $$invalidate(10, enablePresetDropImage = $$props.enablePresetDropImage);
  33047. if ("enableSelectToolToAddShape" in $$props) $$invalidate(69, enableSelectToolToAddShape = $$props.enableSelectToolToAddShape);
  33048. if ("enableTapToAddText" in $$props) $$invalidate(11, enableTapToAddText = $$props.enableTapToAddText);
  33049. if ("willRenderPresetToolbar" in $$props) $$invalidate(70, willRenderPresetToolbar = $$props.willRenderPresetToolbar);
  33050. if ("shapePresets" in $$props) $$invalidate(12, shapePresets = $$props.shapePresets);
  33051. if ("utilKey" in $$props) $$invalidate(13, utilKey = $$props.utilKey);
  33052. if ("mapScreenPointToImagePoint" in $$props) $$invalidate(14, mapScreenPointToImagePoint = $$props.mapScreenPointToImagePoint);
  33053. if ("mapImagePointToScreenPoint" in $$props) $$invalidate(15, mapImagePointToScreenPoint = $$props.mapImagePointToScreenPoint);
  33054. if ("imageRotation" in $$props) $$invalidate(16, imageRotation = $$props.imageRotation);
  33055. if ("imageFlipX" in $$props) $$invalidate(17, imageFlipX = $$props.imageFlipX);
  33056. if ("imageFlipY" in $$props) $$invalidate(18, imageFlipY = $$props.imageFlipY);
  33057. if ("parentRect" in $$props) $$subscribe_parentRect($$invalidate(19, parentRect = $$props.parentRect));
  33058. if ("hooks" in $$props) $$invalidate(71, hooks = $$props.hooks);
  33059. };
  33060. $$self.$$.update = () => {
  33061. if ($$self.$$.dirty[0] & /*shapePresets*/ 4096 | $$self.$$.dirty[2] & /*tools*/ 32) {
  33062. // remove presets tool if no shape presets defined
  33063. $$invalidate(21, toolsFiltered = shapePresets.length === 0
  33064. ? tools.filter(tool => tool[0] !== "preset")
  33065. : tools);
  33066. }
  33067. if ($$self.$$.dirty[0] & /*shapeControls*/ 128) {
  33068. $$invalidate(73, hasShapeControls = Object.keys(shapeControls).length);
  33069. }
  33070. if ($$self.$$.dirty[0] & /*toolsFiltered*/ 2097152) {
  33071. $$invalidate(22, showToolbar = toolsFiltered.length > 1);
  33072. }
  33073. if ($$self.$$.dirty[0] & /*toolsFiltered*/ 2097152) {
  33074. $$invalidate(74, hasTools = !!toolsFiltered.length);
  33075. }
  33076. if ($$self.$$.dirty[0] & /*showToolbar, toolActive, toolsFiltered*/ 6291457) {
  33077. // set to first tool in tools list if not defined
  33078. if (showToolbar && toolActive === undefined) $$invalidate(0, toolActive = toolsFiltered[0][0]);
  33079. }
  33080. if ($$self.$$.dirty[0] & /*toolActive*/ 1) {
  33081. $$invalidate(75, hasActiveTool = toolActive !== undefined);
  33082. }
  33083. if ($$self.$$.dirty[2] & /*hasActiveTool, hasTools, hasShapeControls*/ 14336) {
  33084. $$invalidate(30, shouldRenderControls = (!hasActiveTool || hasTools) && hasShapeControls);
  33085. }
  33086. if ($$self.$$.dirty[0] & /*$isActive, utilKey*/ 16785408 | $$self.$$.dirty[2] & /*$imagePreviewModifiers*/ 16384) {
  33087. //
  33088. // enable seeing the markup outlines outside of the crop area
  33089. //
  33090. if ($isActive) {
  33091. set_store_value(imagePreviewModifiers, $imagePreviewModifiers[utilKey] = { maskMarkupOpacity: 0.85 }, $imagePreviewModifiers);
  33092. } else {
  33093. delete $imagePreviewModifiers[utilKey];
  33094. }
  33095. }
  33096. if ($$self.$$.dirty[0] & /*toolActive*/ 1) {
  33097. if (toolActive) blurOnToolSwitch();
  33098. }
  33099. if ($$self.$$.dirty[2] & /*$isVisible*/ 65536) {
  33100. $$invalidate(32, shouldRenderShapeEditor = $isVisible);
  33101. }
  33102. if ($$self.$$.dirty[0] & /*$utilRect*/ 33554432 | $$self.$$.dirty[2] & /*$stageRect*/ 131072) {
  33103. $$invalidate(33, markupOffset = $utilRect && vectorCreate($stageRect.x - $utilRect.x, $stageRect.y - $utilRect.y));
  33104. }
  33105. if ($$self.$$.dirty[0] & /*shapeControls*/ 128) {
  33106. $$invalidate(80, markupShapeKeys = Object.keys(shapeControls));
  33107. }
  33108. if ($$self.$$.dirty[0] & /*$shapes*/ 67108864) {
  33109. $$invalidate(81, markupSelected = $shapes.filter(shapeIsSelected)[0]);
  33110. }
  33111. if ($$self.$$.dirty[0] & /*$isActive, toolActive*/ 16777217 | $$self.$$.dirty[2] & /*toolShapes*/ 64) {
  33112. $$invalidate(82, markupToolShape = $isActive && (toolShapes[toolActive]
  33113. ? shapeFormat(shapeDeepCopy(toolShapes[toolActive][0]))
  33114. : {}));
  33115. }
  33116. if ($$self.$$.dirty[2] & /*markupToolShape, markupShapeKeys, markupToolStyles*/ 1311744) {
  33117. $$invalidate(77, markupToolStylesComputed = markupToolShape && Object.keys(markupToolShape).reduce(
  33118. (prev, key) => {
  33119. const isDisableStyleProp = key === "disableStyle";
  33120. const isStylableProp = markupShapeKeys.find(shapeKey => shapeKey.split("_").includes(key));
  33121. // skip props that can't be styled, but keep all `disable` props
  33122. if (!isDisableStyleProp && !isStylableProp) return prev;
  33123. // skip props that are set to undefined, this means they won't auto-inherit current styles (line won't inherit line ends)
  33124. if (markupToolShape[key] === undefined) return prev;
  33125. // apply this style
  33126. prev[key] = markupToolStyles[key] || markupToolShape[key];
  33127. return prev;
  33128. },
  33129. {}
  33130. ));
  33131. }
  33132. if ($$self.$$.dirty[2] & /*markupSelected, markupToolStylesComputed*/ 557056) {
  33133. $$invalidate(27, markupShapeSelected = markupSelected || markupToolStylesComputed);
  33134. }
  33135. if ($$self.$$.dirty[0] & /*markupShapeSelected*/ 134217728 | $$self.$$.dirty[2] & /*$shapePreprocessor*/ 2097152) {
  33136. // TODO: remove temporary warning while everyone switches to 8.7.0+
  33137. if (markupShapeSelected && markupShapeSelected.lineEnd && !$shapePreprocessor) {
  33138. console.warn(`Set shapePreprocessor property to draw lineStart and lineEnd styles.\nhttps://pqina.nl/pintura/docs/v8/api/exports/#createshapepreprocessor`);
  33139. }
  33140. }
  33141. if ($$self.$$.dirty[2] & /*markupToolShape*/ 1048576) {
  33142. $$invalidate(34, toolEraseRadius = markupToolShape && isNumber(markupToolShape.eraseRadius)
  33143. ? markupToolShape.eraseRadius
  33144. : undefined);
  33145. }
  33146. if ($$self.$$.dirty[0] & /*$isActiveFraction, toolActive, shapePresets, enablePresetSelectImage*/ 268440065) {
  33147. //
  33148. // presets
  33149. //
  33150. $$invalidate(35, shouldRenderPresets = $isActiveFraction > 0 && toolActive === "preset" && (shapePresets.length > 0 || enablePresetSelectImage));
  33151. }
  33152. if ($$self.$$.dirty[0] & /*$parentRect*/ 8388608) {
  33153. // if parent rect is a `Size` we're sticking presets to the image context
  33154. shouldStickToImage = !hasProp($parentRect, "x") && !hasProp($parentRect, "y");
  33155. }
  33156. if ($$self.$$.dirty[0] & /*pingHub*/ 1048576) {
  33157. $$invalidate(36, ping = pingHub && createPingDispatcher(pingHub));
  33158. }
  33159. if ($$self.$$.dirty[2] & /*willRenderPresetToolbar, $env*/ 4194560) {
  33160. //
  33161. //
  33162. //
  33163. $$invalidate(38, runWillRenderPresetToolbarHook = willRenderPresetToolbar
  33164. ? toolbar => willRenderPresetToolbar(toolbar, addPreset, { ...$env })
  33165. : passthrough);
  33166. }
  33167. if ($$self.$$.dirty[2] & /*hooks*/ 512) {
  33168. //
  33169. // filter out beforeAdd hook
  33170. //
  33171. $$invalidate(39, layoutEditorHooks = Object.keys(hooks).reduce(
  33172. (prev, curr) => {
  33173. if (curr === "beforeAddShape") return prev;
  33174. prev[curr] = hooks[curr];
  33175. return prev;
  33176. },
  33177. {}
  33178. ));
  33179. }
  33180. if ($$self.$$.dirty[0] & /*$isActive*/ 16777216 | $$self.$$.dirty[2] & /*$animation*/ 8388608) {
  33181. $animation && footerOffset.set($isActive ? 0 : 20);
  33182. }
  33183. if ($$self.$$.dirty[2] & /*$footerOffset*/ 16777216) {
  33184. $$invalidate(40, footerStyle = $footerOffset
  33185. ? `transform: translateY(${$footerOffset}px)`
  33186. : undefined);
  33187. }
  33188. };
  33189. $$invalidate(37, computedScrollElasticity = elasticityMultiplier * scrollElasticity);
  33190. return [
  33191. toolActive,
  33192. isActive,
  33193. isActiveFraction,
  33194. isVisible,
  33195. locale,
  33196. shapes,
  33197. toolSelectRadius,
  33198. shapeControls,
  33199. enableButtonFlipVertical,
  33200. enablePresetSelectImage,
  33201. enablePresetDropImage,
  33202. enableTapToAddText,
  33203. shapePresets,
  33204. utilKey,
  33205. mapScreenPointToImagePoint,
  33206. mapImagePointToScreenPoint,
  33207. imageRotation,
  33208. imageFlipX,
  33209. imageFlipY,
  33210. parentRect,
  33211. pingHub,
  33212. toolsFiltered,
  33213. showToolbar,
  33214. $parentRect,
  33215. $isActive,
  33216. $utilRect,
  33217. $shapes,
  33218. markupShapeSelected,
  33219. $isActiveFraction,
  33220. markupEditor,
  33221. shouldRenderControls,
  33222. $rootRect,
  33223. shouldRenderShapeEditor,
  33224. markupOffset,
  33225. toolEraseRadius,
  33226. shouldRenderPresets,
  33227. ping,
  33228. computedScrollElasticity,
  33229. runWillRenderPresetToolbarHook,
  33230. layoutEditorHooks,
  33231. footerStyle,
  33232. $imageOverlayMarkup,
  33233. $presentationScalar,
  33234. env,
  33235. animation,
  33236. rootRect,
  33237. stageRect,
  33238. utilRect,
  33239. imageOverlayMarkup,
  33240. imagePreviewModifiers,
  33241. imageCropRect,
  33242. presentationScalar,
  33243. shapePreprocessor,
  33244. updateActiveTool,
  33245. handleInteractionStart,
  33246. handleInteractionUpdate,
  33247. handleInteractionRelease,
  33248. handleInteractionEnd,
  33249. handleUpdateSelectedMarkupShape,
  33250. handleGrabPreset,
  33251. handleDragPreset,
  33252. handleDropPreset,
  33253. handleAddPreset,
  33254. handleDropFiles,
  33255. handleMarkupUpdate,
  33256. footerOffset,
  33257. stores,
  33258. tools,
  33259. toolShapes,
  33260. enableSelectToolToAddShape,
  33261. willRenderPresetToolbar,
  33262. hooks,
  33263. markupToolStyles,
  33264. hasShapeControls,
  33265. hasTools,
  33266. hasActiveTool,
  33267. $imagePreviewModifiers,
  33268. markupToolStylesComputed,
  33269. $isVisible,
  33270. $stageRect,
  33271. markupShapeKeys,
  33272. markupSelected,
  33273. markupToolShape,
  33274. $shapePreprocessor,
  33275. $env,
  33276. $animation,
  33277. $footerOffset,
  33278. measure_handler_1,
  33279. func,
  33280. func_1,
  33281. func_2,
  33282. func_3,
  33283. func_4,
  33284. shapelayouteditor_binding,
  33285. shapelayouteditor_markup_binding,
  33286. shapelayouteditor_ui_binding,
  33287. div_binding,
  33288. measure_handler
  33289. ];
  33290. }
  33291. class ShapeUtil extends SvelteComponent {
  33292. constructor(options) {
  33293. super();
  33294. init(
  33295. this,
  33296. options,
  33297. instance$9,
  33298. create_fragment$9,
  33299. safe_not_equal,
  33300. {
  33301. isActive: 1,
  33302. isActiveFraction: 2,
  33303. isVisible: 3,
  33304. stores: 66,
  33305. locale: 4,
  33306. shapes: 5,
  33307. tools: 67,
  33308. toolShapes: 68,
  33309. toolActive: 0,
  33310. toolSelectRadius: 6,
  33311. shapeControls: 7,
  33312. enableButtonFlipVertical: 8,
  33313. enablePresetSelectImage: 9,
  33314. enablePresetDropImage: 10,
  33315. enableSelectToolToAddShape: 69,
  33316. enableTapToAddText: 11,
  33317. willRenderPresetToolbar: 70,
  33318. shapePresets: 12,
  33319. utilKey: 13,
  33320. mapScreenPointToImagePoint: 14,
  33321. mapImagePointToScreenPoint: 15,
  33322. imageRotation: 16,
  33323. imageFlipX: 17,
  33324. imageFlipY: 18,
  33325. parentRect: 19,
  33326. hooks: 71
  33327. },
  33328. [-1, -1, -1, -1]
  33329. );
  33330. }
  33331. get isActive() {
  33332. return this.$$.ctx[1];
  33333. }
  33334. set isActive(isActive) {
  33335. this.$set({ isActive });
  33336. flush();
  33337. }
  33338. get isActiveFraction() {
  33339. return this.$$.ctx[2];
  33340. }
  33341. set isActiveFraction(isActiveFraction) {
  33342. this.$set({ isActiveFraction });
  33343. flush();
  33344. }
  33345. get isVisible() {
  33346. return this.$$.ctx[3];
  33347. }
  33348. set isVisible(isVisible) {
  33349. this.$set({ isVisible });
  33350. flush();
  33351. }
  33352. get stores() {
  33353. return this.$$.ctx[66];
  33354. }
  33355. set stores(stores) {
  33356. this.$set({ stores });
  33357. flush();
  33358. }
  33359. get locale() {
  33360. return this.$$.ctx[4];
  33361. }
  33362. set locale(locale) {
  33363. this.$set({ locale });
  33364. flush();
  33365. }
  33366. get shapes() {
  33367. return this.$$.ctx[5];
  33368. }
  33369. set shapes(shapes) {
  33370. this.$set({ shapes });
  33371. flush();
  33372. }
  33373. get tools() {
  33374. return this.$$.ctx[67];
  33375. }
  33376. set tools(tools) {
  33377. this.$set({ tools });
  33378. flush();
  33379. }
  33380. get toolShapes() {
  33381. return this.$$.ctx[68];
  33382. }
  33383. set toolShapes(toolShapes) {
  33384. this.$set({ toolShapes });
  33385. flush();
  33386. }
  33387. get toolActive() {
  33388. return this.$$.ctx[0];
  33389. }
  33390. set toolActive(toolActive) {
  33391. this.$set({ toolActive });
  33392. flush();
  33393. }
  33394. get toolSelectRadius() {
  33395. return this.$$.ctx[6];
  33396. }
  33397. set toolSelectRadius(toolSelectRadius) {
  33398. this.$set({ toolSelectRadius });
  33399. flush();
  33400. }
  33401. get shapeControls() {
  33402. return this.$$.ctx[7];
  33403. }
  33404. set shapeControls(shapeControls) {
  33405. this.$set({ shapeControls });
  33406. flush();
  33407. }
  33408. get enableButtonFlipVertical() {
  33409. return this.$$.ctx[8];
  33410. }
  33411. set enableButtonFlipVertical(enableButtonFlipVertical) {
  33412. this.$set({ enableButtonFlipVertical });
  33413. flush();
  33414. }
  33415. get enablePresetSelectImage() {
  33416. return this.$$.ctx[9];
  33417. }
  33418. set enablePresetSelectImage(enablePresetSelectImage) {
  33419. this.$set({ enablePresetSelectImage });
  33420. flush();
  33421. }
  33422. get enablePresetDropImage() {
  33423. return this.$$.ctx[10];
  33424. }
  33425. set enablePresetDropImage(enablePresetDropImage) {
  33426. this.$set({ enablePresetDropImage });
  33427. flush();
  33428. }
  33429. get enableSelectToolToAddShape() {
  33430. return this.$$.ctx[69];
  33431. }
  33432. set enableSelectToolToAddShape(enableSelectToolToAddShape) {
  33433. this.$set({ enableSelectToolToAddShape });
  33434. flush();
  33435. }
  33436. get enableTapToAddText() {
  33437. return this.$$.ctx[11];
  33438. }
  33439. set enableTapToAddText(enableTapToAddText) {
  33440. this.$set({ enableTapToAddText });
  33441. flush();
  33442. }
  33443. get willRenderPresetToolbar() {
  33444. return this.$$.ctx[70];
  33445. }
  33446. set willRenderPresetToolbar(willRenderPresetToolbar) {
  33447. this.$set({ willRenderPresetToolbar });
  33448. flush();
  33449. }
  33450. get shapePresets() {
  33451. return this.$$.ctx[12];
  33452. }
  33453. set shapePresets(shapePresets) {
  33454. this.$set({ shapePresets });
  33455. flush();
  33456. }
  33457. get utilKey() {
  33458. return this.$$.ctx[13];
  33459. }
  33460. set utilKey(utilKey) {
  33461. this.$set({ utilKey });
  33462. flush();
  33463. }
  33464. get mapScreenPointToImagePoint() {
  33465. return this.$$.ctx[14];
  33466. }
  33467. set mapScreenPointToImagePoint(mapScreenPointToImagePoint) {
  33468. this.$set({ mapScreenPointToImagePoint });
  33469. flush();
  33470. }
  33471. get mapImagePointToScreenPoint() {
  33472. return this.$$.ctx[15];
  33473. }
  33474. set mapImagePointToScreenPoint(mapImagePointToScreenPoint) {
  33475. this.$set({ mapImagePointToScreenPoint });
  33476. flush();
  33477. }
  33478. get imageRotation() {
  33479. return this.$$.ctx[16];
  33480. }
  33481. set imageRotation(imageRotation) {
  33482. this.$set({ imageRotation });
  33483. flush();
  33484. }
  33485. get imageFlipX() {
  33486. return this.$$.ctx[17];
  33487. }
  33488. set imageFlipX(imageFlipX) {
  33489. this.$set({ imageFlipX });
  33490. flush();
  33491. }
  33492. get imageFlipY() {
  33493. return this.$$.ctx[18];
  33494. }
  33495. set imageFlipY(imageFlipY) {
  33496. this.$set({ imageFlipY });
  33497. flush();
  33498. }
  33499. get parentRect() {
  33500. return this.$$.ctx[19];
  33501. }
  33502. set parentRect(parentRect) {
  33503. this.$set({ parentRect });
  33504. flush();
  33505. }
  33506. get hooks() {
  33507. return this.$$.ctx[71];
  33508. }
  33509. set hooks(hooks) {
  33510. this.$set({ hooks });
  33511. flush();
  33512. }
  33513. }
  33514. var _mapImagePointToScreenPoint = (imagePoint, canvasSize, imageSize, imageOrigin, imageTranslation, imageRotation, imageScalar, imageFlipX, imageFlipY) => {
  33515. const mappedPoint = vectorClone(imagePoint);
  33516. const imageCenterX = imageSize.width * 0.5;
  33517. const imageCenterY = imageSize.height * 0.5;
  33518. const canvasCenterX = canvasSize.width * 0.5;
  33519. const canvasCenterY = canvasSize.height * 0.5;
  33520. const imageOffsetX = imageTranslation.x + imageOrigin.x;
  33521. const imageOffsetY = imageTranslation.y + imageOrigin.y;
  33522. if (imageFlipX)
  33523. mappedPoint.x = imageSize.width - mappedPoint.x;
  33524. if (imageFlipY)
  33525. mappedPoint.y = imageSize.height - mappedPoint.y;
  33526. // rotate around image center based on if image is rotated
  33527. const c = Math.cos(imageRotation);
  33528. const s = Math.sin(imageRotation);
  33529. mappedPoint.x -= imageCenterX;
  33530. mappedPoint.y -= imageCenterY;
  33531. const rx = mappedPoint.x * c - mappedPoint.y * s;
  33532. const ry = mappedPoint.x * s + mappedPoint.y * c;
  33533. mappedPoint.x = imageCenterX + rx;
  33534. mappedPoint.y = imageCenterY + ry;
  33535. // position based on screen transforms
  33536. mappedPoint.x *= imageScalar;
  33537. mappedPoint.y *= imageScalar;
  33538. mappedPoint.x += canvasCenterX;
  33539. mappedPoint.y += canvasCenterY;
  33540. mappedPoint.x += imageOffsetX;
  33541. mappedPoint.y += imageOffsetY;
  33542. mappedPoint.x -= imageCenterX * imageScalar;
  33543. mappedPoint.y -= imageCenterY * imageScalar;
  33544. const tx = (imageTranslation.x - imageOffsetX) * imageScalar;
  33545. const ty = (imageTranslation.y - imageOffsetY) * imageScalar;
  33546. const rtx = tx * c - ty * s;
  33547. const rty = tx * s + ty * c;
  33548. mappedPoint.x += rtx;
  33549. mappedPoint.y += rty;
  33550. return mappedPoint;
  33551. };
  33552. var _mapScreenPointToImagePoint = (screenPoint, canvasSize, imageSize, imageOrigin, imageTranslation, imageRotation, imageScalar, imageFlipX, imageFlipY) => {
  33553. const mappedPoint = vectorClone(screenPoint);
  33554. const imageCenter = sizeCenter(imageSize);
  33555. const canvasCenter = sizeCenter(canvasSize);
  33556. const imageOffset = vectorCreate(imageTranslation.x + imageOrigin.x, imageTranslation.y + imageOrigin.y);
  33557. const c = Math.cos(imageRotation);
  33558. const s = Math.sin(imageRotation);
  33559. mappedPoint.x -= canvasCenter.x;
  33560. mappedPoint.y -= canvasCenter.y;
  33561. const tx = (imageTranslation.x - imageOffset.x) * imageScalar;
  33562. const ty = (imageTranslation.y - imageOffset.y) * imageScalar;
  33563. const rtx = tx * c - ty * s;
  33564. const rty = tx * s + ty * c;
  33565. mappedPoint.x -= rtx;
  33566. mappedPoint.y -= rty;
  33567. mappedPoint.x -= imageOffset.x;
  33568. mappedPoint.y -= imageOffset.y;
  33569. mappedPoint.x /= imageScalar;
  33570. mappedPoint.y /= imageScalar;
  33571. const rx = mappedPoint.x * c + mappedPoint.y * s;
  33572. const ry = mappedPoint.x * s - mappedPoint.y * c;
  33573. mappedPoint.x = rx;
  33574. mappedPoint.y = -ry;
  33575. mappedPoint.x += imageCenter.x;
  33576. mappedPoint.y += imageCenter.y;
  33577. if (imageFlipX)
  33578. mappedPoint.x = imageSize.width - mappedPoint.x;
  33579. if (imageFlipY)
  33580. mappedPoint.y = imageSize.height - mappedPoint.y;
  33581. return mappedPoint;
  33582. };
  33583. /* src/core/ui/plugins/annotate/index.svelte generated by Svelte v3.37.0 */
  33584. function create_fragment$8(ctx) {
  33585. let shapeutil;
  33586. let updating_toolActive;
  33587. let current;
  33588. function shapeutil_toolActive_binding(value) {
  33589. /*shapeutil_toolActive_binding*/ ctx[39](value);
  33590. }
  33591. let shapeutil_props = {
  33592. stores: /*stores*/ ctx[4],
  33593. locale: /*locale*/ ctx[5],
  33594. isActive: /*isActive*/ ctx[1],
  33595. isActiveFraction: /*isActiveFraction*/ ctx[2],
  33596. isVisible: /*isVisible*/ ctx[3],
  33597. mapScreenPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[36],
  33598. mapImagePointToScreenPoint: /*mapImagePointToScreenPoint*/ ctx[37],
  33599. utilKey: "annotate",
  33600. imageRotation: /*$imageRotation*/ ctx[28],
  33601. imageFlipX: /*$imageFlipX*/ ctx[26],
  33602. imageFlipY: /*$imageFlipY*/ ctx[27],
  33603. shapes: /*imageAnnotation*/ ctx[30],
  33604. tools: /*annotateTools*/ ctx[11] || /*markupEditorToolbar*/ ctx[6],
  33605. toolShapes: /*annotateToolShapes*/ ctx[12] || /*markupEditorToolStyles*/ ctx[7],
  33606. enableSelectToolToAddShape: /*enableSelectToolToAddShape*/ ctx[18],
  33607. enableTapToAddText: /*enableTapToAddText*/ ctx[19],
  33608. shapeControls: /*annotateShapeControls*/ ctx[13] || /*markupEditorShapeStyleControls*/ ctx[8],
  33609. shapePresets: /*annotatePresets*/ ctx[16],
  33610. enableButtonFlipVertical: /*annotateEnableButtonFlipVertical*/ ctx[14],
  33611. parentRect: /*imageSize*/ ctx[31],
  33612. enablePresetSelectImage: /*annotateEnableSelectImagePreset*/ ctx[15],
  33613. toolSelectRadius: /*markupEditorToolSelectRadius*/ ctx[9],
  33614. willRenderPresetToolbar: /*annotateWillRenderShapePresetToolbar*/ ctx[17] || /*willRenderShapePresetToolbar*/ ctx[10],
  33615. hooks: {
  33616. willRenderShapeControls: /*willRenderShapeControls*/ ctx[20],
  33617. beforeAddShape: /*beforeAddShape*/ ctx[21],
  33618. beforeRemoveShape: /*beforeRemoveShape*/ ctx[22],
  33619. beforeDeselectShape: /*beforeDeselectShape*/ ctx[23],
  33620. beforeSelectShape: /*beforeSelectShape*/ ctx[24],
  33621. beforeUpdateShape: /*beforeUpdateShape*/ ctx[25]
  33622. }
  33623. };
  33624. if (/*annotateActiveTool*/ ctx[0] !== void 0) {
  33625. shapeutil_props.toolActive = /*annotateActiveTool*/ ctx[0];
  33626. }
  33627. shapeutil = new ShapeUtil({ props: shapeutil_props });
  33628. binding_callbacks.push(() => bind(shapeutil, "toolActive", shapeutil_toolActive_binding));
  33629. shapeutil.$on("measure", /*measure_handler*/ ctx[40]);
  33630. return {
  33631. c() {
  33632. create_component(shapeutil.$$.fragment);
  33633. },
  33634. m(target, anchor) {
  33635. mount_component(shapeutil, target, anchor);
  33636. current = true;
  33637. },
  33638. p(ctx, dirty) {
  33639. const shapeutil_changes = {};
  33640. if (dirty[0] & /*stores*/ 16) shapeutil_changes.stores = /*stores*/ ctx[4];
  33641. if (dirty[0] & /*locale*/ 32) shapeutil_changes.locale = /*locale*/ ctx[5];
  33642. if (dirty[0] & /*isActive*/ 2) shapeutil_changes.isActive = /*isActive*/ ctx[1];
  33643. if (dirty[0] & /*isActiveFraction*/ 4) shapeutil_changes.isActiveFraction = /*isActiveFraction*/ ctx[2];
  33644. if (dirty[0] & /*isVisible*/ 8) shapeutil_changes.isVisible = /*isVisible*/ ctx[3];
  33645. if (dirty[0] & /*$imageRotation*/ 268435456) shapeutil_changes.imageRotation = /*$imageRotation*/ ctx[28];
  33646. if (dirty[0] & /*$imageFlipX*/ 67108864) shapeutil_changes.imageFlipX = /*$imageFlipX*/ ctx[26];
  33647. if (dirty[0] & /*$imageFlipY*/ 134217728) shapeutil_changes.imageFlipY = /*$imageFlipY*/ ctx[27];
  33648. if (dirty[0] & /*annotateTools, markupEditorToolbar*/ 2112) shapeutil_changes.tools = /*annotateTools*/ ctx[11] || /*markupEditorToolbar*/ ctx[6];
  33649. if (dirty[0] & /*annotateToolShapes, markupEditorToolStyles*/ 4224) shapeutil_changes.toolShapes = /*annotateToolShapes*/ ctx[12] || /*markupEditorToolStyles*/ ctx[7];
  33650. if (dirty[0] & /*enableSelectToolToAddShape*/ 262144) shapeutil_changes.enableSelectToolToAddShape = /*enableSelectToolToAddShape*/ ctx[18];
  33651. if (dirty[0] & /*enableTapToAddText*/ 524288) shapeutil_changes.enableTapToAddText = /*enableTapToAddText*/ ctx[19];
  33652. if (dirty[0] & /*annotateShapeControls, markupEditorShapeStyleControls*/ 8448) shapeutil_changes.shapeControls = /*annotateShapeControls*/ ctx[13] || /*markupEditorShapeStyleControls*/ ctx[8];
  33653. if (dirty[0] & /*annotatePresets*/ 65536) shapeutil_changes.shapePresets = /*annotatePresets*/ ctx[16];
  33654. if (dirty[0] & /*annotateEnableButtonFlipVertical*/ 16384) shapeutil_changes.enableButtonFlipVertical = /*annotateEnableButtonFlipVertical*/ ctx[14];
  33655. if (dirty[0] & /*annotateEnableSelectImagePreset*/ 32768) shapeutil_changes.enablePresetSelectImage = /*annotateEnableSelectImagePreset*/ ctx[15];
  33656. if (dirty[0] & /*markupEditorToolSelectRadius*/ 512) shapeutil_changes.toolSelectRadius = /*markupEditorToolSelectRadius*/ ctx[9];
  33657. if (dirty[0] & /*annotateWillRenderShapePresetToolbar, willRenderShapePresetToolbar*/ 132096) shapeutil_changes.willRenderPresetToolbar = /*annotateWillRenderShapePresetToolbar*/ ctx[17] || /*willRenderShapePresetToolbar*/ ctx[10];
  33658. if (dirty[0] & /*willRenderShapeControls, beforeAddShape, beforeRemoveShape, beforeDeselectShape, beforeSelectShape, beforeUpdateShape*/ 66060288) shapeutil_changes.hooks = {
  33659. willRenderShapeControls: /*willRenderShapeControls*/ ctx[20],
  33660. beforeAddShape: /*beforeAddShape*/ ctx[21],
  33661. beforeRemoveShape: /*beforeRemoveShape*/ ctx[22],
  33662. beforeDeselectShape: /*beforeDeselectShape*/ ctx[23],
  33663. beforeSelectShape: /*beforeSelectShape*/ ctx[24],
  33664. beforeUpdateShape: /*beforeUpdateShape*/ ctx[25]
  33665. };
  33666. if (!updating_toolActive && dirty[0] & /*annotateActiveTool*/ 1) {
  33667. updating_toolActive = true;
  33668. shapeutil_changes.toolActive = /*annotateActiveTool*/ ctx[0];
  33669. add_flush_callback(() => updating_toolActive = false);
  33670. }
  33671. shapeutil.$set(shapeutil_changes);
  33672. },
  33673. i(local) {
  33674. if (current) return;
  33675. transition_in(shapeutil.$$.fragment, local);
  33676. current = true;
  33677. },
  33678. o(local) {
  33679. transition_out(shapeutil.$$.fragment, local);
  33680. current = false;
  33681. },
  33682. d(detaching) {
  33683. destroy_component(shapeutil, detaching);
  33684. }
  33685. };
  33686. }
  33687. function instance$8($$self, $$props, $$invalidate) {
  33688. let $rootRect;
  33689. let $imageSize;
  33690. let $imageTransforms;
  33691. let $imageFlipX;
  33692. let $imageFlipY;
  33693. let $imageRotation;
  33694. const name = "annotate";
  33695. let { isActive } = $$props;
  33696. let { isActiveFraction } = $$props;
  33697. let { isVisible } = $$props;
  33698. let { stores } = $$props;
  33699. let { locale = {} } = $$props;
  33700. let { markupEditorToolbar = undefined } = $$props;
  33701. let { markupEditorToolStyles = undefined } = $$props;
  33702. let { markupEditorShapeStyleControls = undefined } = $$props;
  33703. let { markupEditorToolSelectRadius = undefined } = $$props;
  33704. let { willRenderShapePresetToolbar = undefined } = $$props;
  33705. let { annotateTools = undefined } = $$props;
  33706. let { annotateToolShapes = undefined } = $$props;
  33707. let { annotateShapeControls = undefined } = $$props;
  33708. let { annotateActiveTool = undefined } = $$props;
  33709. let { annotateEnableButtonFlipVertical = false } = $$props;
  33710. let { annotateEnableSelectImagePreset = false } = $$props;
  33711. let { annotatePresets = [] } = $$props;
  33712. let { annotateWillRenderShapePresetToolbar = undefined } = $$props;
  33713. let { enableSelectToolToAddShape = undefined } = $$props;
  33714. let { enableTapToAddText = undefined } = $$props;
  33715. let { willRenderShapeControls = undefined } = $$props;
  33716. let { beforeAddShape = undefined } = $$props;
  33717. let { beforeRemoveShape = undefined } = $$props;
  33718. let { beforeDeselectShape = undefined } = $$props;
  33719. let { beforeSelectShape = undefined } = $$props;
  33720. let { beforeUpdateShape = undefined } = $$props;
  33721. // connect filter choice to stores
  33722. const { rootRect, imageAnnotation, imageSize, imageTransforms, imageRotation, imageFlipX, imageFlipY } = stores;
  33723. component_subscribe($$self, rootRect, value => $$invalidate(41, $rootRect = value));
  33724. component_subscribe($$self, imageSize, value => $$invalidate(42, $imageSize = value));
  33725. component_subscribe($$self, imageTransforms, value => $$invalidate(43, $imageTransforms = value));
  33726. component_subscribe($$self, imageRotation, value => $$invalidate(28, $imageRotation = value));
  33727. component_subscribe($$self, imageFlipX, value => $$invalidate(26, $imageFlipX = value));
  33728. component_subscribe($$self, imageFlipY, value => $$invalidate(27, $imageFlipY = value));
  33729. //
  33730. // Mapping coordinates
  33731. //
  33732. const mapScreenPointToImagePoint = point => _mapScreenPointToImagePoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY);
  33733. const mapImagePointToScreenPoint = point => _mapImagePointToScreenPoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY);
  33734. function shapeutil_toolActive_binding(value) {
  33735. annotateActiveTool = value;
  33736. $$invalidate(0, annotateActiveTool);
  33737. }
  33738. function measure_handler(event) {
  33739. bubble($$self, event);
  33740. }
  33741. $$self.$$set = $$props => {
  33742. if ("isActive" in $$props) $$invalidate(1, isActive = $$props.isActive);
  33743. if ("isActiveFraction" in $$props) $$invalidate(2, isActiveFraction = $$props.isActiveFraction);
  33744. if ("isVisible" in $$props) $$invalidate(3, isVisible = $$props.isVisible);
  33745. if ("stores" in $$props) $$invalidate(4, stores = $$props.stores);
  33746. if ("locale" in $$props) $$invalidate(5, locale = $$props.locale);
  33747. if ("markupEditorToolbar" in $$props) $$invalidate(6, markupEditorToolbar = $$props.markupEditorToolbar);
  33748. if ("markupEditorToolStyles" in $$props) $$invalidate(7, markupEditorToolStyles = $$props.markupEditorToolStyles);
  33749. if ("markupEditorShapeStyleControls" in $$props) $$invalidate(8, markupEditorShapeStyleControls = $$props.markupEditorShapeStyleControls);
  33750. if ("markupEditorToolSelectRadius" in $$props) $$invalidate(9, markupEditorToolSelectRadius = $$props.markupEditorToolSelectRadius);
  33751. if ("willRenderShapePresetToolbar" in $$props) $$invalidate(10, willRenderShapePresetToolbar = $$props.willRenderShapePresetToolbar);
  33752. if ("annotateTools" in $$props) $$invalidate(11, annotateTools = $$props.annotateTools);
  33753. if ("annotateToolShapes" in $$props) $$invalidate(12, annotateToolShapes = $$props.annotateToolShapes);
  33754. if ("annotateShapeControls" in $$props) $$invalidate(13, annotateShapeControls = $$props.annotateShapeControls);
  33755. if ("annotateActiveTool" in $$props) $$invalidate(0, annotateActiveTool = $$props.annotateActiveTool);
  33756. if ("annotateEnableButtonFlipVertical" in $$props) $$invalidate(14, annotateEnableButtonFlipVertical = $$props.annotateEnableButtonFlipVertical);
  33757. if ("annotateEnableSelectImagePreset" in $$props) $$invalidate(15, annotateEnableSelectImagePreset = $$props.annotateEnableSelectImagePreset);
  33758. if ("annotatePresets" in $$props) $$invalidate(16, annotatePresets = $$props.annotatePresets);
  33759. if ("annotateWillRenderShapePresetToolbar" in $$props) $$invalidate(17, annotateWillRenderShapePresetToolbar = $$props.annotateWillRenderShapePresetToolbar);
  33760. if ("enableSelectToolToAddShape" in $$props) $$invalidate(18, enableSelectToolToAddShape = $$props.enableSelectToolToAddShape);
  33761. if ("enableTapToAddText" in $$props) $$invalidate(19, enableTapToAddText = $$props.enableTapToAddText);
  33762. if ("willRenderShapeControls" in $$props) $$invalidate(20, willRenderShapeControls = $$props.willRenderShapeControls);
  33763. if ("beforeAddShape" in $$props) $$invalidate(21, beforeAddShape = $$props.beforeAddShape);
  33764. if ("beforeRemoveShape" in $$props) $$invalidate(22, beforeRemoveShape = $$props.beforeRemoveShape);
  33765. if ("beforeDeselectShape" in $$props) $$invalidate(23, beforeDeselectShape = $$props.beforeDeselectShape);
  33766. if ("beforeSelectShape" in $$props) $$invalidate(24, beforeSelectShape = $$props.beforeSelectShape);
  33767. if ("beforeUpdateShape" in $$props) $$invalidate(25, beforeUpdateShape = $$props.beforeUpdateShape);
  33768. };
  33769. return [
  33770. annotateActiveTool,
  33771. isActive,
  33772. isActiveFraction,
  33773. isVisible,
  33774. stores,
  33775. locale,
  33776. markupEditorToolbar,
  33777. markupEditorToolStyles,
  33778. markupEditorShapeStyleControls,
  33779. markupEditorToolSelectRadius,
  33780. willRenderShapePresetToolbar,
  33781. annotateTools,
  33782. annotateToolShapes,
  33783. annotateShapeControls,
  33784. annotateEnableButtonFlipVertical,
  33785. annotateEnableSelectImagePreset,
  33786. annotatePresets,
  33787. annotateWillRenderShapePresetToolbar,
  33788. enableSelectToolToAddShape,
  33789. enableTapToAddText,
  33790. willRenderShapeControls,
  33791. beforeAddShape,
  33792. beforeRemoveShape,
  33793. beforeDeselectShape,
  33794. beforeSelectShape,
  33795. beforeUpdateShape,
  33796. $imageFlipX,
  33797. $imageFlipY,
  33798. $imageRotation,
  33799. rootRect,
  33800. imageAnnotation,
  33801. imageSize,
  33802. imageTransforms,
  33803. imageRotation,
  33804. imageFlipX,
  33805. imageFlipY,
  33806. mapScreenPointToImagePoint,
  33807. mapImagePointToScreenPoint,
  33808. name,
  33809. shapeutil_toolActive_binding,
  33810. measure_handler
  33811. ];
  33812. }
  33813. class Annotate extends SvelteComponent {
  33814. constructor(options) {
  33815. super();
  33816. init(
  33817. this,
  33818. options,
  33819. instance$8,
  33820. create_fragment$8,
  33821. safe_not_equal,
  33822. {
  33823. name: 38,
  33824. isActive: 1,
  33825. isActiveFraction: 2,
  33826. isVisible: 3,
  33827. stores: 4,
  33828. locale: 5,
  33829. markupEditorToolbar: 6,
  33830. markupEditorToolStyles: 7,
  33831. markupEditorShapeStyleControls: 8,
  33832. markupEditorToolSelectRadius: 9,
  33833. willRenderShapePresetToolbar: 10,
  33834. annotateTools: 11,
  33835. annotateToolShapes: 12,
  33836. annotateShapeControls: 13,
  33837. annotateActiveTool: 0,
  33838. annotateEnableButtonFlipVertical: 14,
  33839. annotateEnableSelectImagePreset: 15,
  33840. annotatePresets: 16,
  33841. annotateWillRenderShapePresetToolbar: 17,
  33842. enableSelectToolToAddShape: 18,
  33843. enableTapToAddText: 19,
  33844. willRenderShapeControls: 20,
  33845. beforeAddShape: 21,
  33846. beforeRemoveShape: 22,
  33847. beforeDeselectShape: 23,
  33848. beforeSelectShape: 24,
  33849. beforeUpdateShape: 25
  33850. },
  33851. [-1, -1]
  33852. );
  33853. }
  33854. get name() {
  33855. return this.$$.ctx[38];
  33856. }
  33857. get isActive() {
  33858. return this.$$.ctx[1];
  33859. }
  33860. set isActive(isActive) {
  33861. this.$set({ isActive });
  33862. flush();
  33863. }
  33864. get isActiveFraction() {
  33865. return this.$$.ctx[2];
  33866. }
  33867. set isActiveFraction(isActiveFraction) {
  33868. this.$set({ isActiveFraction });
  33869. flush();
  33870. }
  33871. get isVisible() {
  33872. return this.$$.ctx[3];
  33873. }
  33874. set isVisible(isVisible) {
  33875. this.$set({ isVisible });
  33876. flush();
  33877. }
  33878. get stores() {
  33879. return this.$$.ctx[4];
  33880. }
  33881. set stores(stores) {
  33882. this.$set({ stores });
  33883. flush();
  33884. }
  33885. get locale() {
  33886. return this.$$.ctx[5];
  33887. }
  33888. set locale(locale) {
  33889. this.$set({ locale });
  33890. flush();
  33891. }
  33892. get markupEditorToolbar() {
  33893. return this.$$.ctx[6];
  33894. }
  33895. set markupEditorToolbar(markupEditorToolbar) {
  33896. this.$set({ markupEditorToolbar });
  33897. flush();
  33898. }
  33899. get markupEditorToolStyles() {
  33900. return this.$$.ctx[7];
  33901. }
  33902. set markupEditorToolStyles(markupEditorToolStyles) {
  33903. this.$set({ markupEditorToolStyles });
  33904. flush();
  33905. }
  33906. get markupEditorShapeStyleControls() {
  33907. return this.$$.ctx[8];
  33908. }
  33909. set markupEditorShapeStyleControls(markupEditorShapeStyleControls) {
  33910. this.$set({ markupEditorShapeStyleControls });
  33911. flush();
  33912. }
  33913. get markupEditorToolSelectRadius() {
  33914. return this.$$.ctx[9];
  33915. }
  33916. set markupEditorToolSelectRadius(markupEditorToolSelectRadius) {
  33917. this.$set({ markupEditorToolSelectRadius });
  33918. flush();
  33919. }
  33920. get willRenderShapePresetToolbar() {
  33921. return this.$$.ctx[10];
  33922. }
  33923. set willRenderShapePresetToolbar(willRenderShapePresetToolbar) {
  33924. this.$set({ willRenderShapePresetToolbar });
  33925. flush();
  33926. }
  33927. get annotateTools() {
  33928. return this.$$.ctx[11];
  33929. }
  33930. set annotateTools(annotateTools) {
  33931. this.$set({ annotateTools });
  33932. flush();
  33933. }
  33934. get annotateToolShapes() {
  33935. return this.$$.ctx[12];
  33936. }
  33937. set annotateToolShapes(annotateToolShapes) {
  33938. this.$set({ annotateToolShapes });
  33939. flush();
  33940. }
  33941. get annotateShapeControls() {
  33942. return this.$$.ctx[13];
  33943. }
  33944. set annotateShapeControls(annotateShapeControls) {
  33945. this.$set({ annotateShapeControls });
  33946. flush();
  33947. }
  33948. get annotateActiveTool() {
  33949. return this.$$.ctx[0];
  33950. }
  33951. set annotateActiveTool(annotateActiveTool) {
  33952. this.$set({ annotateActiveTool });
  33953. flush();
  33954. }
  33955. get annotateEnableButtonFlipVertical() {
  33956. return this.$$.ctx[14];
  33957. }
  33958. set annotateEnableButtonFlipVertical(annotateEnableButtonFlipVertical) {
  33959. this.$set({ annotateEnableButtonFlipVertical });
  33960. flush();
  33961. }
  33962. get annotateEnableSelectImagePreset() {
  33963. return this.$$.ctx[15];
  33964. }
  33965. set annotateEnableSelectImagePreset(annotateEnableSelectImagePreset) {
  33966. this.$set({ annotateEnableSelectImagePreset });
  33967. flush();
  33968. }
  33969. get annotatePresets() {
  33970. return this.$$.ctx[16];
  33971. }
  33972. set annotatePresets(annotatePresets) {
  33973. this.$set({ annotatePresets });
  33974. flush();
  33975. }
  33976. get annotateWillRenderShapePresetToolbar() {
  33977. return this.$$.ctx[17];
  33978. }
  33979. set annotateWillRenderShapePresetToolbar(annotateWillRenderShapePresetToolbar) {
  33980. this.$set({ annotateWillRenderShapePresetToolbar });
  33981. flush();
  33982. }
  33983. get enableSelectToolToAddShape() {
  33984. return this.$$.ctx[18];
  33985. }
  33986. set enableSelectToolToAddShape(enableSelectToolToAddShape) {
  33987. this.$set({ enableSelectToolToAddShape });
  33988. flush();
  33989. }
  33990. get enableTapToAddText() {
  33991. return this.$$.ctx[19];
  33992. }
  33993. set enableTapToAddText(enableTapToAddText) {
  33994. this.$set({ enableTapToAddText });
  33995. flush();
  33996. }
  33997. get willRenderShapeControls() {
  33998. return this.$$.ctx[20];
  33999. }
  34000. set willRenderShapeControls(willRenderShapeControls) {
  34001. this.$set({ willRenderShapeControls });
  34002. flush();
  34003. }
  34004. get beforeAddShape() {
  34005. return this.$$.ctx[21];
  34006. }
  34007. set beforeAddShape(beforeAddShape) {
  34008. this.$set({ beforeAddShape });
  34009. flush();
  34010. }
  34011. get beforeRemoveShape() {
  34012. return this.$$.ctx[22];
  34013. }
  34014. set beforeRemoveShape(beforeRemoveShape) {
  34015. this.$set({ beforeRemoveShape });
  34016. flush();
  34017. }
  34018. get beforeDeselectShape() {
  34019. return this.$$.ctx[23];
  34020. }
  34021. set beforeDeselectShape(beforeDeselectShape) {
  34022. this.$set({ beforeDeselectShape });
  34023. flush();
  34024. }
  34025. get beforeSelectShape() {
  34026. return this.$$.ctx[24];
  34027. }
  34028. set beforeSelectShape(beforeSelectShape) {
  34029. this.$set({ beforeSelectShape });
  34030. flush();
  34031. }
  34032. get beforeUpdateShape() {
  34033. return this.$$.ctx[25];
  34034. }
  34035. set beforeUpdateShape(beforeUpdateShape) {
  34036. this.$set({ beforeUpdateShape });
  34037. flush();
  34038. }
  34039. }
  34040. // @ts-ignore
  34041. var _plugin_annotate = { util: ['annotate', Annotate] };
  34042. /* src/core/ui/plugins/decorate/index.svelte generated by Svelte v3.37.0 */
  34043. function create_fragment$7(ctx) {
  34044. let shapeutil;
  34045. let updating_toolActive;
  34046. let current;
  34047. function shapeutil_toolActive_binding(value) {
  34048. /*shapeutil_toolActive_binding*/ ctx[33](value);
  34049. }
  34050. let shapeutil_props = {
  34051. stores: /*stores*/ ctx[4],
  34052. locale: /*locale*/ ctx[5],
  34053. isActive: /*isActive*/ ctx[1],
  34054. isActiveFraction: /*isActiveFraction*/ ctx[2],
  34055. isVisible: /*isVisible*/ ctx[3],
  34056. mapScreenPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[30],
  34057. mapImagePointToScreenPoint: /*mapImagePointToScreenPoint*/ ctx[31],
  34058. utilKey: "decorate",
  34059. shapes: /*imageDecoration*/ ctx[27],
  34060. tools: /*decorateTools*/ ctx[11] || /*markupEditorToolbar*/ ctx[6],
  34061. toolShapes: /*decorateToolShapes*/ ctx[12] || /*markupEditorToolStyles*/ ctx[7],
  34062. shapeControls: /*decorateShapeControls*/ ctx[13] || /*markupEditorShapeStyleControls*/ ctx[8],
  34063. shapePresets: /*decoratePresets*/ ctx[16],
  34064. enableSelectToolToAddShape: /*enableSelectToolToAddShape*/ ctx[18],
  34065. enableTapToAddText: /*enableTapToAddText*/ ctx[19],
  34066. enablePresetSelectImage: /*decorateEnableSelectImagePreset*/ ctx[15],
  34067. enableButtonFlipVertical: /*decorateEnableButtonFlipVertical*/ ctx[14],
  34068. parentRect: /*imageCropRect*/ ctx[26],
  34069. toolSelectRadius: /*markupEditorToolSelectRadius*/ ctx[9],
  34070. willRenderPresetToolbar: /*decorateWillRenderShapePresetToolbar*/ ctx[17] || /*willRenderShapePresetToolbar*/ ctx[10],
  34071. hooks: {
  34072. willRenderShapeControls: /*willRenderShapeControls*/ ctx[20],
  34073. beforeAddShape: /*beforeAddShape*/ ctx[21],
  34074. beforeRemoveShape: /*beforeRemoveShape*/ ctx[22],
  34075. beforeDeselectShape: /*beforeDeselectShape*/ ctx[23],
  34076. beforeSelectShape: /*beforeSelectShape*/ ctx[24],
  34077. beforeUpdateShape: /*beforeUpdateShape*/ ctx[25]
  34078. }
  34079. };
  34080. if (/*decorateActiveTool*/ ctx[0] !== void 0) {
  34081. shapeutil_props.toolActive = /*decorateActiveTool*/ ctx[0];
  34082. }
  34083. shapeutil = new ShapeUtil({ props: shapeutil_props });
  34084. binding_callbacks.push(() => bind(shapeutil, "toolActive", shapeutil_toolActive_binding));
  34085. shapeutil.$on("measure", /*measure_handler*/ ctx[34]);
  34086. return {
  34087. c() {
  34088. create_component(shapeutil.$$.fragment);
  34089. },
  34090. m(target, anchor) {
  34091. mount_component(shapeutil, target, anchor);
  34092. current = true;
  34093. },
  34094. p(ctx, dirty) {
  34095. const shapeutil_changes = {};
  34096. if (dirty[0] & /*stores*/ 16) shapeutil_changes.stores = /*stores*/ ctx[4];
  34097. if (dirty[0] & /*locale*/ 32) shapeutil_changes.locale = /*locale*/ ctx[5];
  34098. if (dirty[0] & /*isActive*/ 2) shapeutil_changes.isActive = /*isActive*/ ctx[1];
  34099. if (dirty[0] & /*isActiveFraction*/ 4) shapeutil_changes.isActiveFraction = /*isActiveFraction*/ ctx[2];
  34100. if (dirty[0] & /*isVisible*/ 8) shapeutil_changes.isVisible = /*isVisible*/ ctx[3];
  34101. if (dirty[0] & /*decorateTools, markupEditorToolbar*/ 2112) shapeutil_changes.tools = /*decorateTools*/ ctx[11] || /*markupEditorToolbar*/ ctx[6];
  34102. if (dirty[0] & /*decorateToolShapes, markupEditorToolStyles*/ 4224) shapeutil_changes.toolShapes = /*decorateToolShapes*/ ctx[12] || /*markupEditorToolStyles*/ ctx[7];
  34103. if (dirty[0] & /*decorateShapeControls, markupEditorShapeStyleControls*/ 8448) shapeutil_changes.shapeControls = /*decorateShapeControls*/ ctx[13] || /*markupEditorShapeStyleControls*/ ctx[8];
  34104. if (dirty[0] & /*decoratePresets*/ 65536) shapeutil_changes.shapePresets = /*decoratePresets*/ ctx[16];
  34105. if (dirty[0] & /*enableSelectToolToAddShape*/ 262144) shapeutil_changes.enableSelectToolToAddShape = /*enableSelectToolToAddShape*/ ctx[18];
  34106. if (dirty[0] & /*enableTapToAddText*/ 524288) shapeutil_changes.enableTapToAddText = /*enableTapToAddText*/ ctx[19];
  34107. if (dirty[0] & /*decorateEnableSelectImagePreset*/ 32768) shapeutil_changes.enablePresetSelectImage = /*decorateEnableSelectImagePreset*/ ctx[15];
  34108. if (dirty[0] & /*decorateEnableButtonFlipVertical*/ 16384) shapeutil_changes.enableButtonFlipVertical = /*decorateEnableButtonFlipVertical*/ ctx[14];
  34109. if (dirty[0] & /*markupEditorToolSelectRadius*/ 512) shapeutil_changes.toolSelectRadius = /*markupEditorToolSelectRadius*/ ctx[9];
  34110. if (dirty[0] & /*decorateWillRenderShapePresetToolbar, willRenderShapePresetToolbar*/ 132096) shapeutil_changes.willRenderPresetToolbar = /*decorateWillRenderShapePresetToolbar*/ ctx[17] || /*willRenderShapePresetToolbar*/ ctx[10];
  34111. if (dirty[0] & /*willRenderShapeControls, beforeAddShape, beforeRemoveShape, beforeDeselectShape, beforeSelectShape, beforeUpdateShape*/ 66060288) shapeutil_changes.hooks = {
  34112. willRenderShapeControls: /*willRenderShapeControls*/ ctx[20],
  34113. beforeAddShape: /*beforeAddShape*/ ctx[21],
  34114. beforeRemoveShape: /*beforeRemoveShape*/ ctx[22],
  34115. beforeDeselectShape: /*beforeDeselectShape*/ ctx[23],
  34116. beforeSelectShape: /*beforeSelectShape*/ ctx[24],
  34117. beforeUpdateShape: /*beforeUpdateShape*/ ctx[25]
  34118. };
  34119. if (!updating_toolActive && dirty[0] & /*decorateActiveTool*/ 1) {
  34120. updating_toolActive = true;
  34121. shapeutil_changes.toolActive = /*decorateActiveTool*/ ctx[0];
  34122. add_flush_callback(() => updating_toolActive = false);
  34123. }
  34124. shapeutil.$set(shapeutil_changes);
  34125. },
  34126. i(local) {
  34127. if (current) return;
  34128. transition_in(shapeutil.$$.fragment, local);
  34129. current = true;
  34130. },
  34131. o(local) {
  34132. transition_out(shapeutil.$$.fragment, local);
  34133. current = false;
  34134. },
  34135. d(detaching) {
  34136. destroy_component(shapeutil, detaching);
  34137. }
  34138. };
  34139. }
  34140. function instance$7($$self, $$props, $$invalidate) {
  34141. let $imageSelectionRectPresentation;
  34142. let $presentationScalar;
  34143. const name = "decorate";
  34144. let { isActive } = $$props;
  34145. let { isActiveFraction } = $$props;
  34146. let { isVisible } = $$props;
  34147. let { stores } = $$props;
  34148. let { locale = {} } = $$props;
  34149. let { markupEditorToolbar = undefined } = $$props;
  34150. let { markupEditorToolStyles = undefined } = $$props;
  34151. let { markupEditorShapeStyleControls = undefined } = $$props;
  34152. let { markupEditorToolSelectRadius = undefined } = $$props;
  34153. let { willRenderShapePresetToolbar = undefined } = $$props;
  34154. let { decorateTools = undefined } = $$props;
  34155. let { decorateToolShapes = undefined } = $$props;
  34156. let { decorateShapeControls = undefined } = $$props;
  34157. let { decorateActiveTool = undefined } = $$props;
  34158. let { decorateEnableButtonFlipVertical = false } = $$props;
  34159. let { decorateEnableSelectImagePreset = false } = $$props;
  34160. let { decoratePresets = [] } = $$props;
  34161. let { decorateWillRenderShapePresetToolbar = undefined } = $$props;
  34162. let { enableSelectToolToAddShape = undefined } = $$props;
  34163. let { enableTapToAddText = undefined } = $$props;
  34164. let { willRenderShapeControls = undefined } = $$props;
  34165. let { beforeAddShape = undefined } = $$props;
  34166. let { beforeRemoveShape = undefined } = $$props;
  34167. let { beforeDeselectShape = undefined } = $$props;
  34168. let { beforeSelectShape = undefined } = $$props;
  34169. let { beforeUpdateShape = undefined } = $$props;
  34170. const { imageCropRect, imageDecoration, imageSelectionRectPresentation, presentationScalar } = stores;
  34171. component_subscribe($$self, imageSelectionRectPresentation, value => $$invalidate(35, $imageSelectionRectPresentation = value));
  34172. component_subscribe($$self, presentationScalar, value => $$invalidate(36, $presentationScalar = value));
  34173. const mapScreenPointToImagePoint = screenPoint => {
  34174. const mappedPoint = vectorClone(screenPoint);
  34175. mappedPoint.x -= $imageSelectionRectPresentation.x;
  34176. mappedPoint.y -= $imageSelectionRectPresentation.y;
  34177. mappedPoint.x /= $presentationScalar;
  34178. mappedPoint.y /= $presentationScalar;
  34179. return mappedPoint;
  34180. };
  34181. const mapImagePointToScreenPoint = imagePoint => {
  34182. const mappedPoint = vectorClone(imagePoint);
  34183. mappedPoint.x *= $presentationScalar;
  34184. mappedPoint.y *= $presentationScalar;
  34185. mappedPoint.x += $imageSelectionRectPresentation.x;
  34186. mappedPoint.y += $imageSelectionRectPresentation.y;
  34187. return mappedPoint;
  34188. };
  34189. function shapeutil_toolActive_binding(value) {
  34190. decorateActiveTool = value;
  34191. $$invalidate(0, decorateActiveTool);
  34192. }
  34193. function measure_handler(event) {
  34194. bubble($$self, event);
  34195. }
  34196. $$self.$$set = $$props => {
  34197. if ("isActive" in $$props) $$invalidate(1, isActive = $$props.isActive);
  34198. if ("isActiveFraction" in $$props) $$invalidate(2, isActiveFraction = $$props.isActiveFraction);
  34199. if ("isVisible" in $$props) $$invalidate(3, isVisible = $$props.isVisible);
  34200. if ("stores" in $$props) $$invalidate(4, stores = $$props.stores);
  34201. if ("locale" in $$props) $$invalidate(5, locale = $$props.locale);
  34202. if ("markupEditorToolbar" in $$props) $$invalidate(6, markupEditorToolbar = $$props.markupEditorToolbar);
  34203. if ("markupEditorToolStyles" in $$props) $$invalidate(7, markupEditorToolStyles = $$props.markupEditorToolStyles);
  34204. if ("markupEditorShapeStyleControls" in $$props) $$invalidate(8, markupEditorShapeStyleControls = $$props.markupEditorShapeStyleControls);
  34205. if ("markupEditorToolSelectRadius" in $$props) $$invalidate(9, markupEditorToolSelectRadius = $$props.markupEditorToolSelectRadius);
  34206. if ("willRenderShapePresetToolbar" in $$props) $$invalidate(10, willRenderShapePresetToolbar = $$props.willRenderShapePresetToolbar);
  34207. if ("decorateTools" in $$props) $$invalidate(11, decorateTools = $$props.decorateTools);
  34208. if ("decorateToolShapes" in $$props) $$invalidate(12, decorateToolShapes = $$props.decorateToolShapes);
  34209. if ("decorateShapeControls" in $$props) $$invalidate(13, decorateShapeControls = $$props.decorateShapeControls);
  34210. if ("decorateActiveTool" in $$props) $$invalidate(0, decorateActiveTool = $$props.decorateActiveTool);
  34211. if ("decorateEnableButtonFlipVertical" in $$props) $$invalidate(14, decorateEnableButtonFlipVertical = $$props.decorateEnableButtonFlipVertical);
  34212. if ("decorateEnableSelectImagePreset" in $$props) $$invalidate(15, decorateEnableSelectImagePreset = $$props.decorateEnableSelectImagePreset);
  34213. if ("decoratePresets" in $$props) $$invalidate(16, decoratePresets = $$props.decoratePresets);
  34214. if ("decorateWillRenderShapePresetToolbar" in $$props) $$invalidate(17, decorateWillRenderShapePresetToolbar = $$props.decorateWillRenderShapePresetToolbar);
  34215. if ("enableSelectToolToAddShape" in $$props) $$invalidate(18, enableSelectToolToAddShape = $$props.enableSelectToolToAddShape);
  34216. if ("enableTapToAddText" in $$props) $$invalidate(19, enableTapToAddText = $$props.enableTapToAddText);
  34217. if ("willRenderShapeControls" in $$props) $$invalidate(20, willRenderShapeControls = $$props.willRenderShapeControls);
  34218. if ("beforeAddShape" in $$props) $$invalidate(21, beforeAddShape = $$props.beforeAddShape);
  34219. if ("beforeRemoveShape" in $$props) $$invalidate(22, beforeRemoveShape = $$props.beforeRemoveShape);
  34220. if ("beforeDeselectShape" in $$props) $$invalidate(23, beforeDeselectShape = $$props.beforeDeselectShape);
  34221. if ("beforeSelectShape" in $$props) $$invalidate(24, beforeSelectShape = $$props.beforeSelectShape);
  34222. if ("beforeUpdateShape" in $$props) $$invalidate(25, beforeUpdateShape = $$props.beforeUpdateShape);
  34223. };
  34224. return [
  34225. decorateActiveTool,
  34226. isActive,
  34227. isActiveFraction,
  34228. isVisible,
  34229. stores,
  34230. locale,
  34231. markupEditorToolbar,
  34232. markupEditorToolStyles,
  34233. markupEditorShapeStyleControls,
  34234. markupEditorToolSelectRadius,
  34235. willRenderShapePresetToolbar,
  34236. decorateTools,
  34237. decorateToolShapes,
  34238. decorateShapeControls,
  34239. decorateEnableButtonFlipVertical,
  34240. decorateEnableSelectImagePreset,
  34241. decoratePresets,
  34242. decorateWillRenderShapePresetToolbar,
  34243. enableSelectToolToAddShape,
  34244. enableTapToAddText,
  34245. willRenderShapeControls,
  34246. beforeAddShape,
  34247. beforeRemoveShape,
  34248. beforeDeselectShape,
  34249. beforeSelectShape,
  34250. beforeUpdateShape,
  34251. imageCropRect,
  34252. imageDecoration,
  34253. imageSelectionRectPresentation,
  34254. presentationScalar,
  34255. mapScreenPointToImagePoint,
  34256. mapImagePointToScreenPoint,
  34257. name,
  34258. shapeutil_toolActive_binding,
  34259. measure_handler
  34260. ];
  34261. }
  34262. class Decorate extends SvelteComponent {
  34263. constructor(options) {
  34264. super();
  34265. init(
  34266. this,
  34267. options,
  34268. instance$7,
  34269. create_fragment$7,
  34270. safe_not_equal,
  34271. {
  34272. name: 32,
  34273. isActive: 1,
  34274. isActiveFraction: 2,
  34275. isVisible: 3,
  34276. stores: 4,
  34277. locale: 5,
  34278. markupEditorToolbar: 6,
  34279. markupEditorToolStyles: 7,
  34280. markupEditorShapeStyleControls: 8,
  34281. markupEditorToolSelectRadius: 9,
  34282. willRenderShapePresetToolbar: 10,
  34283. decorateTools: 11,
  34284. decorateToolShapes: 12,
  34285. decorateShapeControls: 13,
  34286. decorateActiveTool: 0,
  34287. decorateEnableButtonFlipVertical: 14,
  34288. decorateEnableSelectImagePreset: 15,
  34289. decoratePresets: 16,
  34290. decorateWillRenderShapePresetToolbar: 17,
  34291. enableSelectToolToAddShape: 18,
  34292. enableTapToAddText: 19,
  34293. willRenderShapeControls: 20,
  34294. beforeAddShape: 21,
  34295. beforeRemoveShape: 22,
  34296. beforeDeselectShape: 23,
  34297. beforeSelectShape: 24,
  34298. beforeUpdateShape: 25
  34299. },
  34300. [-1, -1]
  34301. );
  34302. }
  34303. get name() {
  34304. return this.$$.ctx[32];
  34305. }
  34306. get isActive() {
  34307. return this.$$.ctx[1];
  34308. }
  34309. set isActive(isActive) {
  34310. this.$set({ isActive });
  34311. flush();
  34312. }
  34313. get isActiveFraction() {
  34314. return this.$$.ctx[2];
  34315. }
  34316. set isActiveFraction(isActiveFraction) {
  34317. this.$set({ isActiveFraction });
  34318. flush();
  34319. }
  34320. get isVisible() {
  34321. return this.$$.ctx[3];
  34322. }
  34323. set isVisible(isVisible) {
  34324. this.$set({ isVisible });
  34325. flush();
  34326. }
  34327. get stores() {
  34328. return this.$$.ctx[4];
  34329. }
  34330. set stores(stores) {
  34331. this.$set({ stores });
  34332. flush();
  34333. }
  34334. get locale() {
  34335. return this.$$.ctx[5];
  34336. }
  34337. set locale(locale) {
  34338. this.$set({ locale });
  34339. flush();
  34340. }
  34341. get markupEditorToolbar() {
  34342. return this.$$.ctx[6];
  34343. }
  34344. set markupEditorToolbar(markupEditorToolbar) {
  34345. this.$set({ markupEditorToolbar });
  34346. flush();
  34347. }
  34348. get markupEditorToolStyles() {
  34349. return this.$$.ctx[7];
  34350. }
  34351. set markupEditorToolStyles(markupEditorToolStyles) {
  34352. this.$set({ markupEditorToolStyles });
  34353. flush();
  34354. }
  34355. get markupEditorShapeStyleControls() {
  34356. return this.$$.ctx[8];
  34357. }
  34358. set markupEditorShapeStyleControls(markupEditorShapeStyleControls) {
  34359. this.$set({ markupEditorShapeStyleControls });
  34360. flush();
  34361. }
  34362. get markupEditorToolSelectRadius() {
  34363. return this.$$.ctx[9];
  34364. }
  34365. set markupEditorToolSelectRadius(markupEditorToolSelectRadius) {
  34366. this.$set({ markupEditorToolSelectRadius });
  34367. flush();
  34368. }
  34369. get willRenderShapePresetToolbar() {
  34370. return this.$$.ctx[10];
  34371. }
  34372. set willRenderShapePresetToolbar(willRenderShapePresetToolbar) {
  34373. this.$set({ willRenderShapePresetToolbar });
  34374. flush();
  34375. }
  34376. get decorateTools() {
  34377. return this.$$.ctx[11];
  34378. }
  34379. set decorateTools(decorateTools) {
  34380. this.$set({ decorateTools });
  34381. flush();
  34382. }
  34383. get decorateToolShapes() {
  34384. return this.$$.ctx[12];
  34385. }
  34386. set decorateToolShapes(decorateToolShapes) {
  34387. this.$set({ decorateToolShapes });
  34388. flush();
  34389. }
  34390. get decorateShapeControls() {
  34391. return this.$$.ctx[13];
  34392. }
  34393. set decorateShapeControls(decorateShapeControls) {
  34394. this.$set({ decorateShapeControls });
  34395. flush();
  34396. }
  34397. get decorateActiveTool() {
  34398. return this.$$.ctx[0];
  34399. }
  34400. set decorateActiveTool(decorateActiveTool) {
  34401. this.$set({ decorateActiveTool });
  34402. flush();
  34403. }
  34404. get decorateEnableButtonFlipVertical() {
  34405. return this.$$.ctx[14];
  34406. }
  34407. set decorateEnableButtonFlipVertical(decorateEnableButtonFlipVertical) {
  34408. this.$set({ decorateEnableButtonFlipVertical });
  34409. flush();
  34410. }
  34411. get decorateEnableSelectImagePreset() {
  34412. return this.$$.ctx[15];
  34413. }
  34414. set decorateEnableSelectImagePreset(decorateEnableSelectImagePreset) {
  34415. this.$set({ decorateEnableSelectImagePreset });
  34416. flush();
  34417. }
  34418. get decoratePresets() {
  34419. return this.$$.ctx[16];
  34420. }
  34421. set decoratePresets(decoratePresets) {
  34422. this.$set({ decoratePresets });
  34423. flush();
  34424. }
  34425. get decorateWillRenderShapePresetToolbar() {
  34426. return this.$$.ctx[17];
  34427. }
  34428. set decorateWillRenderShapePresetToolbar(decorateWillRenderShapePresetToolbar) {
  34429. this.$set({ decorateWillRenderShapePresetToolbar });
  34430. flush();
  34431. }
  34432. get enableSelectToolToAddShape() {
  34433. return this.$$.ctx[18];
  34434. }
  34435. set enableSelectToolToAddShape(enableSelectToolToAddShape) {
  34436. this.$set({ enableSelectToolToAddShape });
  34437. flush();
  34438. }
  34439. get enableTapToAddText() {
  34440. return this.$$.ctx[19];
  34441. }
  34442. set enableTapToAddText(enableTapToAddText) {
  34443. this.$set({ enableTapToAddText });
  34444. flush();
  34445. }
  34446. get willRenderShapeControls() {
  34447. return this.$$.ctx[20];
  34448. }
  34449. set willRenderShapeControls(willRenderShapeControls) {
  34450. this.$set({ willRenderShapeControls });
  34451. flush();
  34452. }
  34453. get beforeAddShape() {
  34454. return this.$$.ctx[21];
  34455. }
  34456. set beforeAddShape(beforeAddShape) {
  34457. this.$set({ beforeAddShape });
  34458. flush();
  34459. }
  34460. get beforeRemoveShape() {
  34461. return this.$$.ctx[22];
  34462. }
  34463. set beforeRemoveShape(beforeRemoveShape) {
  34464. this.$set({ beforeRemoveShape });
  34465. flush();
  34466. }
  34467. get beforeDeselectShape() {
  34468. return this.$$.ctx[23];
  34469. }
  34470. set beforeDeselectShape(beforeDeselectShape) {
  34471. this.$set({ beforeDeselectShape });
  34472. flush();
  34473. }
  34474. get beforeSelectShape() {
  34475. return this.$$.ctx[24];
  34476. }
  34477. set beforeSelectShape(beforeSelectShape) {
  34478. this.$set({ beforeSelectShape });
  34479. flush();
  34480. }
  34481. get beforeUpdateShape() {
  34482. return this.$$.ctx[25];
  34483. }
  34484. set beforeUpdateShape(beforeUpdateShape) {
  34485. this.$set({ beforeUpdateShape });
  34486. flush();
  34487. }
  34488. }
  34489. // @ts-ignore
  34490. var _plugin_decorate = { util: ['decorate', Decorate] };
  34491. /* src/core/ui/plugins/sticker/index.svelte generated by Svelte v3.37.0 */
  34492. function create_fragment$6(ctx) {
  34493. let shapeutil;
  34494. let current;
  34495. shapeutil = new ShapeUtil({
  34496. props: {
  34497. stores: /*stores*/ ctx[3],
  34498. locale: /*locale*/ ctx[4],
  34499. isActive: /*isActive*/ ctx[0],
  34500. isActiveFraction: /*isActiveFraction*/ ctx[1],
  34501. isVisible: /*isVisible*/ ctx[2],
  34502. mapScreenPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[32],
  34503. mapImagePointToScreenPoint: /*mapImagePointToScreenPoint*/ ctx[33],
  34504. utilKey: "sticker",
  34505. shapePresets: /*stickers*/ ctx[5],
  34506. shapes: /*stickerStickToImage*/ ctx[6]
  34507. ? /*imageAnnotation*/ ctx[25]
  34508. : /*imageDecoration*/ ctx[26],
  34509. toolActive: "preset",
  34510. imageFlipX: /*stickerStickToImage*/ ctx[6]
  34511. ? /*$imageFlipX*/ ctx[18]
  34512. : false,
  34513. imageFlipY: /*stickerStickToImage*/ ctx[6]
  34514. ? /*$imageFlipY*/ ctx[19]
  34515. : false,
  34516. imageRotation: /*stickerStickToImage*/ ctx[6]
  34517. ? /*$imageRotation*/ ctx[20]
  34518. : 0,
  34519. parentRect: /*stickerStickToImage*/ ctx[6]
  34520. ? /*imageSize*/ ctx[27]
  34521. : /*imageCropRect*/ ctx[23],
  34522. enablePresetSelectImage: /*stickerEnableSelectImage*/ ctx[7],
  34523. enableButtonFlipVertical: /*stickersEnableButtonFlipVertical*/ ctx[8],
  34524. toolSelectRadius: /*markupEditorToolSelectRadius*/ ctx[11],
  34525. willRenderPresetToolbar: /*stickersWillRenderShapePresetToolbar*/ ctx[9] || /*willRenderShapePresetToolbar*/ ctx[12],
  34526. hooks: {
  34527. willRenderShapeControls: /*willRenderShapeControls*/ ctx[10],
  34528. beforeAddShape: /*beforeAddShape*/ ctx[13],
  34529. beforeRemoveShape: /*beforeRemoveShape*/ ctx[14],
  34530. beforeDeselectShape: /*beforeDeselectShape*/ ctx[15],
  34531. beforeSelectShape: /*beforeSelectShape*/ ctx[16],
  34532. beforeUpdateShape: /*beforeUpdateShape*/ ctx[17]
  34533. }
  34534. }
  34535. });
  34536. shapeutil.$on("measure", /*measure_handler*/ ctx[35]);
  34537. return {
  34538. c() {
  34539. create_component(shapeutil.$$.fragment);
  34540. },
  34541. m(target, anchor) {
  34542. mount_component(shapeutil, target, anchor);
  34543. current = true;
  34544. },
  34545. p(ctx, dirty) {
  34546. const shapeutil_changes = {};
  34547. if (dirty[0] & /*stores*/ 8) shapeutil_changes.stores = /*stores*/ ctx[3];
  34548. if (dirty[0] & /*locale*/ 16) shapeutil_changes.locale = /*locale*/ ctx[4];
  34549. if (dirty[0] & /*isActive*/ 1) shapeutil_changes.isActive = /*isActive*/ ctx[0];
  34550. if (dirty[0] & /*isActiveFraction*/ 2) shapeutil_changes.isActiveFraction = /*isActiveFraction*/ ctx[1];
  34551. if (dirty[0] & /*isVisible*/ 4) shapeutil_changes.isVisible = /*isVisible*/ ctx[2];
  34552. if (dirty[0] & /*stickers*/ 32) shapeutil_changes.shapePresets = /*stickers*/ ctx[5];
  34553. if (dirty[0] & /*stickerStickToImage*/ 64) shapeutil_changes.shapes = /*stickerStickToImage*/ ctx[6]
  34554. ? /*imageAnnotation*/ ctx[25]
  34555. : /*imageDecoration*/ ctx[26];
  34556. if (dirty[0] & /*stickerStickToImage, $imageFlipX*/ 262208) shapeutil_changes.imageFlipX = /*stickerStickToImage*/ ctx[6]
  34557. ? /*$imageFlipX*/ ctx[18]
  34558. : false;
  34559. if (dirty[0] & /*stickerStickToImage, $imageFlipY*/ 524352) shapeutil_changes.imageFlipY = /*stickerStickToImage*/ ctx[6]
  34560. ? /*$imageFlipY*/ ctx[19]
  34561. : false;
  34562. if (dirty[0] & /*stickerStickToImage, $imageRotation*/ 1048640) shapeutil_changes.imageRotation = /*stickerStickToImage*/ ctx[6]
  34563. ? /*$imageRotation*/ ctx[20]
  34564. : 0;
  34565. if (dirty[0] & /*stickerStickToImage*/ 64) shapeutil_changes.parentRect = /*stickerStickToImage*/ ctx[6]
  34566. ? /*imageSize*/ ctx[27]
  34567. : /*imageCropRect*/ ctx[23];
  34568. if (dirty[0] & /*stickerEnableSelectImage*/ 128) shapeutil_changes.enablePresetSelectImage = /*stickerEnableSelectImage*/ ctx[7];
  34569. if (dirty[0] & /*stickersEnableButtonFlipVertical*/ 256) shapeutil_changes.enableButtonFlipVertical = /*stickersEnableButtonFlipVertical*/ ctx[8];
  34570. if (dirty[0] & /*markupEditorToolSelectRadius*/ 2048) shapeutil_changes.toolSelectRadius = /*markupEditorToolSelectRadius*/ ctx[11];
  34571. if (dirty[0] & /*stickersWillRenderShapePresetToolbar, willRenderShapePresetToolbar*/ 4608) shapeutil_changes.willRenderPresetToolbar = /*stickersWillRenderShapePresetToolbar*/ ctx[9] || /*willRenderShapePresetToolbar*/ ctx[12];
  34572. if (dirty[0] & /*willRenderShapeControls, beforeAddShape, beforeRemoveShape, beforeDeselectShape, beforeSelectShape, beforeUpdateShape*/ 254976) shapeutil_changes.hooks = {
  34573. willRenderShapeControls: /*willRenderShapeControls*/ ctx[10],
  34574. beforeAddShape: /*beforeAddShape*/ ctx[13],
  34575. beforeRemoveShape: /*beforeRemoveShape*/ ctx[14],
  34576. beforeDeselectShape: /*beforeDeselectShape*/ ctx[15],
  34577. beforeSelectShape: /*beforeSelectShape*/ ctx[16],
  34578. beforeUpdateShape: /*beforeUpdateShape*/ ctx[17]
  34579. };
  34580. shapeutil.$set(shapeutil_changes);
  34581. },
  34582. i(local) {
  34583. if (current) return;
  34584. transition_in(shapeutil.$$.fragment, local);
  34585. current = true;
  34586. },
  34587. o(local) {
  34588. transition_out(shapeutil.$$.fragment, local);
  34589. current = false;
  34590. },
  34591. d(detaching) {
  34592. destroy_component(shapeutil, detaching);
  34593. }
  34594. };
  34595. }
  34596. function instance$6($$self, $$props, $$invalidate) {
  34597. let $rootRect;
  34598. let $imageSize;
  34599. let $imageTransforms;
  34600. let $imageFlipX;
  34601. let $imageFlipY;
  34602. let $imageSelectionRectPresentation;
  34603. let $presentationScalar;
  34604. let $imageRotation;
  34605. const name = "sticker";
  34606. let { isActive } = $$props;
  34607. let { isActiveFraction } = $$props;
  34608. let { isVisible } = $$props;
  34609. let { stores } = $$props;
  34610. let { locale = {} } = $$props;
  34611. let { stickers = [] } = $$props;
  34612. let { stickerStickToImage = false } = $$props;
  34613. let { stickerEnableSelectImage = true } = $$props;
  34614. let { stickersEnableButtonFlipVertical = false } = $$props;
  34615. let { stickersWillRenderShapePresetToolbar = undefined } = $$props;
  34616. let { willRenderShapeControls = undefined } = $$props;
  34617. let { markupEditorToolSelectRadius = undefined } = $$props;
  34618. let { willRenderShapePresetToolbar = undefined } = $$props;
  34619. let { beforeAddShape = undefined } = $$props;
  34620. let { beforeRemoveShape = undefined } = $$props;
  34621. let { beforeDeselectShape = undefined } = $$props;
  34622. let { beforeSelectShape = undefined } = $$props;
  34623. let { beforeUpdateShape = undefined } = $$props;
  34624. // connect filter choice to stores
  34625. const { presentationScalar, rootRect, imageCropRect, imageSelectionRectPresentation, imageAnnotation, imageDecoration, imageSize, imageTransforms, imageRotation, imageFlipX, imageFlipY } = stores;
  34626. component_subscribe($$self, presentationScalar, value => $$invalidate(40, $presentationScalar = value));
  34627. component_subscribe($$self, rootRect, value => $$invalidate(36, $rootRect = value));
  34628. component_subscribe($$self, imageSelectionRectPresentation, value => $$invalidate(39, $imageSelectionRectPresentation = value));
  34629. component_subscribe($$self, imageSize, value => $$invalidate(37, $imageSize = value));
  34630. component_subscribe($$self, imageTransforms, value => $$invalidate(38, $imageTransforms = value));
  34631. component_subscribe($$self, imageRotation, value => $$invalidate(20, $imageRotation = value));
  34632. component_subscribe($$self, imageFlipX, value => $$invalidate(18, $imageFlipX = value));
  34633. component_subscribe($$self, imageFlipY, value => $$invalidate(19, $imageFlipY = value));
  34634. //
  34635. // Mapping coordinates
  34636. //
  34637. const mapScreenPointToImagePoint = stickerStickToImage
  34638. ? point => _mapScreenPointToImagePoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY)
  34639. : point => {
  34640. const mappedPoint = vectorClone(point);
  34641. mappedPoint.x -= $imageSelectionRectPresentation.x;
  34642. mappedPoint.y -= $imageSelectionRectPresentation.y;
  34643. mappedPoint.x /= $presentationScalar;
  34644. mappedPoint.y /= $presentationScalar;
  34645. return mappedPoint;
  34646. };
  34647. const mapImagePointToScreenPoint = stickerStickToImage
  34648. ? point => _mapImagePointToScreenPoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY)
  34649. : point => {
  34650. const mappedPoint = vectorClone(point);
  34651. mappedPoint.x *= $presentationScalar;
  34652. mappedPoint.y *= $presentationScalar;
  34653. mappedPoint.x += $imageSelectionRectPresentation.x;
  34654. mappedPoint.y += $imageSelectionRectPresentation.y;
  34655. return mappedPoint;
  34656. };
  34657. function measure_handler(event) {
  34658. bubble($$self, event);
  34659. }
  34660. $$self.$$set = $$props => {
  34661. if ("isActive" in $$props) $$invalidate(0, isActive = $$props.isActive);
  34662. if ("isActiveFraction" in $$props) $$invalidate(1, isActiveFraction = $$props.isActiveFraction);
  34663. if ("isVisible" in $$props) $$invalidate(2, isVisible = $$props.isVisible);
  34664. if ("stores" in $$props) $$invalidate(3, stores = $$props.stores);
  34665. if ("locale" in $$props) $$invalidate(4, locale = $$props.locale);
  34666. if ("stickers" in $$props) $$invalidate(5, stickers = $$props.stickers);
  34667. if ("stickerStickToImage" in $$props) $$invalidate(6, stickerStickToImage = $$props.stickerStickToImage);
  34668. if ("stickerEnableSelectImage" in $$props) $$invalidate(7, stickerEnableSelectImage = $$props.stickerEnableSelectImage);
  34669. if ("stickersEnableButtonFlipVertical" in $$props) $$invalidate(8, stickersEnableButtonFlipVertical = $$props.stickersEnableButtonFlipVertical);
  34670. if ("stickersWillRenderShapePresetToolbar" in $$props) $$invalidate(9, stickersWillRenderShapePresetToolbar = $$props.stickersWillRenderShapePresetToolbar);
  34671. if ("willRenderShapeControls" in $$props) $$invalidate(10, willRenderShapeControls = $$props.willRenderShapeControls);
  34672. if ("markupEditorToolSelectRadius" in $$props) $$invalidate(11, markupEditorToolSelectRadius = $$props.markupEditorToolSelectRadius);
  34673. if ("willRenderShapePresetToolbar" in $$props) $$invalidate(12, willRenderShapePresetToolbar = $$props.willRenderShapePresetToolbar);
  34674. if ("beforeAddShape" in $$props) $$invalidate(13, beforeAddShape = $$props.beforeAddShape);
  34675. if ("beforeRemoveShape" in $$props) $$invalidate(14, beforeRemoveShape = $$props.beforeRemoveShape);
  34676. if ("beforeDeselectShape" in $$props) $$invalidate(15, beforeDeselectShape = $$props.beforeDeselectShape);
  34677. if ("beforeSelectShape" in $$props) $$invalidate(16, beforeSelectShape = $$props.beforeSelectShape);
  34678. if ("beforeUpdateShape" in $$props) $$invalidate(17, beforeUpdateShape = $$props.beforeUpdateShape);
  34679. };
  34680. return [
  34681. isActive,
  34682. isActiveFraction,
  34683. isVisible,
  34684. stores,
  34685. locale,
  34686. stickers,
  34687. stickerStickToImage,
  34688. stickerEnableSelectImage,
  34689. stickersEnableButtonFlipVertical,
  34690. stickersWillRenderShapePresetToolbar,
  34691. willRenderShapeControls,
  34692. markupEditorToolSelectRadius,
  34693. willRenderShapePresetToolbar,
  34694. beforeAddShape,
  34695. beforeRemoveShape,
  34696. beforeDeselectShape,
  34697. beforeSelectShape,
  34698. beforeUpdateShape,
  34699. $imageFlipX,
  34700. $imageFlipY,
  34701. $imageRotation,
  34702. presentationScalar,
  34703. rootRect,
  34704. imageCropRect,
  34705. imageSelectionRectPresentation,
  34706. imageAnnotation,
  34707. imageDecoration,
  34708. imageSize,
  34709. imageTransforms,
  34710. imageRotation,
  34711. imageFlipX,
  34712. imageFlipY,
  34713. mapScreenPointToImagePoint,
  34714. mapImagePointToScreenPoint,
  34715. name,
  34716. measure_handler
  34717. ];
  34718. }
  34719. class Sticker extends SvelteComponent {
  34720. constructor(options) {
  34721. super();
  34722. init(
  34723. this,
  34724. options,
  34725. instance$6,
  34726. create_fragment$6,
  34727. safe_not_equal,
  34728. {
  34729. name: 34,
  34730. isActive: 0,
  34731. isActiveFraction: 1,
  34732. isVisible: 2,
  34733. stores: 3,
  34734. locale: 4,
  34735. stickers: 5,
  34736. stickerStickToImage: 6,
  34737. stickerEnableSelectImage: 7,
  34738. stickersEnableButtonFlipVertical: 8,
  34739. stickersWillRenderShapePresetToolbar: 9,
  34740. willRenderShapeControls: 10,
  34741. markupEditorToolSelectRadius: 11,
  34742. willRenderShapePresetToolbar: 12,
  34743. beforeAddShape: 13,
  34744. beforeRemoveShape: 14,
  34745. beforeDeselectShape: 15,
  34746. beforeSelectShape: 16,
  34747. beforeUpdateShape: 17
  34748. },
  34749. [-1, -1]
  34750. );
  34751. }
  34752. get name() {
  34753. return this.$$.ctx[34];
  34754. }
  34755. get isActive() {
  34756. return this.$$.ctx[0];
  34757. }
  34758. set isActive(isActive) {
  34759. this.$set({ isActive });
  34760. flush();
  34761. }
  34762. get isActiveFraction() {
  34763. return this.$$.ctx[1];
  34764. }
  34765. set isActiveFraction(isActiveFraction) {
  34766. this.$set({ isActiveFraction });
  34767. flush();
  34768. }
  34769. get isVisible() {
  34770. return this.$$.ctx[2];
  34771. }
  34772. set isVisible(isVisible) {
  34773. this.$set({ isVisible });
  34774. flush();
  34775. }
  34776. get stores() {
  34777. return this.$$.ctx[3];
  34778. }
  34779. set stores(stores) {
  34780. this.$set({ stores });
  34781. flush();
  34782. }
  34783. get locale() {
  34784. return this.$$.ctx[4];
  34785. }
  34786. set locale(locale) {
  34787. this.$set({ locale });
  34788. flush();
  34789. }
  34790. get stickers() {
  34791. return this.$$.ctx[5];
  34792. }
  34793. set stickers(stickers) {
  34794. this.$set({ stickers });
  34795. flush();
  34796. }
  34797. get stickerStickToImage() {
  34798. return this.$$.ctx[6];
  34799. }
  34800. set stickerStickToImage(stickerStickToImage) {
  34801. this.$set({ stickerStickToImage });
  34802. flush();
  34803. }
  34804. get stickerEnableSelectImage() {
  34805. return this.$$.ctx[7];
  34806. }
  34807. set stickerEnableSelectImage(stickerEnableSelectImage) {
  34808. this.$set({ stickerEnableSelectImage });
  34809. flush();
  34810. }
  34811. get stickersEnableButtonFlipVertical() {
  34812. return this.$$.ctx[8];
  34813. }
  34814. set stickersEnableButtonFlipVertical(stickersEnableButtonFlipVertical) {
  34815. this.$set({ stickersEnableButtonFlipVertical });
  34816. flush();
  34817. }
  34818. get stickersWillRenderShapePresetToolbar() {
  34819. return this.$$.ctx[9];
  34820. }
  34821. set stickersWillRenderShapePresetToolbar(stickersWillRenderShapePresetToolbar) {
  34822. this.$set({ stickersWillRenderShapePresetToolbar });
  34823. flush();
  34824. }
  34825. get willRenderShapeControls() {
  34826. return this.$$.ctx[10];
  34827. }
  34828. set willRenderShapeControls(willRenderShapeControls) {
  34829. this.$set({ willRenderShapeControls });
  34830. flush();
  34831. }
  34832. get markupEditorToolSelectRadius() {
  34833. return this.$$.ctx[11];
  34834. }
  34835. set markupEditorToolSelectRadius(markupEditorToolSelectRadius) {
  34836. this.$set({ markupEditorToolSelectRadius });
  34837. flush();
  34838. }
  34839. get willRenderShapePresetToolbar() {
  34840. return this.$$.ctx[12];
  34841. }
  34842. set willRenderShapePresetToolbar(willRenderShapePresetToolbar) {
  34843. this.$set({ willRenderShapePresetToolbar });
  34844. flush();
  34845. }
  34846. get beforeAddShape() {
  34847. return this.$$.ctx[13];
  34848. }
  34849. set beforeAddShape(beforeAddShape) {
  34850. this.$set({ beforeAddShape });
  34851. flush();
  34852. }
  34853. get beforeRemoveShape() {
  34854. return this.$$.ctx[14];
  34855. }
  34856. set beforeRemoveShape(beforeRemoveShape) {
  34857. this.$set({ beforeRemoveShape });
  34858. flush();
  34859. }
  34860. get beforeDeselectShape() {
  34861. return this.$$.ctx[15];
  34862. }
  34863. set beforeDeselectShape(beforeDeselectShape) {
  34864. this.$set({ beforeDeselectShape });
  34865. flush();
  34866. }
  34867. get beforeSelectShape() {
  34868. return this.$$.ctx[16];
  34869. }
  34870. set beforeSelectShape(beforeSelectShape) {
  34871. this.$set({ beforeSelectShape });
  34872. flush();
  34873. }
  34874. get beforeUpdateShape() {
  34875. return this.$$.ctx[17];
  34876. }
  34877. set beforeUpdateShape(beforeUpdateShape) {
  34878. this.$set({ beforeUpdateShape });
  34879. flush();
  34880. }
  34881. }
  34882. // @ts-ignore
  34883. var _plugin_sticker = { util: ['sticker', Sticker] };
  34884. /* src/core/ui/plugins/frame/index.svelte generated by Svelte v3.37.0 */
  34885. function create_option_slot(ctx) {
  34886. let div;
  34887. let html_tag;
  34888. let raw_value = (/*getOptionThumb*/ ctx[13](/*option*/ ctx[27].value) || "") + "";
  34889. let t0;
  34890. let span;
  34891. let t1_value = (isFunction(/*option*/ ctx[27].label)
  34892. ? /*option*/ ctx[27].label(/*locale*/ ctx[1])
  34893. : /*option*/ ctx[27].label) + "";
  34894. let t1;
  34895. return {
  34896. c() {
  34897. div = element("div");
  34898. t0 = space();
  34899. span = element("span");
  34900. t1 = text(t1_value);
  34901. html_tag = new HtmlTag(t0);
  34902. attr(div, "slot", "option");
  34903. },
  34904. m(target, anchor) {
  34905. insert(target, div, anchor);
  34906. html_tag.m(raw_value, div);
  34907. append(div, t0);
  34908. append(div, span);
  34909. append(span, t1);
  34910. },
  34911. p(ctx, dirty) {
  34912. if (dirty & /*option*/ 134217728 && raw_value !== (raw_value = (/*getOptionThumb*/ ctx[13](/*option*/ ctx[27].value) || "") + "")) html_tag.p(raw_value);
  34913. if (dirty & /*option, locale*/ 134217730 && t1_value !== (t1_value = (isFunction(/*option*/ ctx[27].label)
  34914. ? /*option*/ ctx[27].label(/*locale*/ ctx[1])
  34915. : /*option*/ ctx[27].label) + "")) set_data(t1, t1_value);
  34916. },
  34917. d(detaching) {
  34918. if (detaching) detach(div);
  34919. }
  34920. };
  34921. }
  34922. // (125:8) <Scrollable elasticity={scrollElasticity}>
  34923. function create_default_slot$2(ctx) {
  34924. let radiogroup;
  34925. let current;
  34926. radiogroup = new RadioGroup({
  34927. props: {
  34928. locale: /*locale*/ ctx[1],
  34929. layout: "row",
  34930. options: /*frameOptions*/ ctx[2],
  34931. selectedIndex: /*selectedFrameIndex*/ ctx[10],
  34932. onchange: /*handleChangeFrame*/ ctx[11],
  34933. $$slots: {
  34934. option: [
  34935. create_option_slot,
  34936. ({ option }) => ({ 27: option }),
  34937. ({ option }) => option ? 134217728 : 0
  34938. ]
  34939. },
  34940. $$scope: { ctx }
  34941. }
  34942. });
  34943. return {
  34944. c() {
  34945. create_component(radiogroup.$$.fragment);
  34946. },
  34947. m(target, anchor) {
  34948. mount_component(radiogroup, target, anchor);
  34949. current = true;
  34950. },
  34951. p(ctx, dirty) {
  34952. const radiogroup_changes = {};
  34953. if (dirty & /*locale*/ 2) radiogroup_changes.locale = /*locale*/ ctx[1];
  34954. if (dirty & /*frameOptions*/ 4) radiogroup_changes.options = /*frameOptions*/ ctx[2];
  34955. if (dirty & /*$$scope, option, locale*/ 402653186) {
  34956. radiogroup_changes.$$scope = { dirty, ctx };
  34957. }
  34958. radiogroup.$set(radiogroup_changes);
  34959. },
  34960. i(local) {
  34961. if (current) return;
  34962. transition_in(radiogroup.$$.fragment, local);
  34963. current = true;
  34964. },
  34965. o(local) {
  34966. transition_out(radiogroup.$$.fragment, local);
  34967. current = false;
  34968. },
  34969. d(detaching) {
  34970. destroy_component(radiogroup, detaching);
  34971. }
  34972. };
  34973. }
  34974. // (116:4)
  34975. function create_footer_slot$1(ctx) {
  34976. let div;
  34977. let shapestyleeditor;
  34978. let t;
  34979. let scrollable;
  34980. let current;
  34981. shapestyleeditor = new ShapeStyleEditor({
  34982. props: {
  34983. locale: /*locale*/ ctx[1],
  34984. shape: /*$imageFrame*/ ctx[5],
  34985. onchange: /*handleUpdateSelectedFrameShape*/ ctx[12],
  34986. controls: /*markupEditorShapeStyleControls*/ ctx[3],
  34987. scrollElasticity: /*computedScrollElasticity*/ ctx[4]
  34988. }
  34989. });
  34990. scrollable = new Scrollable({
  34991. props: {
  34992. elasticity: /*scrollElasticity*/ ctx[8],
  34993. $$slots: { default: [create_default_slot$2] },
  34994. $$scope: { ctx }
  34995. }
  34996. });
  34997. return {
  34998. c() {
  34999. div = element("div");
  35000. create_component(shapestyleeditor.$$.fragment);
  35001. t = space();
  35002. create_component(scrollable.$$.fragment);
  35003. attr(div, "slot", "footer");
  35004. attr(div, "style", /*footerStyle*/ ctx[6]);
  35005. },
  35006. m(target, anchor) {
  35007. insert(target, div, anchor);
  35008. mount_component(shapestyleeditor, div, null);
  35009. append(div, t);
  35010. mount_component(scrollable, div, null);
  35011. current = true;
  35012. },
  35013. p(ctx, dirty) {
  35014. const shapestyleeditor_changes = {};
  35015. if (dirty & /*locale*/ 2) shapestyleeditor_changes.locale = /*locale*/ ctx[1];
  35016. if (dirty & /*$imageFrame*/ 32) shapestyleeditor_changes.shape = /*$imageFrame*/ ctx[5];
  35017. if (dirty & /*markupEditorShapeStyleControls*/ 8) shapestyleeditor_changes.controls = /*markupEditorShapeStyleControls*/ ctx[3];
  35018. if (dirty & /*computedScrollElasticity*/ 16) shapestyleeditor_changes.scrollElasticity = /*computedScrollElasticity*/ ctx[4];
  35019. shapestyleeditor.$set(shapestyleeditor_changes);
  35020. const scrollable_changes = {};
  35021. if (dirty & /*$$scope, locale, frameOptions*/ 268435462) {
  35022. scrollable_changes.$$scope = { dirty, ctx };
  35023. }
  35024. scrollable.$set(scrollable_changes);
  35025. if (!current || dirty & /*footerStyle*/ 64) {
  35026. attr(div, "style", /*footerStyle*/ ctx[6]);
  35027. }
  35028. },
  35029. i(local) {
  35030. if (current) return;
  35031. transition_in(shapestyleeditor.$$.fragment, local);
  35032. transition_in(scrollable.$$.fragment, local);
  35033. current = true;
  35034. },
  35035. o(local) {
  35036. transition_out(shapestyleeditor.$$.fragment, local);
  35037. transition_out(scrollable.$$.fragment, local);
  35038. current = false;
  35039. },
  35040. d(detaching) {
  35041. if (detaching) detach(div);
  35042. destroy_component(shapestyleeditor);
  35043. destroy_component(scrollable);
  35044. }
  35045. };
  35046. }
  35047. function create_fragment$5(ctx) {
  35048. let util;
  35049. let current;
  35050. util = new Util({
  35051. props: {
  35052. $$slots: { footer: [create_footer_slot$1] },
  35053. $$scope: { ctx }
  35054. }
  35055. });
  35056. util.$on("measure", /*measure_handler*/ ctx[21]);
  35057. return {
  35058. c() {
  35059. create_component(util.$$.fragment);
  35060. },
  35061. m(target, anchor) {
  35062. mount_component(util, target, anchor);
  35063. current = true;
  35064. },
  35065. p(ctx, [dirty]) {
  35066. const util_changes = {};
  35067. if (dirty & /*$$scope, footerStyle, locale, frameOptions, $imageFrame, markupEditorShapeStyleControls, computedScrollElasticity*/ 268435582) {
  35068. util_changes.$$scope = { dirty, ctx };
  35069. }
  35070. util.$set(util_changes);
  35071. },
  35072. i(local) {
  35073. if (current) return;
  35074. transition_in(util.$$.fragment, local);
  35075. current = true;
  35076. },
  35077. o(local) {
  35078. transition_out(util.$$.fragment, local);
  35079. current = false;
  35080. },
  35081. d(detaching) {
  35082. destroy_component(util, detaching);
  35083. }
  35084. };
  35085. }
  35086. function instance$5($$self, $$props, $$invalidate) {
  35087. let computedScrollElasticity;
  35088. let footerStyle;
  35089. let $imageFrame;
  35090. let $animation;
  35091. let $isActive,
  35092. $$unsubscribe_isActive = noop,
  35093. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(19, $isActive = $$value)), isActive);
  35094. let $footerOffset;
  35095. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  35096. const name = "frame";
  35097. let { isActive } = $$props;
  35098. $$subscribe_isActive();
  35099. let { stores } = $$props;
  35100. let { locale = {} } = $$props;
  35101. let { frameStyles = {} } = $$props;
  35102. let { frameOptions = [] } = $$props;
  35103. let { markupEditorShapeStyleControls = undefined } = $$props;
  35104. // connect filter choice to stores
  35105. const { animation, elasticityMultiplier, scrollElasticity, imageFrame } = stores;
  35106. component_subscribe($$self, animation, value => $$invalidate(18, $animation = value));
  35107. component_subscribe($$self, imageFrame, value => $$invalidate(5, $imageFrame = value));
  35108. // current index in frame list
  35109. let selectedFrameIndex = $imageFrame
  35110. ? frameOptions.findIndex(([id]) => id === $imageFrame.id)
  35111. : 0;
  35112. // default frame styles
  35113. let frameActiveStyles = { frameColor: [1, 1, 1] };
  35114. const handleChangeFrame = ({ value }) => {
  35115. // get new frame
  35116. const frameBase = frameStyles[value];
  35117. // no new frame selected
  35118. if (!frameBase || !frameBase.shape) {
  35119. imageFrame.set(undefined);
  35120. return;
  35121. }
  35122. // create new base frame
  35123. const frame = {
  35124. id: value,
  35125. // set base styles
  35126. ...frameActiveStyles,
  35127. // copy the frame base, it's possible that this frame has a different layout
  35128. ...shapeDeepCopy(frameBase.shape)
  35129. };
  35130. imageFrame.set(frame);
  35131. };
  35132. function handleUpdateSelectedFrameShape(props) {
  35133. // remember color style for when creating or styling other element
  35134. if (hasProp(props, "frameColor")) frameActiveStyles.frameColor = props.frameColor;
  35135. // it's possible we're only updating default styles
  35136. if (!$imageFrame) return;
  35137. // frameSelected
  35138. shapeUpdateProps($imageFrame, props);
  35139. // update shape so ui shape controls are updated
  35140. imageFrame.set($imageFrame);
  35141. }
  35142. const isIncompleteSVGMarkup = str => (/rect|path|circle|line|<g>/i).test(str);
  35143. const isHTML = str => (/div/i).test(str);
  35144. const getThumb = value => {
  35145. if (isHTML(value)) return value;
  35146. // could be full svg
  35147. if (isSVGMarkup(value)) return value;
  35148. // could be a partial svg in which case we turn it into a full svg
  35149. if (isIncompleteSVGMarkup(value)) return `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" stroke-width="1" stroke="currentColor" fill="none" aria-hidden="true" focusable="false" stroke-linecap="round" stroke-linejoin="round">${value}</svg>`;
  35150. // if not, must be URL
  35151. return `<img src="${value}" alt=""/>`;
  35152. };
  35153. const getOptionThumb = key => {
  35154. const frameStyle = frameStyles[key];
  35155. if (!frameStyle || !frameStyle.thumb) return;
  35156. return getThumb(frameStyle.thumb);
  35157. };
  35158. //
  35159. // Footer style
  35160. //
  35161. const footerOffset = spring($animation ? 20 : 0);
  35162. component_subscribe($$self, footerOffset, value => $$invalidate(20, $footerOffset = value));
  35163. function measure_handler(event) {
  35164. bubble($$self, event);
  35165. }
  35166. $$self.$$set = $$props => {
  35167. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(0, isActive = $$props.isActive));
  35168. if ("stores" in $$props) $$invalidate(16, stores = $$props.stores);
  35169. if ("locale" in $$props) $$invalidate(1, locale = $$props.locale);
  35170. if ("frameStyles" in $$props) $$invalidate(17, frameStyles = $$props.frameStyles);
  35171. if ("frameOptions" in $$props) $$invalidate(2, frameOptions = $$props.frameOptions);
  35172. if ("markupEditorShapeStyleControls" in $$props) $$invalidate(3, markupEditorShapeStyleControls = $$props.markupEditorShapeStyleControls);
  35173. };
  35174. $$self.$$.update = () => {
  35175. if ($$self.$$.dirty & /*$animation, $isActive*/ 786432) {
  35176. $animation && footerOffset.set($isActive ? 0 : 20);
  35177. }
  35178. if ($$self.$$.dirty & /*$footerOffset*/ 1048576) {
  35179. $$invalidate(6, footerStyle = $footerOffset
  35180. ? `transform: translateY(${$footerOffset}px)`
  35181. : undefined);
  35182. }
  35183. };
  35184. $$invalidate(4, computedScrollElasticity = elasticityMultiplier * scrollElasticity);
  35185. return [
  35186. isActive,
  35187. locale,
  35188. frameOptions,
  35189. markupEditorShapeStyleControls,
  35190. computedScrollElasticity,
  35191. $imageFrame,
  35192. footerStyle,
  35193. animation,
  35194. scrollElasticity,
  35195. imageFrame,
  35196. selectedFrameIndex,
  35197. handleChangeFrame,
  35198. handleUpdateSelectedFrameShape,
  35199. getOptionThumb,
  35200. footerOffset,
  35201. name,
  35202. stores,
  35203. frameStyles,
  35204. $animation,
  35205. $isActive,
  35206. $footerOffset,
  35207. measure_handler
  35208. ];
  35209. }
  35210. class Frame extends SvelteComponent {
  35211. constructor(options) {
  35212. super();
  35213. init(this, options, instance$5, create_fragment$5, safe_not_equal, {
  35214. name: 15,
  35215. isActive: 0,
  35216. stores: 16,
  35217. locale: 1,
  35218. frameStyles: 17,
  35219. frameOptions: 2,
  35220. markupEditorShapeStyleControls: 3
  35221. });
  35222. }
  35223. get name() {
  35224. return this.$$.ctx[15];
  35225. }
  35226. get isActive() {
  35227. return this.$$.ctx[0];
  35228. }
  35229. set isActive(isActive) {
  35230. this.$set({ isActive });
  35231. flush();
  35232. }
  35233. get stores() {
  35234. return this.$$.ctx[16];
  35235. }
  35236. set stores(stores) {
  35237. this.$set({ stores });
  35238. flush();
  35239. }
  35240. get locale() {
  35241. return this.$$.ctx[1];
  35242. }
  35243. set locale(locale) {
  35244. this.$set({ locale });
  35245. flush();
  35246. }
  35247. get frameStyles() {
  35248. return this.$$.ctx[17];
  35249. }
  35250. set frameStyles(frameStyles) {
  35251. this.$set({ frameStyles });
  35252. flush();
  35253. }
  35254. get frameOptions() {
  35255. return this.$$.ctx[2];
  35256. }
  35257. set frameOptions(frameOptions) {
  35258. this.$set({ frameOptions });
  35259. flush();
  35260. }
  35261. get markupEditorShapeStyleControls() {
  35262. return this.$$.ctx[3];
  35263. }
  35264. set markupEditorShapeStyleControls(markupEditorShapeStyleControls) {
  35265. this.$set({ markupEditorShapeStyleControls });
  35266. flush();
  35267. }
  35268. }
  35269. // @ts-ignore
  35270. var _plugin_frame = { util: ['frame', Frame] };
  35271. /* src/core/ui/plugins/resize/DimensionInput.svelte generated by Svelte v3.37.0 */
  35272. function create_fragment$4(ctx) {
  35273. let div;
  35274. let label_1;
  35275. let t0;
  35276. let t1;
  35277. let input;
  35278. let input_value_value;
  35279. let mounted;
  35280. let dispose;
  35281. return {
  35282. c() {
  35283. div = element("div");
  35284. label_1 = element("label");
  35285. t0 = text(/*label*/ ctx[1]);
  35286. t1 = space();
  35287. input = element("input");
  35288. attr(label_1, "for", /*id*/ ctx[0]);
  35289. attr(label_1, "title", /*title*/ ctx[2]);
  35290. attr(label_1, "aria-label", /*title*/ ctx[2]);
  35291. attr(input, "id", /*id*/ ctx[0]);
  35292. attr(input, "type", "text");
  35293. attr(input, "inputmode", "numeric");
  35294. attr(input, "pattern", "[0-9]*");
  35295. attr(input, "data-state", /*state*/ ctx[3]);
  35296. attr(input, "autocomplete", "off");
  35297. attr(input, "placeholder", /*placeholder*/ ctx[4]);
  35298. input.value = input_value_value = /*value*/ ctx[5] === undefined
  35299. ? ""
  35300. : /*format*/ ctx[7](/*value*/ ctx[5] + "");
  35301. attr(div, "class", "PinturaInputDimension");
  35302. },
  35303. m(target, anchor) {
  35304. insert(target, div, anchor);
  35305. append(div, label_1);
  35306. append(label_1, t0);
  35307. append(div, t1);
  35308. append(div, input);
  35309. if (!mounted) {
  35310. dispose = listen(input, "input", /*input_handler*/ ctx[8]);
  35311. mounted = true;
  35312. }
  35313. },
  35314. p(ctx, [dirty]) {
  35315. if (dirty & /*label*/ 2) set_data(t0, /*label*/ ctx[1]);
  35316. if (dirty & /*id*/ 1) {
  35317. attr(label_1, "for", /*id*/ ctx[0]);
  35318. }
  35319. if (dirty & /*title*/ 4) {
  35320. attr(label_1, "title", /*title*/ ctx[2]);
  35321. }
  35322. if (dirty & /*title*/ 4) {
  35323. attr(label_1, "aria-label", /*title*/ ctx[2]);
  35324. }
  35325. if (dirty & /*id*/ 1) {
  35326. attr(input, "id", /*id*/ ctx[0]);
  35327. }
  35328. if (dirty & /*state*/ 8) {
  35329. attr(input, "data-state", /*state*/ ctx[3]);
  35330. }
  35331. if (dirty & /*placeholder*/ 16) {
  35332. attr(input, "placeholder", /*placeholder*/ ctx[4]);
  35333. }
  35334. if (dirty & /*value, format*/ 160 && input_value_value !== (input_value_value = /*value*/ ctx[5] === undefined
  35335. ? ""
  35336. : /*format*/ ctx[7](/*value*/ ctx[5] + "")) && input.value !== input_value_value) {
  35337. input.value = input_value_value;
  35338. }
  35339. },
  35340. i: noop,
  35341. o: noop,
  35342. d(detaching) {
  35343. if (detaching) detach(div);
  35344. mounted = false;
  35345. dispose();
  35346. }
  35347. };
  35348. }
  35349. function instance$4($$self, $$props, $$invalidate) {
  35350. let { id } = $$props;
  35351. let { label } = $$props;
  35352. let { title } = $$props;
  35353. let { state } = $$props;
  35354. let { placeholder } = $$props;
  35355. let { value } = $$props;
  35356. let { onchange } = $$props;
  35357. let { format = str => str.replace(/\D/g, "") } = $$props;
  35358. const input_handler = e => onchange(format(e.currentTarget.value));
  35359. $$self.$$set = $$props => {
  35360. if ("id" in $$props) $$invalidate(0, id = $$props.id);
  35361. if ("label" in $$props) $$invalidate(1, label = $$props.label);
  35362. if ("title" in $$props) $$invalidate(2, title = $$props.title);
  35363. if ("state" in $$props) $$invalidate(3, state = $$props.state);
  35364. if ("placeholder" in $$props) $$invalidate(4, placeholder = $$props.placeholder);
  35365. if ("value" in $$props) $$invalidate(5, value = $$props.value);
  35366. if ("onchange" in $$props) $$invalidate(6, onchange = $$props.onchange);
  35367. if ("format" in $$props) $$invalidate(7, format = $$props.format);
  35368. };
  35369. return [id, label, title, state, placeholder, value, onchange, format, input_handler];
  35370. }
  35371. class DimensionInput extends SvelteComponent {
  35372. constructor(options) {
  35373. super();
  35374. init(this, options, instance$4, create_fragment$4, safe_not_equal, {
  35375. id: 0,
  35376. label: 1,
  35377. title: 2,
  35378. state: 3,
  35379. placeholder: 4,
  35380. value: 5,
  35381. onchange: 6,
  35382. format: 7
  35383. });
  35384. }
  35385. }
  35386. /* src/core/ui/plugins/resize/DimensionLock.svelte generated by Svelte v3.37.0 */
  35387. function create_default_slot$1(ctx) {
  35388. let g;
  35389. return {
  35390. c() {
  35391. g = svg_element("g");
  35392. },
  35393. m(target, anchor) {
  35394. insert(target, g, anchor);
  35395. g.innerHTML = /*icon*/ ctx[2];
  35396. },
  35397. p(ctx, dirty) {
  35398. if (dirty & /*icon*/ 4) g.innerHTML = /*icon*/ ctx[2]; },
  35399. d(detaching) {
  35400. if (detaching) detach(g);
  35401. }
  35402. };
  35403. }
  35404. function create_fragment$3(ctx) {
  35405. let div;
  35406. let input;
  35407. let t;
  35408. let label;
  35409. let icon_1;
  35410. let current;
  35411. let mounted;
  35412. let dispose;
  35413. icon_1 = new Icon({
  35414. props: {
  35415. $$slots: { default: [create_default_slot$1] },
  35416. $$scope: { ctx }
  35417. }
  35418. });
  35419. return {
  35420. c() {
  35421. div = element("div");
  35422. input = element("input");
  35423. t = space();
  35424. label = element("label");
  35425. create_component(icon_1.$$.fragment);
  35426. attr(input, "id", /*id*/ ctx[0]);
  35427. attr(input, "class", "implicit");
  35428. attr(input, "type", "checkbox");
  35429. input.checked = /*locked*/ ctx[1];
  35430. attr(label, "for", /*id*/ ctx[0]);
  35431. attr(label, "title", /*title*/ ctx[3]);
  35432. },
  35433. m(target, anchor) {
  35434. insert(target, div, anchor);
  35435. append(div, input);
  35436. append(div, t);
  35437. append(div, label);
  35438. mount_component(icon_1, label, null);
  35439. current = true;
  35440. if (!mounted) {
  35441. dispose = listen(input, "change", /*change_handler*/ ctx[5]);
  35442. mounted = true;
  35443. }
  35444. },
  35445. p(ctx, [dirty]) {
  35446. if (!current || dirty & /*id*/ 1) {
  35447. attr(input, "id", /*id*/ ctx[0]);
  35448. }
  35449. if (!current || dirty & /*locked*/ 2) {
  35450. input.checked = /*locked*/ ctx[1];
  35451. }
  35452. const icon_1_changes = {};
  35453. if (dirty & /*$$scope, icon*/ 68) {
  35454. icon_1_changes.$$scope = { dirty, ctx };
  35455. }
  35456. icon_1.$set(icon_1_changes);
  35457. if (!current || dirty & /*id*/ 1) {
  35458. attr(label, "for", /*id*/ ctx[0]);
  35459. }
  35460. if (!current || dirty & /*title*/ 8) {
  35461. attr(label, "title", /*title*/ ctx[3]);
  35462. }
  35463. },
  35464. i(local) {
  35465. if (current) return;
  35466. transition_in(icon_1.$$.fragment, local);
  35467. current = true;
  35468. },
  35469. o(local) {
  35470. transition_out(icon_1.$$.fragment, local);
  35471. current = false;
  35472. },
  35473. d(detaching) {
  35474. if (detaching) detach(div);
  35475. destroy_component(icon_1);
  35476. mounted = false;
  35477. dispose();
  35478. }
  35479. };
  35480. }
  35481. function instance$3($$self, $$props, $$invalidate) {
  35482. let { id } = $$props;
  35483. let { locked } = $$props;
  35484. let { icon } = $$props;
  35485. let { title } = $$props;
  35486. let { onchange } = $$props;
  35487. const change_handler = e => onchange(e.currentTarget.checked);
  35488. $$self.$$set = $$props => {
  35489. if ("id" in $$props) $$invalidate(0, id = $$props.id);
  35490. if ("locked" in $$props) $$invalidate(1, locked = $$props.locked);
  35491. if ("icon" in $$props) $$invalidate(2, icon = $$props.icon);
  35492. if ("title" in $$props) $$invalidate(3, title = $$props.title);
  35493. if ("onchange" in $$props) $$invalidate(4, onchange = $$props.onchange);
  35494. };
  35495. return [id, locked, icon, title, onchange, change_handler];
  35496. }
  35497. class DimensionLock extends SvelteComponent {
  35498. constructor(options) {
  35499. super();
  35500. init(this, options, instance$3, create_fragment$3, safe_not_equal, {
  35501. id: 0,
  35502. locked: 1,
  35503. icon: 2,
  35504. title: 3,
  35505. onchange: 4
  35506. });
  35507. }
  35508. }
  35509. /* src/core/ui/plugins/resize/index.svelte generated by Svelte v3.37.0 */
  35510. function create_default_slot(ctx) {
  35511. let t;
  35512. return {
  35513. c() {
  35514. t = text("Save");
  35515. },
  35516. m(target, anchor) {
  35517. insert(target, t, anchor);
  35518. },
  35519. d(detaching) {
  35520. if (detaching) detach(t);
  35521. }
  35522. };
  35523. }
  35524. // (542:4)
  35525. function create_footer_slot(ctx) {
  35526. let form;
  35527. let div1;
  35528. let fieldset;
  35529. let legend;
  35530. let t0_value = /*locale*/ ctx[1].resizeLabelFormCaption + "";
  35531. let t0;
  35532. let t1;
  35533. let div0;
  35534. let dynamiccomponenttree;
  35535. let t2;
  35536. let button;
  35537. let current;
  35538. let mounted;
  35539. let dispose;
  35540. dynamiccomponenttree = new DynamicComponentTree_1({ props: { items: /*tools*/ ctx[3] } });
  35541. button = new Button({
  35542. props: {
  35543. type: "submit",
  35544. class: "implicit",
  35545. $$slots: { default: [create_default_slot] },
  35546. $$scope: { ctx }
  35547. }
  35548. });
  35549. return {
  35550. c() {
  35551. form = element("form");
  35552. div1 = element("div");
  35553. fieldset = element("fieldset");
  35554. legend = element("legend");
  35555. t0 = text(t0_value);
  35556. t1 = space();
  35557. div0 = element("div");
  35558. create_component(dynamiccomponenttree.$$.fragment);
  35559. t2 = space();
  35560. create_component(button.$$.fragment);
  35561. attr(legend, "class", "implicit");
  35562. attr(div0, "class", "PinturaFieldsetInner");
  35563. attr(div1, "class", "PinturaFormInner");
  35564. attr(form, "slot", "footer");
  35565. attr(form, "style", /*footerStyle*/ ctx[4]);
  35566. },
  35567. m(target, anchor) {
  35568. insert(target, form, anchor);
  35569. append(form, div1);
  35570. append(div1, fieldset);
  35571. append(fieldset, legend);
  35572. append(legend, t0);
  35573. append(fieldset, t1);
  35574. append(fieldset, div0);
  35575. mount_component(dynamiccomponenttree, div0, null);
  35576. /*div0_binding*/ ctx[62](div0);
  35577. append(div1, t2);
  35578. mount_component(button, div1, null);
  35579. current = true;
  35580. if (!mounted) {
  35581. dispose = [
  35582. listen(div0, "focusin", /*handleFocusIn*/ ctx[13]),
  35583. listen(div0, "focusout", /*handleFocusOut*/ ctx[14]),
  35584. listen(form, "submit", prevent_default(/*handleSubmit*/ ctx[15]))
  35585. ];
  35586. mounted = true;
  35587. }
  35588. },
  35589. p(ctx, dirty) {
  35590. if ((!current || dirty[0] & /*locale*/ 2) && t0_value !== (t0_value = /*locale*/ ctx[1].resizeLabelFormCaption + "")) set_data(t0, t0_value);
  35591. const dynamiccomponenttree_changes = {};
  35592. if (dirty[0] & /*tools*/ 8) dynamiccomponenttree_changes.items = /*tools*/ ctx[3];
  35593. dynamiccomponenttree.$set(dynamiccomponenttree_changes);
  35594. const button_changes = {};
  35595. if (dirty[2] & /*$$scope*/ 524288) {
  35596. button_changes.$$scope = { dirty, ctx };
  35597. }
  35598. button.$set(button_changes);
  35599. if (!current || dirty[0] & /*footerStyle*/ 16) {
  35600. attr(form, "style", /*footerStyle*/ ctx[4]);
  35601. }
  35602. },
  35603. i(local) {
  35604. if (current) return;
  35605. transition_in(dynamiccomponenttree.$$.fragment, local);
  35606. transition_in(button.$$.fragment, local);
  35607. current = true;
  35608. },
  35609. o(local) {
  35610. transition_out(dynamiccomponenttree.$$.fragment, local);
  35611. transition_out(button.$$.fragment, local);
  35612. current = false;
  35613. },
  35614. d(detaching) {
  35615. if (detaching) detach(form);
  35616. destroy_component(dynamiccomponenttree);
  35617. /*div0_binding*/ ctx[62](null);
  35618. destroy_component(button);
  35619. mounted = false;
  35620. run_all(dispose);
  35621. }
  35622. };
  35623. }
  35624. function create_fragment$2(ctx) {
  35625. let util;
  35626. let current;
  35627. util = new Util({
  35628. props: {
  35629. $$slots: { footer: [create_footer_slot] },
  35630. $$scope: { ctx }
  35631. }
  35632. });
  35633. util.$on("measure", /*measure_handler*/ ctx[63]);
  35634. return {
  35635. c() {
  35636. create_component(util.$$.fragment);
  35637. },
  35638. m(target, anchor) {
  35639. mount_component(util, target, anchor);
  35640. current = true;
  35641. },
  35642. p(ctx, dirty) {
  35643. const util_changes = {};
  35644. if (dirty[0] & /*footerStyle, fieldsGroup, tools, locale*/ 30 | dirty[2] & /*$$scope*/ 524288) {
  35645. util_changes.$$scope = { dirty, ctx };
  35646. }
  35647. util.$set(util_changes);
  35648. },
  35649. i(local) {
  35650. if (current) return;
  35651. transition_in(util.$$.fragment, local);
  35652. current = true;
  35653. },
  35654. o(local) {
  35655. transition_out(util.$$.fragment, local);
  35656. current = false;
  35657. },
  35658. d(detaching) {
  35659. destroy_component(util, detaching);
  35660. }
  35661. };
  35662. }
  35663. function instance$2($$self, $$props, $$invalidate) {
  35664. let sizePresetLabel;
  35665. let widthPresetLabel;
  35666. let heightPresetLabel;
  35667. let canRenderSizePresets;
  35668. let canRenderWidthPresets;
  35669. let canRenderHeightPresets;
  35670. let canRenderSizeInputs;
  35671. let tools;
  35672. let footerStyle;
  35673. let $imageCropRectAspectRatio;
  35674. let $imageOutputSize;
  35675. let $imageCropAspectRatio;
  35676. let $imageSize;
  35677. let $formattedResizeSizePresetOptions;
  35678. let $formattedResizeSizePresetOptionsFlattened;
  35679. let $formattedResizeWidthPresetOptions;
  35680. let $formattedResizeWidthPresetOptionsFlattened;
  35681. let $formattedResizeHeightPresetOptions;
  35682. let $formattedResizeHeightPresetOptionsFlattened;
  35683. let $sizePresetSelectedIndex;
  35684. let $widthPresetSelectedIndex;
  35685. let $heightPresetSelectedIndex;
  35686. let $imageCropRect;
  35687. let $iconActiveFraction;
  35688. let $env;
  35689. let $animation;
  35690. let $isActive,
  35691. $$unsubscribe_isActive = noop,
  35692. $$subscribe_isActive = () => ($$unsubscribe_isActive(), $$unsubscribe_isActive = subscribe(isActive, $$value => $$invalidate(60, $isActive = $$value)), isActive);
  35693. let $footerOffset;
  35694. $$self.$$.on_destroy.push(() => $$unsubscribe_isActive());
  35695. const formatValue = (value, min = 0, max = 9999) => {
  35696. if (isString(value)) {
  35697. value = value.replace(/\D/g, "");
  35698. if (!value.length) return;
  35699. }
  35700. const v = Math.round(value);
  35701. if (Number.isNaN(v)) return;
  35702. return clamp(v, min, max);
  35703. };
  35704. const name = "resize";
  35705. let { isActive } = $$props;
  35706. $$subscribe_isActive();
  35707. let { stores } = $$props;
  35708. let { locale = {} } = $$props;
  35709. let { resizeMinSize = sizeCreate(1, 1) } = $$props;
  35710. let { resizeMaxSize = sizeCreate(9999, 9999) } = $$props;
  35711. let { resizeSizePresetOptions = undefined } = $$props;
  35712. let { resizeWidthPresetOptions = undefined } = $$props;
  35713. let { resizeHeightPresetOptions = undefined } = $$props;
  35714. let { resizeWillRenderFooter = passthrough } = $$props;
  35715. // offset
  35716. const iconActiveFraction = spring(0, { stiffness: 0.15, damping: 0.3 });
  35717. component_subscribe($$self, iconActiveFraction, value => $$invalidate(57, $iconActiveFraction = value));
  35718. const { animation, imageSize, imageCropRect, imageCropRectAspectRatio, imageCropAspectRatio, imageOutputSize, history, env } = stores;
  35719. component_subscribe($$self, animation, value => $$invalidate(59, $animation = value));
  35720. component_subscribe($$self, imageSize, value => $$invalidate(69, $imageSize = value));
  35721. component_subscribe($$self, imageCropRect, value => $$invalidate(52, $imageCropRect = value));
  35722. component_subscribe($$self, imageCropRectAspectRatio, value => $$invalidate(39, $imageCropRectAspectRatio = value));
  35723. component_subscribe($$self, imageCropAspectRatio, value => $$invalidate(68, $imageCropAspectRatio = value));
  35724. component_subscribe($$self, imageOutputSize, value => $$invalidate(67, $imageOutputSize = value));
  35725. component_subscribe($$self, env, value => $$invalidate(58, $env = value));
  35726. const formId = getUniqueId();
  35727. let fieldsGroup;
  35728. let maintainAspectRatio = false;
  35729. let width;
  35730. let height;
  35731. let activeField;
  35732. let lastActiveField;
  35733. const getState = (value, field, activeField, resizeMinSize, resizeMaxSize) => value != null && activeField !== field
  35734. ? value >= resizeMinSize[field] && value <= resizeMaxSize[field]
  35735. ? "valid"
  35736. : "invalid"
  35737. : "undetermined";
  35738. const getWidthPlaceholder = (value, cropAspectRatio, cropRect) => Math.round(value != null ? value * cropAspectRatio : cropRect.width);
  35739. const getHeightPlaceholder = (value, cropAspectRatio, cropRect) => Math.round(value != null
  35740. ? value / cropAspectRatio
  35741. : cropRect.height);
  35742. // populate active field
  35743. const handleFocusIn = e => {
  35744. const id = e.target.id;
  35745. if ((/width/).test(id)) {
  35746. $$invalidate(37, activeField = "width");
  35747. } else if ((/height/).test(id)) {
  35748. $$invalidate(37, activeField = "height");
  35749. } else if ((/aspectRatio/i).test(id)) {
  35750. $$invalidate(37, activeField = "lock");
  35751. } else {
  35752. $$invalidate(37, activeField = undefined);
  35753. }
  35754. };
  35755. const handleFocusOut = e => {
  35756. if (!fieldsGroup.contains(e.relatedTarget)) handleSubmit();
  35757. $$invalidate(37, activeField = undefined);
  35758. };
  35759. // sync fields if one has a value and aspect ratio should be maintained
  35760. const syncFields = () => {
  35761. if (!maintainAspectRatio || !width || !height) return;
  35762. if (activeField === "width") {
  35763. // sync height field
  35764. $$invalidate(36, height = Math.round(width / $imageCropRectAspectRatio));
  35765. } else if (activeField === "height") {
  35766. // sync width field
  35767. $$invalidate(35, width = Math.round(height * $imageCropRectAspectRatio));
  35768. } else {
  35769. if (lastActiveField === "width") {
  35770. $$invalidate(36, height = Math.round(width / $imageCropRectAspectRatio));
  35771. } else if (lastActiveField === "height") {
  35772. $$invalidate(35, width = Math.round(height * $imageCropRectAspectRatio));
  35773. }
  35774. consolidateSize();
  35775. }
  35776. };
  35777. // $: if (maintainAspectRatio && width && height) syncFields()
  35778. const consolidateSize = forcedAspectRatio => {
  35779. // first need to limit values
  35780. let inputWidth = formatValue(width);
  35781. let inputHeight = formatValue(height);
  35782. let currentWidth = inputWidth;
  35783. let currentHeight = inputHeight;
  35784. let bothAxisDefined = currentWidth && currentHeight;
  35785. let aspectRatio = forcedAspectRatio || $imageCropRectAspectRatio;
  35786. // done, no consolidation needed
  35787. if (!currentWidth && !currentHeight) return;
  35788. // need to fill in missing values
  35789. if (currentWidth && !currentHeight) {
  35790. currentHeight = Math.round(currentWidth / aspectRatio);
  35791. } else if (currentHeight && !currentWidth) {
  35792. currentWidth = Math.round(currentHeight * aspectRatio);
  35793. }
  35794. aspectRatio = forcedAspectRatio || bothAxisDefined
  35795. ? getAspectRatio(currentWidth, currentHeight)
  35796. : $imageCropRectAspectRatio;
  35797. // now we have both width and height let's re-fit the min max size
  35798. let currentSize = sizeCreate(currentWidth, currentHeight);
  35799. if (!sizeContains(resizeMaxSize, currentSize)) {
  35800. // too big
  35801. currentSize = rectContainRect(resizeMaxSize, aspectRatio);
  35802. }
  35803. if (!sizeContains(currentSize, resizeMinSize)) {
  35804. // too small
  35805. currentSize = rectCoverRect(resizeMinSize, aspectRatio);
  35806. }
  35807. $$invalidate(35, width = inputWidth != null
  35808. ? Math.round(currentSize.width)
  35809. : undefined);
  35810. $$invalidate(36, height = inputHeight != null
  35811. ? Math.round(currentSize.height)
  35812. : undefined);
  35813. };
  35814. const handleSubmit = () => {
  35815. // calculate correct values
  35816. consolidateSize();
  35817. // get curent values so we can check if they were changed (if not, no need to write history or update)
  35818. const { width: currentWidth, height: currentHeight } = $imageOutputSize || {};
  35819. // no need to update
  35820. if (currentWidth === width && currentHeight === height) return;
  35821. // update state
  35822. if (!width && !height) {
  35823. // reset image crop
  35824. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = $imageSize.width / $imageSize.height, $imageCropAspectRatio);
  35825. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = undefined, $imageCropAspectRatio);
  35826. // reset output size
  35827. set_store_value(imageOutputSize, $imageOutputSize = undefined, $imageOutputSize);
  35828. } else {
  35829. if (width && height) set_store_value(imageCropAspectRatio, $imageCropAspectRatio = width / height, $imageCropAspectRatio);
  35830. set_store_value(imageOutputSize, $imageOutputSize = sizeCreate(width, height), $imageOutputSize);
  35831. }
  35832. history.write();
  35833. };
  35834. // handle external updates to outputSize
  35835. imageOutputSize.subscribe(size => {
  35836. if (!size) {
  35837. $$invalidate(35, width = undefined);
  35838. $$invalidate(36, height = undefined);
  35839. return;
  35840. }
  35841. $$invalidate(35, width = size.width);
  35842. $$invalidate(36, height = size.height);
  35843. // make sure the size conforms to min max
  35844. consolidateSize();
  35845. });
  35846. // if the crop aspect ratio is changed we need to align width/height
  35847. imageCropAspectRatio.subscribe(cropAspectRatio => {
  35848. // exit if no dimensions supplied
  35849. if (!width && !height) return;
  35850. // no crop aspect ratio has been selected, so all is fine
  35851. if (!cropAspectRatio) return;
  35852. // fix size to match new aspect ratio of the crop
  35853. if (width && height && getAspectRatio(width, height) !== cropAspectRatio) {
  35854. $$invalidate(36, height = width / cropAspectRatio);
  35855. consolidateSize(cropAspectRatio);
  35856. } else {
  35857. consolidateSize();
  35858. }
  35859. });
  35860. //
  35861. // size presets
  35862. //
  35863. const formatPresetDimensionOption = option => {
  35864. if (isString(option[0])) {
  35865. option[1] = option[1].map(formatPresetDimensionOption);
  35866. return option;
  35867. }
  35868. return isNumber(option) ? [option, "" + option] : option;
  35869. };
  35870. const formatPresetSizeOption = option => {
  35871. if (isString(option[0])) {
  35872. option[1] = option[1].map(formatPresetSizeOption);
  35873. return option;
  35874. }
  35875. let [value, label] = option;
  35876. // Size only
  35877. if (isNumber(value) && isNumber(label)) {
  35878. const [w, h] = [value, label];
  35879. label = `${w} × ${h}`;
  35880. value = [w, h];
  35881. }
  35882. return [value, label];
  35883. };
  35884. const formattedResizeSizePresetOptions = writable();
  35885. component_subscribe($$self, formattedResizeSizePresetOptions, value => $$invalidate(40, $formattedResizeSizePresetOptions = value));
  35886. const formattedResizeSizePresetOptionsFlattened = writable();
  35887. component_subscribe($$self, formattedResizeSizePresetOptionsFlattened, value => $$invalidate(41, $formattedResizeSizePresetOptionsFlattened = value));
  35888. const formattedResizeWidthPresetOptions = writable();
  35889. component_subscribe($$self, formattedResizeWidthPresetOptions, value => $$invalidate(42, $formattedResizeWidthPresetOptions = value));
  35890. const formattedResizeWidthPresetOptionsFlattened = writable();
  35891. component_subscribe($$self, formattedResizeWidthPresetOptionsFlattened, value => $$invalidate(43, $formattedResizeWidthPresetOptionsFlattened = value));
  35892. const formattedResizeHeightPresetOptions = writable();
  35893. component_subscribe($$self, formattedResizeHeightPresetOptions, value => $$invalidate(44, $formattedResizeHeightPresetOptions = value));
  35894. const formattedResizeHeightPresetOptionsFlattened = writable();
  35895. component_subscribe($$self, formattedResizeHeightPresetOptionsFlattened, value => $$invalidate(45, $formattedResizeHeightPresetOptionsFlattened = value));
  35896. const sizePresetSelectedIndex = derived([imageOutputSize, formattedResizeSizePresetOptionsFlattened], ([$imageOutputSize, $formattedResizeSizePresetOptionsFlattened], set) => {
  35897. if (!$formattedResizeSizePresetOptionsFlattened) return set(-1);
  35898. const index = $formattedResizeSizePresetOptionsFlattened.findIndex(([value]) => {
  35899. if (!value && !$imageOutputSize) return true;
  35900. if (!value) return false;
  35901. const [width, height] = value;
  35902. return $imageOutputSize.width === width && $imageOutputSize.height === height;
  35903. });
  35904. set(index < 0 ? 0 : index);
  35905. });
  35906. component_subscribe($$self, sizePresetSelectedIndex, value => $$invalidate(47, $sizePresetSelectedIndex = value));
  35907. const widthPresetSelectedIndex = derived([imageOutputSize, formattedResizeWidthPresetOptionsFlattened], ([$imageOutputSize, $formattedResizeWidthPresetOptionsFlattened], set) => {
  35908. if (!$formattedResizeWidthPresetOptionsFlattened) return set(-1);
  35909. const index = $formattedResizeWidthPresetOptionsFlattened.findIndex(([value]) => {
  35910. if (!value && !$imageOutputSize) return true;
  35911. if (!value) return false;
  35912. return $imageOutputSize.width === value;
  35913. });
  35914. set(index < 0 ? 0 : index);
  35915. });
  35916. component_subscribe($$self, widthPresetSelectedIndex, value => $$invalidate(49, $widthPresetSelectedIndex = value));
  35917. const heightPresetSelectedIndex = derived([imageOutputSize, formattedResizeHeightPresetOptionsFlattened], ([$imageOutputSize, $formattedResizeHeightPresetOptionsFlattened], set) => {
  35918. if (!$formattedResizeHeightPresetOptionsFlattened) return set(-1);
  35919. const index = $formattedResizeHeightPresetOptionsFlattened.findIndex(([value]) => {
  35920. if (!value && !$imageOutputSize) return true;
  35921. if (!value) return false;
  35922. return $imageOutputSize.height === value;
  35923. });
  35924. set(index < 0 ? 0 : index);
  35925. });
  35926. component_subscribe($$self, heightPresetSelectedIndex, value => $$invalidate(51, $heightPresetSelectedIndex = value));
  35927. let storedCropRect = undefined;
  35928. let storedCropAspectRatio = undefined;
  35929. const setImageOutputSizeWithArray = size => {
  35930. if (size && !storedCropRect) {
  35931. storedCropRect = { ...$imageCropRect };
  35932. storedCropAspectRatio = $imageCropAspectRatio;
  35933. }
  35934. if (!size) {
  35935. set_store_value(imageCropRect, $imageCropRect = storedCropRect, $imageCropRect);
  35936. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = storedCropAspectRatio, $imageCropAspectRatio);
  35937. set_store_value(imageOutputSize, $imageOutputSize = undefined, $imageOutputSize);
  35938. storedCropRect = undefined;
  35939. storedCropAspectRatio = undefined;
  35940. } else {
  35941. set_store_value(imageCropAspectRatio, $imageCropAspectRatio = getAspectRatio(size[0], size[1]), $imageCropAspectRatio);
  35942. set_store_value(imageOutputSize, $imageOutputSize = sizeCreateFromArray(size), $imageOutputSize);
  35943. }
  35944. history.write();
  35945. };
  35946. //
  35947. // toolbar
  35948. //
  35949. let redrawTrigger = {};
  35950. //
  35951. // Footer
  35952. //
  35953. const footerOffset = spring($animation ? 20 : 0);
  35954. component_subscribe($$self, footerOffset, value => $$invalidate(61, $footerOffset = value));
  35955. function div0_binding($$value) {
  35956. binding_callbacks[$$value ? "unshift" : "push"](() => {
  35957. fieldsGroup = $$value;
  35958. $$invalidate(2, fieldsGroup);
  35959. });
  35960. }
  35961. function measure_handler(event) {
  35962. bubble($$self, event);
  35963. }
  35964. $$self.$$set = $$props => {
  35965. if ("isActive" in $$props) $$subscribe_isActive($$invalidate(0, isActive = $$props.isActive));
  35966. if ("stores" in $$props) $$invalidate(27, stores = $$props.stores);
  35967. if ("locale" in $$props) $$invalidate(1, locale = $$props.locale);
  35968. if ("resizeMinSize" in $$props) $$invalidate(28, resizeMinSize = $$props.resizeMinSize);
  35969. if ("resizeMaxSize" in $$props) $$invalidate(29, resizeMaxSize = $$props.resizeMaxSize);
  35970. if ("resizeSizePresetOptions" in $$props) $$invalidate(30, resizeSizePresetOptions = $$props.resizeSizePresetOptions);
  35971. if ("resizeWidthPresetOptions" in $$props) $$invalidate(31, resizeWidthPresetOptions = $$props.resizeWidthPresetOptions);
  35972. if ("resizeHeightPresetOptions" in $$props) $$invalidate(32, resizeHeightPresetOptions = $$props.resizeHeightPresetOptions);
  35973. if ("resizeWillRenderFooter" in $$props) $$invalidate(33, resizeWillRenderFooter = $$props.resizeWillRenderFooter);
  35974. };
  35975. $$self.$$.update = () => {
  35976. if ($$self.$$.dirty[0] & /*resizeSizePresetOptions*/ 1073741824 | $$self.$$.dirty[1] & /*$formattedResizeSizePresetOptions*/ 512) {
  35977. if (resizeSizePresetOptions) {
  35978. set_store_value(formattedResizeSizePresetOptions, $formattedResizeSizePresetOptions = resizeSizePresetOptions.map(formatPresetSizeOption), $formattedResizeSizePresetOptions);
  35979. set_store_value(formattedResizeSizePresetOptionsFlattened, $formattedResizeSizePresetOptionsFlattened = flattenOptions($formattedResizeSizePresetOptions), $formattedResizeSizePresetOptionsFlattened);
  35980. }
  35981. }
  35982. if ($$self.$$.dirty[1] & /*$formattedResizeSizePresetOptions*/ 512) {
  35983. //
  35984. // helper bools
  35985. //
  35986. $$invalidate(53, canRenderSizePresets = !!$formattedResizeSizePresetOptions);
  35987. }
  35988. if ($$self.$$.dirty[1] & /*$sizePresetSelectedIndex, $formattedResizeSizePresetOptionsFlattened*/ 66560) {
  35989. $$invalidate(46, sizePresetLabel = $sizePresetSelectedIndex > -1 && $formattedResizeSizePresetOptionsFlattened[$sizePresetSelectedIndex][1]);
  35990. }
  35991. if ($$self.$$.dirty[1] & /*resizeWidthPresetOptions, $formattedResizeWidthPresetOptions*/ 2049) {
  35992. if (resizeWidthPresetOptions) {
  35993. set_store_value(formattedResizeWidthPresetOptions, $formattedResizeWidthPresetOptions = resizeWidthPresetOptions.map(formatPresetDimensionOption), $formattedResizeWidthPresetOptions);
  35994. set_store_value(formattedResizeWidthPresetOptionsFlattened, $formattedResizeWidthPresetOptionsFlattened = flattenOptions($formattedResizeWidthPresetOptions), $formattedResizeWidthPresetOptionsFlattened);
  35995. }
  35996. }
  35997. if ($$self.$$.dirty[1] & /*canRenderSizePresets, $formattedResizeWidthPresetOptions*/ 4196352) {
  35998. $$invalidate(54, canRenderWidthPresets = !canRenderSizePresets && $formattedResizeWidthPresetOptions);
  35999. }
  36000. if ($$self.$$.dirty[1] & /*$widthPresetSelectedIndex, $formattedResizeWidthPresetOptionsFlattened*/ 266240) {
  36001. $$invalidate(48, widthPresetLabel = $widthPresetSelectedIndex > -1 && $formattedResizeWidthPresetOptionsFlattened[$widthPresetSelectedIndex][1]);
  36002. }
  36003. if ($$self.$$.dirty[1] & /*resizeHeightPresetOptions, $formattedResizeHeightPresetOptions*/ 8194) {
  36004. if (resizeHeightPresetOptions) {
  36005. set_store_value(formattedResizeHeightPresetOptions, $formattedResizeHeightPresetOptions = resizeHeightPresetOptions.map(formatPresetDimensionOption), $formattedResizeHeightPresetOptions);
  36006. set_store_value(formattedResizeHeightPresetOptionsFlattened, $formattedResizeHeightPresetOptionsFlattened = flattenOptions($formattedResizeHeightPresetOptions), $formattedResizeHeightPresetOptionsFlattened);
  36007. }
  36008. }
  36009. if ($$self.$$.dirty[1] & /*canRenderSizePresets, $formattedResizeHeightPresetOptions*/ 4202496) {
  36010. $$invalidate(55, canRenderHeightPresets = !canRenderSizePresets && $formattedResizeHeightPresetOptions);
  36011. }
  36012. if ($$self.$$.dirty[1] & /*$heightPresetSelectedIndex, $formattedResizeHeightPresetOptionsFlattened*/ 1064960) {
  36013. $$invalidate(50, heightPresetLabel = $heightPresetSelectedIndex > -1 && $formattedResizeHeightPresetOptionsFlattened[$heightPresetSelectedIndex][1]);
  36014. }
  36015. if ($$self.$$.dirty[1] & /*canRenderSizePresets, canRenderWidthPresets, canRenderHeightPresets*/ 29360128) {
  36016. $$invalidate(56, canRenderSizeInputs = !canRenderSizePresets && !canRenderWidthPresets && !canRenderHeightPresets);
  36017. }
  36018. if ($$self.$$.dirty[0] & /*locale, resizeMinSize, resizeMaxSize*/ 805306370 | $$self.$$.dirty[1] & /*redrawTrigger, resizeWillRenderFooter, canRenderSizePresets, sizePresetLabel, $formattedResizeSizePresetOptions, $sizePresetSelectedIndex, canRenderWidthPresets, widthPresetLabel, $formattedResizeWidthPresetOptions, $widthPresetSelectedIndex, canRenderHeightPresets, heightPresetLabel, $formattedResizeHeightPresetOptions, $heightPresetSelectedIndex, canRenderSizeInputs, height, $imageCropRectAspectRatio, $imageCropRect, width, activeField, maintainAspectRatio, $iconActiveFraction, $env*/ 268413948) {
  36019. $$invalidate(3, tools = redrawTrigger && resizeWillRenderFooter(
  36020. [
  36021. canRenderSizePresets && [
  36022. "Dropdown",
  36023. "size-presets",
  36024. {
  36025. label: sizePresetLabel,
  36026. options: $formattedResizeSizePresetOptions,
  36027. onchange: item => setImageOutputSizeWithArray(item.value),
  36028. selectedIndex: $sizePresetSelectedIndex
  36029. }
  36030. ],
  36031. canRenderWidthPresets && [
  36032. "Dropdown",
  36033. "width-presets",
  36034. {
  36035. label: widthPresetLabel,
  36036. options: $formattedResizeWidthPresetOptions,
  36037. onchange: item => {
  36038. $$invalidate(35, width = item.value);
  36039. handleSubmit();
  36040. },
  36041. selectedIndex: $widthPresetSelectedIndex
  36042. }
  36043. ],
  36044. canRenderWidthPresets && canRenderHeightPresets && [
  36045. "span",
  36046. "times",
  36047. {
  36048. class: "PinturaResizeLabel",
  36049. innerHTML: "&times;"
  36050. }
  36051. ],
  36052. canRenderHeightPresets && [
  36053. "Dropdown",
  36054. "height-presets",
  36055. {
  36056. label: heightPresetLabel,
  36057. options: $formattedResizeHeightPresetOptions,
  36058. onchange: item => {
  36059. $$invalidate(36, height = item.value);
  36060. handleSubmit();
  36061. },
  36062. selectedIndex: $heightPresetSelectedIndex
  36063. }
  36064. ],
  36065. canRenderSizeInputs && [
  36066. DimensionInput,
  36067. "width-input",
  36068. {
  36069. id: `width-${formId}`,
  36070. title: locale.resizeTitleInputWidth,
  36071. label: locale.resizeLabelInputWidth,
  36072. placeholder: getWidthPlaceholder(formatValue(height), $imageCropRectAspectRatio, $imageCropRect),
  36073. value: width,
  36074. state: getState(formatValue(width), "width", activeField, resizeMinSize, resizeMaxSize),
  36075. onchange: value => {
  36076. $$invalidate(35, width = value);
  36077. syncFields();
  36078. }
  36079. }
  36080. ],
  36081. canRenderSizeInputs && [
  36082. DimensionLock,
  36083. "aspect-ratio-lock",
  36084. {
  36085. id: `aspect-ratio-lock-${formId}`,
  36086. title: locale.resizeTitleButtonMaintainAspectRatio,
  36087. icon: isString(locale.resizeIconButtonMaintainAspectRatio)
  36088. ? locale.resizeIconButtonMaintainAspectRatio
  36089. : locale.resizeIconButtonMaintainAspectRatio(maintainAspectRatio, $iconActiveFraction),
  36090. locked: maintainAspectRatio,
  36091. onchange: locked => {
  36092. $$invalidate(34, maintainAspectRatio = locked);
  36093. syncFields();
  36094. }
  36095. }
  36096. ],
  36097. canRenderSizeInputs && [
  36098. DimensionInput,
  36099. "height-input",
  36100. {
  36101. id: `height-${formId}`,
  36102. title: locale.resizeTitleInputHeight,
  36103. label: locale.resizeLabelInputHeight,
  36104. placeholder: getHeightPlaceholder(formatValue(width), $imageCropRectAspectRatio, $imageCropRect),
  36105. value: height,
  36106. state: getState(formatValue(height), "height", activeField, resizeMinSize, resizeMaxSize),
  36107. onchange: value => {
  36108. $$invalidate(36, height = value);
  36109. syncFields();
  36110. }
  36111. }
  36112. ]
  36113. ].filter(Boolean),
  36114. { ...$env },
  36115. () => $$invalidate(38, redrawTrigger = {})
  36116. ).filter(Boolean));
  36117. }
  36118. if ($$self.$$.dirty[1] & /*maintainAspectRatio*/ 8) {
  36119. iconActiveFraction.set(maintainAspectRatio ? 1 : 0);
  36120. }
  36121. if ($$self.$$.dirty[1] & /*activeField*/ 64) {
  36122. if (activeField) lastActiveField = activeField;
  36123. }
  36124. if ($$self.$$.dirty[1] & /*$animation, $isActive*/ 805306368) {
  36125. $animation && footerOffset.set($isActive ? 0 : 20);
  36126. }
  36127. if ($$self.$$.dirty[1] & /*$footerOffset*/ 1073741824) {
  36128. $$invalidate(4, footerStyle = $footerOffset
  36129. ? `transform: translateY(${$footerOffset}px)`
  36130. : undefined);
  36131. }
  36132. };
  36133. return [
  36134. isActive,
  36135. locale,
  36136. fieldsGroup,
  36137. tools,
  36138. footerStyle,
  36139. iconActiveFraction,
  36140. animation,
  36141. imageSize,
  36142. imageCropRect,
  36143. imageCropRectAspectRatio,
  36144. imageCropAspectRatio,
  36145. imageOutputSize,
  36146. env,
  36147. handleFocusIn,
  36148. handleFocusOut,
  36149. handleSubmit,
  36150. formattedResizeSizePresetOptions,
  36151. formattedResizeSizePresetOptionsFlattened,
  36152. formattedResizeWidthPresetOptions,
  36153. formattedResizeWidthPresetOptionsFlattened,
  36154. formattedResizeHeightPresetOptions,
  36155. formattedResizeHeightPresetOptionsFlattened,
  36156. sizePresetSelectedIndex,
  36157. widthPresetSelectedIndex,
  36158. heightPresetSelectedIndex,
  36159. footerOffset,
  36160. name,
  36161. stores,
  36162. resizeMinSize,
  36163. resizeMaxSize,
  36164. resizeSizePresetOptions,
  36165. resizeWidthPresetOptions,
  36166. resizeHeightPresetOptions,
  36167. resizeWillRenderFooter,
  36168. maintainAspectRatio,
  36169. width,
  36170. height,
  36171. activeField,
  36172. redrawTrigger,
  36173. $imageCropRectAspectRatio,
  36174. $formattedResizeSizePresetOptions,
  36175. $formattedResizeSizePresetOptionsFlattened,
  36176. $formattedResizeWidthPresetOptions,
  36177. $formattedResizeWidthPresetOptionsFlattened,
  36178. $formattedResizeHeightPresetOptions,
  36179. $formattedResizeHeightPresetOptionsFlattened,
  36180. sizePresetLabel,
  36181. $sizePresetSelectedIndex,
  36182. widthPresetLabel,
  36183. $widthPresetSelectedIndex,
  36184. heightPresetLabel,
  36185. $heightPresetSelectedIndex,
  36186. $imageCropRect,
  36187. canRenderSizePresets,
  36188. canRenderWidthPresets,
  36189. canRenderHeightPresets,
  36190. canRenderSizeInputs,
  36191. $iconActiveFraction,
  36192. $env,
  36193. $animation,
  36194. $isActive,
  36195. $footerOffset,
  36196. div0_binding,
  36197. measure_handler
  36198. ];
  36199. }
  36200. class Resize extends SvelteComponent {
  36201. constructor(options) {
  36202. super();
  36203. init(
  36204. this,
  36205. options,
  36206. instance$2,
  36207. create_fragment$2,
  36208. safe_not_equal,
  36209. {
  36210. name: 26,
  36211. isActive: 0,
  36212. stores: 27,
  36213. locale: 1,
  36214. resizeMinSize: 28,
  36215. resizeMaxSize: 29,
  36216. resizeSizePresetOptions: 30,
  36217. resizeWidthPresetOptions: 31,
  36218. resizeHeightPresetOptions: 32,
  36219. resizeWillRenderFooter: 33
  36220. },
  36221. [-1, -1, -1]
  36222. );
  36223. }
  36224. get name() {
  36225. return this.$$.ctx[26];
  36226. }
  36227. get isActive() {
  36228. return this.$$.ctx[0];
  36229. }
  36230. set isActive(isActive) {
  36231. this.$set({ isActive });
  36232. flush();
  36233. }
  36234. get stores() {
  36235. return this.$$.ctx[27];
  36236. }
  36237. set stores(stores) {
  36238. this.$set({ stores });
  36239. flush();
  36240. }
  36241. get locale() {
  36242. return this.$$.ctx[1];
  36243. }
  36244. set locale(locale) {
  36245. this.$set({ locale });
  36246. flush();
  36247. }
  36248. get resizeMinSize() {
  36249. return this.$$.ctx[28];
  36250. }
  36251. set resizeMinSize(resizeMinSize) {
  36252. this.$set({ resizeMinSize });
  36253. flush();
  36254. }
  36255. get resizeMaxSize() {
  36256. return this.$$.ctx[29];
  36257. }
  36258. set resizeMaxSize(resizeMaxSize) {
  36259. this.$set({ resizeMaxSize });
  36260. flush();
  36261. }
  36262. get resizeSizePresetOptions() {
  36263. return this.$$.ctx[30];
  36264. }
  36265. set resizeSizePresetOptions(resizeSizePresetOptions) {
  36266. this.$set({ resizeSizePresetOptions });
  36267. flush();
  36268. }
  36269. get resizeWidthPresetOptions() {
  36270. return this.$$.ctx[31];
  36271. }
  36272. set resizeWidthPresetOptions(resizeWidthPresetOptions) {
  36273. this.$set({ resizeWidthPresetOptions });
  36274. flush();
  36275. }
  36276. get resizeHeightPresetOptions() {
  36277. return this.$$.ctx[32];
  36278. }
  36279. set resizeHeightPresetOptions(resizeHeightPresetOptions) {
  36280. this.$set({ resizeHeightPresetOptions });
  36281. flush();
  36282. }
  36283. get resizeWillRenderFooter() {
  36284. return this.$$.ctx[33];
  36285. }
  36286. set resizeWillRenderFooter(resizeWillRenderFooter) {
  36287. this.$set({ resizeWillRenderFooter });
  36288. flush();
  36289. }
  36290. }
  36291. // @ts-ignore
  36292. var _plugin_resize = { util: ['resize', Resize] };
  36293. /* src/core/ui/plugins/redact/index.svelte generated by Svelte v3.37.0 */
  36294. function create_fragment$1(ctx) {
  36295. let shapeutil;
  36296. let current;
  36297. shapeutil = new ShapeUtil({
  36298. props: {
  36299. stores: /*stores*/ ctx[3],
  36300. locale: /*locale*/ ctx[4],
  36301. isActive: /*isActive*/ ctx[0],
  36302. isActiveFraction: /*isActiveFraction*/ ctx[1],
  36303. isVisible: /*isVisible*/ ctx[2],
  36304. mapScreenPointToImagePoint: /*mapScreenPointToImagePoint*/ ctx[15],
  36305. mapImagePointToScreenPoint: /*mapImagePointToScreenPoint*/ ctx[16],
  36306. utilKey: "redact",
  36307. imageRotation: /*$imageRotation*/ ctx[7],
  36308. imageFlipX: /*$imageFlipX*/ ctx[5],
  36309. imageFlipY: /*$imageFlipY*/ ctx[6],
  36310. shapes: /*imageRedaction*/ ctx[8],
  36311. tools: ["rect"],
  36312. toolShapes: {
  36313. rectangle: [{ x: 0, y: 0, width: 0, height: 0 }]
  36314. },
  36315. toolActive: "rectangle",
  36316. parentRect: /*imageSize*/ ctx[10],
  36317. enablePresetDropImage: false,
  36318. enablePresetSelectImage: false,
  36319. hooks: {
  36320. willRenderShapeControls: /*func*/ ctx[18]
  36321. }
  36322. }
  36323. });
  36324. shapeutil.$on("measure", /*measure_handler*/ ctx[19]);
  36325. return {
  36326. c() {
  36327. create_component(shapeutil.$$.fragment);
  36328. },
  36329. m(target, anchor) {
  36330. mount_component(shapeutil, target, anchor);
  36331. current = true;
  36332. },
  36333. p(ctx, [dirty]) {
  36334. const shapeutil_changes = {};
  36335. if (dirty & /*stores*/ 8) shapeutil_changes.stores = /*stores*/ ctx[3];
  36336. if (dirty & /*locale*/ 16) shapeutil_changes.locale = /*locale*/ ctx[4];
  36337. if (dirty & /*isActive*/ 1) shapeutil_changes.isActive = /*isActive*/ ctx[0];
  36338. if (dirty & /*isActiveFraction*/ 2) shapeutil_changes.isActiveFraction = /*isActiveFraction*/ ctx[1];
  36339. if (dirty & /*isVisible*/ 4) shapeutil_changes.isVisible = /*isVisible*/ ctx[2];
  36340. if (dirty & /*$imageRotation*/ 128) shapeutil_changes.imageRotation = /*$imageRotation*/ ctx[7];
  36341. if (dirty & /*$imageFlipX*/ 32) shapeutil_changes.imageFlipX = /*$imageFlipX*/ ctx[5];
  36342. if (dirty & /*$imageFlipY*/ 64) shapeutil_changes.imageFlipY = /*$imageFlipY*/ ctx[6];
  36343. shapeutil.$set(shapeutil_changes);
  36344. },
  36345. i(local) {
  36346. if (current) return;
  36347. transition_in(shapeutil.$$.fragment, local);
  36348. current = true;
  36349. },
  36350. o(local) {
  36351. transition_out(shapeutil.$$.fragment, local);
  36352. current = false;
  36353. },
  36354. d(detaching) {
  36355. destroy_component(shapeutil, detaching);
  36356. }
  36357. };
  36358. }
  36359. function instance$1($$self, $$props, $$invalidate) {
  36360. let $rootRect;
  36361. let $imageSize;
  36362. let $imageTransforms;
  36363. let $imageFlipX;
  36364. let $imageFlipY;
  36365. let $imageRotation;
  36366. const name = "redact";
  36367. let { isActive } = $$props;
  36368. let { isActiveFraction } = $$props;
  36369. let { isVisible } = $$props;
  36370. let { stores } = $$props;
  36371. let { locale = {} } = $$props;
  36372. // connect filter choice to stores
  36373. const { imageRedaction, rootRect, imageSize, imageTransforms, imageRotation, imageFlipX, imageFlipY } = stores;
  36374. component_subscribe($$self, rootRect, value => $$invalidate(20, $rootRect = value));
  36375. component_subscribe($$self, imageSize, value => $$invalidate(21, $imageSize = value));
  36376. component_subscribe($$self, imageTransforms, value => $$invalidate(22, $imageTransforms = value));
  36377. component_subscribe($$self, imageRotation, value => $$invalidate(7, $imageRotation = value));
  36378. component_subscribe($$self, imageFlipX, value => $$invalidate(5, $imageFlipX = value));
  36379. component_subscribe($$self, imageFlipY, value => $$invalidate(6, $imageFlipY = value));
  36380. //
  36381. // Mapping coordinates
  36382. //
  36383. const mapScreenPointToImagePoint = point => _mapScreenPointToImagePoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY);
  36384. const mapImagePointToScreenPoint = point => _mapImagePointToScreenPoint(point, $rootRect, $imageSize, $imageTransforms.origin, $imageTransforms.translation, $imageTransforms.rotation.z, $imageTransforms.scale, $imageFlipX, $imageFlipY);
  36385. const func = controls => {
  36386. const children = getNodeChildren(controls[0]);
  36387. removeNode("to-front", children);
  36388. return controls;
  36389. };
  36390. function measure_handler(event) {
  36391. bubble($$self, event);
  36392. }
  36393. $$self.$$set = $$props => {
  36394. if ("isActive" in $$props) $$invalidate(0, isActive = $$props.isActive);
  36395. if ("isActiveFraction" in $$props) $$invalidate(1, isActiveFraction = $$props.isActiveFraction);
  36396. if ("isVisible" in $$props) $$invalidate(2, isVisible = $$props.isVisible);
  36397. if ("stores" in $$props) $$invalidate(3, stores = $$props.stores);
  36398. if ("locale" in $$props) $$invalidate(4, locale = $$props.locale);
  36399. };
  36400. return [
  36401. isActive,
  36402. isActiveFraction,
  36403. isVisible,
  36404. stores,
  36405. locale,
  36406. $imageFlipX,
  36407. $imageFlipY,
  36408. $imageRotation,
  36409. imageRedaction,
  36410. rootRect,
  36411. imageSize,
  36412. imageTransforms,
  36413. imageRotation,
  36414. imageFlipX,
  36415. imageFlipY,
  36416. mapScreenPointToImagePoint,
  36417. mapImagePointToScreenPoint,
  36418. name,
  36419. func,
  36420. measure_handler
  36421. ];
  36422. }
  36423. class Redact extends SvelteComponent {
  36424. constructor(options) {
  36425. super();
  36426. init(this, options, instance$1, create_fragment$1, safe_not_equal, {
  36427. name: 17,
  36428. isActive: 0,
  36429. isActiveFraction: 1,
  36430. isVisible: 2,
  36431. stores: 3,
  36432. locale: 4
  36433. });
  36434. }
  36435. get name() {
  36436. return this.$$.ctx[17];
  36437. }
  36438. get isActive() {
  36439. return this.$$.ctx[0];
  36440. }
  36441. set isActive(isActive) {
  36442. this.$set({ isActive });
  36443. flush();
  36444. }
  36445. get isActiveFraction() {
  36446. return this.$$.ctx[1];
  36447. }
  36448. set isActiveFraction(isActiveFraction) {
  36449. this.$set({ isActiveFraction });
  36450. flush();
  36451. }
  36452. get isVisible() {
  36453. return this.$$.ctx[2];
  36454. }
  36455. set isVisible(isVisible) {
  36456. this.$set({ isVisible });
  36457. flush();
  36458. }
  36459. get stores() {
  36460. return this.$$.ctx[3];
  36461. }
  36462. set stores(stores) {
  36463. this.$set({ stores });
  36464. flush();
  36465. }
  36466. get locale() {
  36467. return this.$$.ctx[4];
  36468. }
  36469. set locale(locale) {
  36470. this.$set({ locale });
  36471. flush();
  36472. }
  36473. }
  36474. // @ts-ignore
  36475. var _plugin_redact = { util: ['redact', Redact] };
  36476. const IconCross =
  36477. '<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M18 6L6 18M6 6l12 12"></path></path></g>';
  36478. const CharacterA =
  36479. '<path fill="none" d="M9 15 L12 9 L15 15 M10 13.5 h3" stroke="currentColor" stroke-width=".125em"/>';
  36480. var _locale_en_gb = {
  36481. // generic
  36482. labelReset: 'Reset',
  36483. labelDefault: 'Default',
  36484. labelAuto: 'Auto',
  36485. labelNone: 'None',
  36486. labelEdit: 'Edit',
  36487. labelClose: 'Close',
  36488. labelSupportError: (features) => `${features.join(', ')} not supported on this browser`,
  36489. // defaults
  36490. labelColor: 'Color',
  36491. labelWidth: 'Width',
  36492. labelSize: 'Size',
  36493. labelOffset: 'Offset',
  36494. labelAmount: 'Amount',
  36495. labelInset: 'Inset',
  36496. labelRadius: 'Radius',
  36497. // sizes
  36498. labelSizeExtraSmall: 'Extra small',
  36499. labelSizeSmall: 'Small',
  36500. labelSizeMediumSmall: 'Medium small',
  36501. labelSizeMedium: 'Medium',
  36502. labelSizeMediumLarge: 'Medium large',
  36503. labelSizeLarge: 'Large',
  36504. labelSizeExtraLarge: 'Extra large',
  36505. // unused?
  36506. labelButtonRevert: 'Revert',
  36507. labelButtonCancel: 'Cancel',
  36508. labelButtonUndo: 'Undo',
  36509. labelButtonRedo: 'Redo',
  36510. labelButtonExport: 'Done',
  36511. iconSupportError: `<g fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><g><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></g>`,
  36512. iconButtonClose: IconCross,
  36513. iconButtonRevert: `<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M7.388 18.538a8 8 0 10-2.992-9.03"/><path fill="currentColor" d="M2.794 11.696L2.37 6.714l5.088 3.18z"/><path d="M12 8v4M12 12l4 2"/></g>`,
  36514. iconButtonUndo: `<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M10 8h4c2.485 0 5 2 5 5s-2.515 5-5 5h-4"/><path fill="currentColor" d="M5 8l4-3v6z"/></g>`,
  36515. iconButtonRedo: `<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M14 8h-4c-2.485 0-5 2-5 5s2.515 5 5 5h4"/><path fill="currentColor" d="M19 8l-4-3v6z"/></g>`,
  36516. iconButtonExport: `<polyline points="20 6 9 17 4 12" fill="none" stroke="currentColor" stroke-width=".125em"></polyline>`,
  36517. // status
  36518. statusLabelButtonClose: 'Close',
  36519. statusIconButtonClose: IconCross,
  36520. statusLabelLoadImage: (state) => {
  36521. if (!state || !state.task) return 'Waiting for image';
  36522. if (state.error)
  36523. return state.error.code === 'IMAGE_TOO_SMALL'
  36524. ? 'Minimum image size is {minWidth} × {minHeight}'
  36525. : 'Error loading image';
  36526. if (state.task === 'blob-to-bitmap') return 'Creating preview…';
  36527. return 'Loading image…';
  36528. },
  36529. // processing status message
  36530. statusLabelProcessImage: (state) => {
  36531. if (!state || !state.task) return undefined;
  36532. if (state.task === 'store') {
  36533. if (state.error) return 'Error uploading image';
  36534. return 'Uploading image…';
  36535. }
  36536. if (state.error) return 'Error processing image';
  36537. return 'Processing image…';
  36538. },
  36539. };
  36540. const MarkupEditor = {
  36541. shapeLabelButtonSelectSticker: 'Select image',
  36542. shapeIconButtonSelectSticker: `<g fill="none" stroke="currentColor" stroke-width="0.0625em"><path d="M8 21 L15 11 L19 15"/><path d="M15 2 v5 h5"/><path d="M8 2 h8 l4 4 v12 q0 4 -4 4 h-8 q-4 0 -4 -4 v-12 q0 -4 4 -4z"/></g><circle fill="currentColor" cx="10" cy="8" r="1.5"/>`,
  36543. shapeIconButtonFlipHorizontal: `<g stroke="currentColor" stroke-width=".125em"><path fill="none" d="M6 6.5h5v11H6z"/><path fill="currentColor" d="M15 6.5h3v11h-3z"/><path d="M11 4v16" fill="currentColor"/></g>`,
  36544. shapeIconButtonFlipVertical: `<g stroke="currentColor" stroke-width=".125em"><rect x="7" y="8" width="11" height="5" fill="none"/><rect x="7" y="17" width="11" height="2" fill="currentColor"/><line x1="5" y1="13" x2="20" y2="13"/></g>`,
  36545. shapeIconButtonRemove: `<g fill="none" fill-rule="evenodd"><path stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7.5 7h9z"/><path d="M7.916 9h8.168a1 1 0 01.99 1.14l-.972 6.862a2 2 0 01-1.473 1.653c-.877.23-1.753.345-2.629.345-.876 0-1.752-.115-2.628-.345a2 2 0 01-1.473-1.653l-.973-6.862A1 1 0 017.916 9z" fill="currentColor"/><rect fill="currentColor" x="10" y="5" width="4" height="3" rx="1"/></g>`,
  36546. shapeIconButtonDuplicate: `<g fill="none" fill-rule="evenodd"><path d="M15 13.994V16a2 2 0 01-2 2H8a2 2 0 01-2-2v-5a2 2 0 012-2h2.142" stroke="currentColor" stroke-width=".125em"/><path d="M15 9V8a1 1 0 00-2 0v1h-1a1 1 0 000 2h1v1a1 1 0 002 0v-1h1a1 1 0 000-2h-1zm-4-4h6a2 2 0 012 2v6a2 2 0 01-2 2h-6a2 2 0 01-2-2V7a2 2 0 012-2z" fill="currentColor"/></g>`,
  36547. shapeIconButtonMoveToFront: `<g fill="none" fill-rule="evenodd"><rect fill="currentColor" x="11" y="13" width="8" height="2" rx="1"/><rect fill="currentColor" x="9" y="17" width="10" height="2" rx="1"/><path d="M11.364 8H10a5 5 0 000 10M12 6.5L14.5 8 12 9.5z" stroke="currentColor" stroke-width=".125em" stroke-linecap="round"/></g>`,
  36548. shapeIconButtonTextLayoutAutoWidth: `${CharacterA}`,
  36549. shapeIconButtonTextLayoutAutoHeight: `<g fill="currentColor"><circle cx="4" cy="12" r="1.5"/><circle cx="20" cy="12" r="1.5"/></g>${CharacterA}`,
  36550. shapeIconButtonTextLayoutFixedSize: `<g fill="currentColor"><circle cx="5" cy="6" r="1.5"/><circle cx="19" cy="6" r="1.5"/><circle cx="19" cy="19" r="1.5"/><circle cx="5" cy="19" r="1.5"/></g>${CharacterA}`,
  36551. shapeTitleButtonTextLayoutAutoWidth: 'Auto width',
  36552. shapeTitleButtonTextLayoutAutoHeight: 'Auto height',
  36553. shapeTitleButtonTextLayoutFixedSize: 'Fixed size',
  36554. shapeTitleButtonFlipHorizontal: 'Flip Horizontal',
  36555. shapeTitleButtonFlipVertical: 'Flip Vertical',
  36556. shapeTitleButtonRemove: 'Remove',
  36557. shapeTitleButtonDuplicate: 'Duplicate',
  36558. shapeTitleButtonMoveToFront: 'Move to front',
  36559. shapeLabelInputText: 'Edit text',
  36560. shapeIconInputCancel: `<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M18 6L6 18M6 6l12 12"/></g>`,
  36561. shapeIconInputConfirm: `<g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><polyline points="20 6 9 17 4 12"/></g>`,
  36562. shapeLabelInputCancel: 'Cancel',
  36563. shapeLabelInputConfirm: 'Confirm',
  36564. shapeLabelStrokeNone: 'No outline',
  36565. shapeLabelFontStyleNormal: 'Normal',
  36566. shapeLabelFontStyleBold: 'Bold',
  36567. shapeLabelFontStyleItalic: 'Italic',
  36568. shapeLabelFontStyleItalicBold: 'Bold Italic',
  36569. shapeTitleBackgroundColor: 'Fill color',
  36570. shapeTitleFontFamily: 'Font',
  36571. shapeTitleFontSize: 'Font size',
  36572. shapeTitleFontStyle: 'Font style',
  36573. shapeTitleLineHeight: 'Leading',
  36574. shapeTitleLineStart: 'Start',
  36575. shapeTitleLineEnd: 'End',
  36576. shapeTitleStrokeWidth: 'Line width',
  36577. shapeTitleStrokeColor: 'Line color',
  36578. shapeTitleLineDecorationBar: 'Bar',
  36579. shapeTitleLineDecorationCircle: 'Circle',
  36580. shapeTitleLineDecorationSquare: 'Square',
  36581. shapeTitleLineDecorationArrow: 'Arrow',
  36582. shapeTitleLineDecorationCircleSolid: 'Circle solid',
  36583. shapeTitleLineDecorationSquareSolid: 'Square solid',
  36584. shapeTitleLineDecorationArrowSolid: 'Arrow solid',
  36585. shapeIconLineDecorationBar: `<g stroke="currentColor" stroke-linecap="round" stroke-width=".125em"><path d="M5,12 H16"/><path d="M16,8 V16"/></g>`,
  36586. shapeIconLineDecorationCircle: `<g stroke="currentColor" stroke-linecap="round"><path stroke-width=".125em" d="M5,12 H12"/><circle fill="none" stroke-width=".125em" cx="16" cy="12" r="4"/></g>`,
  36587. shapeIconLineDecorationSquare: `<g stroke="currentColor" stroke-linecap="round"><path stroke-width=".125em" d="M5,12 H12"/><rect fill="none" stroke-width=".125em" x="12" y="8" width="8" height="8"/></g>`,
  36588. shapeIconLineDecorationArrow: `<g stroke="currentColor" stroke-linecap="round" stroke-width=".125em"><path d="M5,12 H16 M13,7 l6,5 l-6,5" fill="none"/></g>`,
  36589. shapeIconLineDecorationCircleSolid: `<g stroke="currentColor" stroke-linecap="round"><path stroke-width=".125em" d="M5,12 H12"/><circle fill="currentColor" cx="16" cy="12" r="4"/></g>`,
  36590. shapeIconLineDecorationSquareSolid: `<g stroke="currentColor" stroke-linecap="round"><path stroke-width=".125em" d="M5,12 H12"/><rect fill="currentColor" x="12" y="8" width="8" height="8"/></g>`,
  36591. shapeIconLineDecorationArrowSolid: `<g stroke="currentColor" stroke-linecap="round" stroke-width=".125em"><path d="M5,12 H16"/><path d="M13,7 l6,5 l-6,5z" fill="currentColor"/></g>`,
  36592. shapeTitleColorTransparent: 'Transparent',
  36593. shapeTitleColorWhite: 'White',
  36594. shapeTitleColorSilver: 'Silver',
  36595. shapeTitleColorGray: 'Gray',
  36596. shapeTitleColorBlack: 'Black',
  36597. shapeTitleColorNavy: 'Navy',
  36598. shapeTitleColorBlue: 'Blue',
  36599. shapeTitleColorAqua: 'Aqua',
  36600. shapeTitleColorTeal: 'Teal',
  36601. shapeTitleColorOlive: 'Olive',
  36602. shapeTitleColorGreen: 'Green',
  36603. shapeTitleColorYellow: 'Yellow',
  36604. shapeTitleColorOrange: 'Orange',
  36605. shapeTitleColorRed: 'Red',
  36606. shapeTitleColorMaroon: 'Maroon',
  36607. shapeTitleColorFuchsia: 'Fuchsia',
  36608. shapeTitleColorPurple: 'Purple',
  36609. shapeTitleTextColor: 'Font color',
  36610. shapeTitleTextAlign: 'Text align',
  36611. shapeTitleTextAlignLeft: 'Left align text',
  36612. shapeTitleTextAlignCenter: 'Center align text',
  36613. shapeTitleTextAlignRight: 'Right align text',
  36614. shapeIconTextAlignLeft: `<g stroke-width=".125em" stroke="currentColor"><line x1="5" y1="8" x2="15" y2="8"/><line x1="5" y1="12" x2="19" y2="12"/><line x1="5" y1="16" x2="14" y2="16"/></g>`,
  36615. shapeIconTextAlignCenter: `<g stroke-width=".125em" stroke="currentColor"><line x1="7" y1="8" x2="17" y2="8"/><line x1="5" y1="12" x2="19" y2="12"/><line x1="8" y1="16" x2="16" y2="16"/></g>`,
  36616. shapeIconTextAlignRight: `<g stroke-width=".125em" stroke="currentColor"><line x1="9" y1="8" x2="19" y2="8"/><line x1="5" y1="12" x2="19" y2="12"/><line x1="11" y1="16" x2="19" y2="16"/></g>`,
  36617. shapeLabelToolSharpie: 'Sharpie',
  36618. shapeLabelToolEraser: 'Eraser',
  36619. shapeLabelToolRectangle: 'Rectangle',
  36620. shapeLabelToolEllipse: 'Ellipse',
  36621. shapeLabelToolArrow: 'Arrow',
  36622. shapeLabelToolLine: 'Line',
  36623. shapeLabelToolText: 'Text',
  36624. shapeLabelToolPreset: 'Stickers',
  36625. shapeIconToolSharpie: `<g stroke-width=".125em" stroke="currentColor" fill="none"><path d="M2.025 5c5.616-2.732 8.833-3.857 9.65-3.374C12.903 2.351.518 12.666 2.026 14 3.534 15.334 16.536.566 17.73 2.566 18.924 4.566 3.98 17.187 4.831 18c.851.813 9.848-6 11.643-6 1.087 0-2.53 5.11-2.92 7-.086.41 3.323-1.498 4.773-1 .494.17.64 2.317 1.319 3 .439.443 1.332.776 2.679 1" stroke="currentColor" stroke-width=".125em" fill="none" fill-rule="evenodd" stroke-linejoin="round"/></g>`,
  36626. shapeIconToolEraser: `<g stroke-width=".125em" stroke="currentColor" stroke-linecap="round" fill="none"><g transform="translate(3, 15) rotate(-45)"><rect x="0" y="0" width="18" height="10" rx="3"/></g><line x1="11" y1="21" x2="18" y2="21"/><line x1="20" y1="21" x2="22" y2="21"/></g>`,
  36627. shapeIconToolRectangle: `<g stroke-width=".125em" stroke="currentColor" fill="none"><rect x="2" y="2" width="20" height="20" rx="3"/></g>`,
  36628. shapeIconToolEllipse: `<g stroke-width=".125em" stroke="currentColor" fill="none"><circle cx="12" cy="12" r="11"/></g>`,
  36629. shapeIconToolArrow: `<g stroke-width=".125em" stroke="currentColor" fill="none"><line x1="20" y1="3" x2="6" y2="21"/><path d="m10 5 L22 1 L21 13" fill="currentColor" stroke="none"/></g>`,
  36630. shapeIconToolLine: `<g stroke-width=".125em" stroke="currentColor" fill="none"><line x1="20" y1="3" x2="6" y2="21"/></g>`,
  36631. shapeIconToolText: `<g stroke="none" fill="currentColor" transform="translate(6,0)"><path d="M8.14 20.085c.459 0 .901-.034 1.329-.102a8.597 8.597 0 001.015-.21v1.984c-.281.135-.695.247-1.242.336a9.328 9.328 0 01-1.477.133c-3.312 0-4.968-1.745-4.968-5.235V6.804H.344v-1.25l2.453-1.078L3.89.819h1.5v3.97h4.97v2.015H5.39v10.078c0 1.031.245 1.823.735 2.375s1.161.828 2.015.828z"/>`,
  36632. shapeIconToolPreset: `<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M12 22c2.773 0 1.189-5.177 3-7 1.796-1.808 7-.25 7-3 0-5.523-4.477-10-10-10S2 6.477 2 12s4.477 10 10 10z"></path><path d="M20 17c-3 3-5 5-8 5"></path></g>`,
  36633. };
  36634. var _plugin_crop_locale_en_gb = {
  36635. cropLabel: 'Crop',
  36636. cropIcon:
  36637. '<g stroke-width=".125em" stroke="currentColor" fill="none"><path d="M23 17H9a2 2 0 0 1-2-2v-5m0-3V1 M1 7h14a2 2 0 0 1 2 2v7m0 4v3"/></g>',
  36638. cropIconButtonRecenter: `<path stroke="currentColor" fill="none" stroke-width="2" stroke-linejoin="bevel" d="M1.5 7.5v-6h6M1.5 16.5v6h6M22.5 16.5v6h-6M22.5 7.5v-6h-6"/><circle cx="12" cy="12" r="3.5" fill="currentColor" stroke="none"/>`,
  36639. cropIconButtonRotateLeft:
  36640. '<g stroke="none" fill="currentColor"><path fill="none" d="M-1-1h582v402H-1z"/><rect x="3" rx="1" height="12" width="12" y="9"/><path d="M15 5h-1a5 5 0 015 5 1 1 0 002 0 7 7 0 00-7-7h-1.374l.747-.747A1 1 0 0011.958.84L9.603 3.194a1 1 0 000 1.415l2.355 2.355a1 1 0 001.415-1.414l-.55-.55H15z"/></g>',
  36641. cropIconButtonRotateRight:
  36642. '<g stroke="none" fill="currentColor"><path fill="none" d="M-1-1h582v402H-1z"/><path d="M11.177 5H10a5 5 0 00-5 5 1 1 0 01-2 0 7 7 0 017-7h1.374l-.747-.747A1 1 0 0112.042.84l2.355 2.355a1 1 0 010 1.415l-2.355 2.354a1 1 0 01-1.415-1.414l.55-.55z"/><rect rx="1" height="12" width="12" y="9" x="9"/></g>',
  36643. cropIconButtonFlipVertical:
  36644. '<g stroke="none" fill="currentColor"><path d="M19.993 12.143H7a1 1 0 0 1-1-1V5.994a1 1 0 0 1 1.368-.93l12.993 5.15a1 1 0 0 1-.368 1.93z"/><path d="M19.993 14a1 1 0 0 1 .368 1.93L7.368 21.078A1 1 0 0 1 6 20.148V15a1 1 0 0 1 1-1h12.993z" opacity=".6"/></g>',
  36645. cropIconButtonFlipHorizontal:
  36646. '<g stroke="none" fill="currentColor"><path d="M11.93 7.007V20a1 1 0 0 1-1 1H5.78a1 1 0 0 1-.93-1.368l5.15-12.993a1 1 0 0 1 1.929.368z"/><path d="M14 7.007V20a1 1 0 0 0 1 1h5.149a1 1 0 0 0 .93-1.368l-5.15-12.993A1 1 0 0 0 14 7.007z" opacity=".6"/></g>',
  36647. cropIconSelectPreset: (locale, aspectRatio) => {
  36648. const [a, b, c] = !aspectRatio
  36649. ? [0.2, 0.3, 0.4]
  36650. : [
  36651. aspectRatio < 1 ? 1 : 0.3,
  36652. aspectRatio === 1 ? 0.85 : 0.5,
  36653. aspectRatio > 1 ? 1 : 0.3,
  36654. ];
  36655. return `<g fill="currentColor">
  36656. <rect opacity="${a}" x="2" y="4" width="10" height="18" rx="1"/>
  36657. <rect opacity="${b}" x="4" y="8" width="14" height="14" rx="1"/>
  36658. <rect opacity="${c}" x="6" y="12" width="17" height="10" rx="1"/>
  36659. </g>`;
  36660. },
  36661. cropIconCropBoundary: (locale, isBoundToImage) => {
  36662. const [a, b, c, d] = isBoundToImage ? [0.3, 1, 0, 0] : [0, 0, 0.3, 1];
  36663. return `<g fill="currentColor">
  36664. <rect opacity="${a}" x="2" y="3" width="20" height="20" rx="1"/>
  36665. <rect opacity="${b}" x="7" y="8" width="10" height="10" rx="1"/>
  36666. <rect opacity="${c}" x="4" y="8" width="14" height="14" rx="1"/>
  36667. <rect opacity="${d}" x="12" y="4" width="10" height="10" rx="1"/>
  36668. </g>`;
  36669. },
  36670. cropLabelButtonRecenter: 'Recenter',
  36671. cropLabelButtonRotateLeft: 'Rotate left',
  36672. cropLabelButtonRotateRight: 'Rotate right',
  36673. cropLabelButtonFlipHorizontal: 'Flip horizontal',
  36674. cropLabelButtonFlipVertical: 'Flip vertical',
  36675. cropLabelSelectPreset: 'Crop shape',
  36676. cropLabelCropBoundary: 'Crop boundary',
  36677. cropLabelCropBoundaryEdge: 'Edge of image',
  36678. cropLabelCropBoundaryNone: 'None',
  36679. cropLabelTabRotation: 'Rotation',
  36680. cropLabelTabZoom: 'Zoom',
  36681. };
  36682. var _plugin_filter_locale_en_gb = {
  36683. filterLabel: 'Filter',
  36684. filterIcon:
  36685. '<g stroke-width=".125em" stroke="currentColor" fill="none"><path d="M18.347 9.907a6.5 6.5 0 1 0-1.872 3.306M3.26 11.574a6.5 6.5 0 1 0 2.815-1.417 M10.15 17.897A6.503 6.503 0 0 0 16.5 23a6.5 6.5 0 1 0-6.183-8.51"/></g>',
  36686. filterLabelChrome: 'Chrome',
  36687. filterLabelFade: 'Fade',
  36688. filterLabelCold: 'Cold',
  36689. filterLabelWarm: 'Warm',
  36690. filterLabelPastel: 'Pastel',
  36691. filterLabelMonoDefault: 'Mono',
  36692. filterLabelMonoNoir: 'Noir',
  36693. filterLabelMonoWash: 'Wash',
  36694. filterLabelMonoStark: 'Stark',
  36695. filterLabelSepiaDefault: 'Sepia',
  36696. filterLabelSepiaBlues: 'Blues',
  36697. filterLabelSepiaRust: 'Rust',
  36698. filterLabelSepiaColor: 'Color',
  36699. };
  36700. var _plugin_finetune_locale_en_gb = {
  36701. finetuneLabel: 'Finetune',
  36702. finetuneIcon:
  36703. '<g stroke-width=".125em" stroke="currentColor" fill="none"><path d="M4 1v5.5m0 3.503V23M12 1v10.5m0 3.5v8M20 1v15.5m0 3.5v3M2 7h4M10 12h4M18 17h4"/></g>',
  36704. finetuneLabelBrightness: 'Brightness',
  36705. finetuneLabelContrast: 'Contrast',
  36706. finetuneLabelSaturation: 'Saturation',
  36707. finetuneLabelExposure: 'Exposure',
  36708. finetuneLabelTemperature: 'Temperature',
  36709. finetuneLabelGamma: 'Gamma',
  36710. finetuneLabelClarity: 'Clarity',
  36711. finetuneLabelVignette: 'Vignette',
  36712. };
  36713. var _plugin_resize_locale_en_gb = {
  36714. resizeLabel: 'Resize',
  36715. resizeIcon:
  36716. '<g stroke-width=".125em" stroke="currentColor" fill="none"><rect x="2" y="12" width="10" height="10" rx="2"/><path d="M4 11.5V4a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5.5"/><path d="M14 10l3.365-3.365M14 6h4v4"/></g>',
  36717. resizeLabelFormCaption: 'Image output size',
  36718. resizeLabelInputWidth: 'w',
  36719. resizeTitleInputWidth: 'Width',
  36720. resizeLabelInputHeight: 'h',
  36721. resizeTitleInputHeight: 'Height',
  36722. resizeTitleButtonMaintainAspectRatio: 'Maintain aspectratio',
  36723. resizeIconButtonMaintainAspectRatio: (active, activeFraction) => `
  36724. <defs>
  36725. <mask id="mask1" x="0" y="0" width="24" height="24" >
  36726. <rect x="0" y="0" width="24" height="10" fill="#fff" stroke="none"/>
  36727. </mask>
  36728. </defs>
  36729. <g fill="none" fill-rule="evenodd">
  36730. <g mask="url(#mask1)">
  36731. <path transform="translate(0 ${
  36732. (activeFraction - 1) * 3
  36733. })" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" d="M9.401 10.205v-.804a2.599 2.599 0 0 1 5.198 0V17"/>
  36734. </g>
  36735. <rect fill="currentColor" x="7" y="10" width="10" height="7" rx="1.5"/>
  36736. </g>
  36737. `,
  36738. };
  36739. var _plugin_decorate_locale_en_gb = {
  36740. decorateLabel: 'Decorate',
  36741. decorateIcon:
  36742. '<g fill="none" fill-rule="evenodd"><path stroke="currentColor" stroke-width=".125em" stroke-linecap="round" stroke-linejoin="round" d="M12 18.5l-6.466 3.4 1.235-7.2-5.23-5.1 7.228-1.05L12 2l3.233 6.55 7.229 1.05-5.231 5.1 1.235 7.2z"/></g>',
  36743. };
  36744. var _plugin_annotate_locale_en_gb = {
  36745. annotateLabel: 'Annotate',
  36746. annotateIcon:
  36747. '<g stroke-width=".125em" stroke="currentColor" fill="none"><path d="M17.086 2.914a2.828 2.828 0 1 1 4 4l-14.5 14.5-5.5 1.5 1.5-5.5 14.5-14.5z"/></g>',
  36748. };
  36749. var _plugin_sticker_locale_en_gb = {
  36750. stickerLabel: 'Sticker',
  36751. stickerIcon:
  36752. '<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em"><path d="M12 22c2.773 0 1.189-5.177 3-7 1.796-1.808 7-.25 7-3 0-5.523-4.477-10-10-10S2 6.477 2 12s4.477 10 10 10z"/><path d="M20 17c-3 3-5 5-8 5"/></g>',
  36753. };
  36754. var _plugin_frame_locale_en_gb = {
  36755. frameLabel: 'Frame',
  36756. frameIcon: `<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em">
  36757. <rect x="2" y="2" width="20" height="20" rx="4"/>
  36758. <rect x="6" y="6" width="12" height="12" rx="1"/>
  36759. </g>`,
  36760. frameLabelMatSharp: 'Mat',
  36761. frameLabelMatRound: 'Bevel',
  36762. frameLabelLineSingle: 'Line',
  36763. frameLabelLineMultiple: 'Zebra',
  36764. frameLabelEdgeSeparate: 'Inset',
  36765. frameLabelEdgeOverlap: 'Plus',
  36766. frameLabelEdgeCross: 'Lumber',
  36767. frameLabelCornerHooks: 'Hook',
  36768. frameLabelPolaroid: 'Polaroid',
  36769. };
  36770. var _plugin_redact_locale_en_gb = {
  36771. redactLabel: 'Redact',
  36772. redactIcon: `<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width=".125em">
  36773. <path d="M 2 7 l 0.1 -.1"/>
  36774. <path d="M 2 12 l 5 -5"/>
  36775. <path d="M 2 17 l 10 -10"/>
  36776. <path d="M 7 17 l 10 -10"/>
  36777. <path d="M 12 17 l 10 -10"/>
  36778. <path d="M 17 17 l 5 -5"/>
  36779. <path d="M 22 17 l .1 -.1"/>
  36780. </g>`,
  36781. };
  36782. var hasDefinedCustomElement = (name) => document.createElement(name).constructor !== HTMLElement;
  36783. var linkAccessors = (destination, origin) => {
  36784. const descriptors = Object.getOwnPropertyDescriptors(destination);
  36785. Object.keys(descriptors).forEach((key) => {
  36786. // props, set new setter and getter
  36787. if (!!descriptors[key]['get']) {
  36788. Object.defineProperty(origin, key, {
  36789. get: () => destination[key],
  36790. set: (value) => (destination[key] = value),
  36791. });
  36792. }
  36793. // method, copy reference
  36794. else {
  36795. origin[key] = destination[key];
  36796. }
  36797. });
  36798. };
  36799. var hasDoctype = () => isBrowser() && document.doctype !== null;
  36800. var initEditorView = (target) => {
  36801. const accessors = {};
  36802. const { sub, pub } = pubsub();
  36803. // catch missing doctype
  36804. if (!hasDoctype())
  36805. console.warn('Browser is in quirks mode, add <!DOCTYPE html> to page to fix render issues');
  36806. // create editor core
  36807. const core = createImageEditor();
  36808. linkAccessors(core, accessors);
  36809. // create editor view
  36810. const view = attachEditorView(target, core.stores);
  36811. linkAccessors(view, accessors);
  36812. // listen for UI interaction and link to editor API (internals)
  36813. const unsubs = ['loadImage', 'processImage', 'abortProcessImage', 'abortLoadImage'].map((event) => view.on(event, (e) => {
  36814. // run core method, if returns a promise, we silence errors as those are passed to the UI via stores
  36815. const returned = core[event](e && e.detail);
  36816. if (returned instanceof Promise)
  36817. returned.catch(() => { });
  36818. }));
  36819. // auto subscribes on each possible publisher
  36820. const subscribe = (event, cb) => {
  36821. const unsubInit = sub(event, cb);
  36822. const unsubCore = core.on(event, cb);
  36823. const unsubView = view.on(event, cb);
  36824. return () => {
  36825. unsubInit();
  36826. unsubCore();
  36827. unsubView();
  36828. };
  36829. };
  36830. // handles every event, useful for routing events from the options object
  36831. accessors.handleEvent = noop$1;
  36832. const handleEventUnsubs = editorEvents.map((type) => subscribe(type, (res) => accessors.handleEvent(type, res)));
  36833. // set up new api
  36834. defineMethods(accessors, {
  36835. on: subscribe,
  36836. updateImage: (src) => new Promise((resolve, reject) => {
  36837. // save history
  36838. const storedHistory = accessors.history.get();
  36839. // save state
  36840. const storedState = accessors.imageState;
  36841. // update image
  36842. core.loadImage(src)
  36843. .then((res) => {
  36844. // restore history
  36845. accessors.history.set(storedHistory);
  36846. // restore state
  36847. accessors.imageState = storedState;
  36848. // done!
  36849. resolve(res);
  36850. })
  36851. .catch(reject);
  36852. }),
  36853. close: () => {
  36854. pub('close');
  36855. },
  36856. destroy: () => {
  36857. // unsub
  36858. [...unsubs, ...handleEventUnsubs].forEach((unsub) => unsub());
  36859. // destroy
  36860. view.destroy();
  36861. core.destroy();
  36862. // destroyed
  36863. pub('destroy');
  36864. },
  36865. });
  36866. return accessors;
  36867. };
  36868. const TAG = 'pintura-editor';
  36869. var _defineCustomElements = () => new Promise((resolve) => {
  36870. if (!PinturaImageEditorElement)
  36871. return resolve([]);
  36872. !hasDefinedCustomElement(TAG) && customElements.define(TAG, PinturaImageEditorElement);
  36873. customElements.whenDefined(TAG).then(() => resolve(document.querySelectorAll(TAG)));
  36874. });
  36875. const PinturaImageEditorElement = isBrowser() &&
  36876. class extends HTMLElement {
  36877. constructor() {
  36878. super();
  36879. this._editor = undefined;
  36880. this._unsubs = undefined;
  36881. }
  36882. static get observedAttributes() {
  36883. return ['src'];
  36884. }
  36885. attributeChangedCallback(attrName, oldValue, newValue) {
  36886. this[attrName] = newValue;
  36887. }
  36888. connectedCallback() {
  36889. this._editor = initEditorView(this);
  36890. linkAccessors(this._editor, this);
  36891. this._editor.src = this.getAttribute('src');
  36892. this._unsubs = dispatchEditorEvents(this._editor, this);
  36893. }
  36894. disconnectedCallback() {
  36895. this._editor.destroy();
  36896. this._unsubs.forEach((unsub) => unsub());
  36897. }
  36898. };
  36899. const CSS_CLASS_NAME = 'pintura-editor';
  36900. var _appendEditor = (target, options = {}) => {
  36901. const element = isString(target)
  36902. ? document.querySelector(target)
  36903. : target;
  36904. if (!isElement(element))
  36905. return undefined;
  36906. options.class = options.class ? `${CSS_CLASS_NAME} ${options.class}` : CSS_CLASS_NAME;
  36907. const accessors = initEditorView(element);
  36908. return Object.assign(accessors, options);
  36909. };
  36910. /* src/core/ui/modal/index.svelte generated by Svelte v3.37.0 */
  36911. const { document: document_1, window: window_1 } = globals;
  36912. function create_fragment(ctx) {
  36913. let t;
  36914. let div;
  36915. let mounted;
  36916. let dispose;
  36917. add_render_callback(/*onwindowresize*/ ctx[27]);
  36918. return {
  36919. c() {
  36920. t = space();
  36921. div = element("div");
  36922. attr(div, "class", /*className*/ ctx[5]);
  36923. attr(div, "style", /*style*/ ctx[4]);
  36924. },
  36925. m(target, anchor) {
  36926. insert(target, t, anchor);
  36927. insert(target, div, anchor);
  36928. /*div_binding*/ ctx[28](div);
  36929. if (!mounted) {
  36930. dispose = [
  36931. listen(window_1, "keydown", /*handleKey*/ ctx[10]),
  36932. listen(window_1, "orientationchange", /*spawnMeasureElement*/ ctx[11]),
  36933. listen(window_1, "resize", /*onwindowresize*/ ctx[27]),
  36934. listen(document_1.body, "focusin", function () {
  36935. if (is_function(!/*hidden*/ ctx[1] && /*handleFocusIn*/ ctx[7])) (!/*hidden*/ ctx[1] && /*handleFocusIn*/ ctx[7]).apply(this, arguments);
  36936. }),
  36937. listen(document_1.body, "focusout", function () {
  36938. if (is_function(/*hasFocussedTextField*/ ctx[2] && /*handleFocusOut*/ ctx[8])) (/*hasFocussedTextField*/ ctx[2] && /*handleFocusOut*/ ctx[8]).apply(this, arguments);
  36939. }),
  36940. listen(div, "wheel", /*handleWheel*/ ctx[9], { passive: false })
  36941. ];
  36942. mounted = true;
  36943. }
  36944. },
  36945. p(new_ctx, dirty) {
  36946. ctx = new_ctx;
  36947. if (dirty[0] & /*className*/ 32) {
  36948. attr(div, "class", /*className*/ ctx[5]);
  36949. }
  36950. if (dirty[0] & /*style*/ 16) {
  36951. attr(div, "style", /*style*/ ctx[4]);
  36952. }
  36953. },
  36954. i: noop,
  36955. o: noop,
  36956. d(detaching) {
  36957. if (detaching) detach(t);
  36958. if (detaching) detach(div);
  36959. /*div_binding*/ ctx[28](null);
  36960. mounted = false;
  36961. run_all(dispose);
  36962. }
  36963. };
  36964. }
  36965. function instance($$self, $$props, $$invalidate) {
  36966. let o;
  36967. let viewportRules;
  36968. let isOpaque;
  36969. let isIOSFooterVisible;
  36970. let style;
  36971. let className;
  36972. let scrollsBodyOnInteraction;
  36973. let $opacity;
  36974. const dispatch = createEventDispatcher();
  36975. let { root } = $$props;
  36976. let { preventZoomViewport = true } = $$props;
  36977. let { preventScrollBodyIfNeeded = true } = $$props;
  36978. let { preventFooterOverlapIfNeeded = true } = $$props;
  36979. let { class: klass = undefined } = $$props;
  36980. let hidden = true;
  36981. let hiding = false;
  36982. let showing = false;
  36983. let doc = isBrowser() && document.documentElement;
  36984. let body = isBrowser() && document.body;
  36985. let head = isBrowser() && document.head;
  36986. const opacity = spring(0, { precision: 0.001, damping: 0.5 });
  36987. component_subscribe($$self, opacity, value => $$invalidate(23, $opacity = value));
  36988. // animate hide and show
  36989. const unsub = opacity.subscribe(o => {
  36990. if (showing && o >= 1) {
  36991. $$invalidate(19, showing = false); // now shown
  36992. $$invalidate(1, hidden = false);
  36993. dispatch("show");
  36994. } else if (hiding && o <= 0) {
  36995. $$invalidate(18, hiding = false); // now hidden
  36996. $$invalidate(1, hidden = true);
  36997. dispatch("hide");
  36998. }
  36999. });
  37000. // clean up when removed
  37001. onDestroy(() => {
  37002. // make sure no longer locking body element
  37003. doc.classList.remove("PinturaModalBodyLock");
  37004. // clean up subs
  37005. unsub();
  37006. });
  37007. let hasFocussedTextField = false;
  37008. let viewportDefaults = undefined;
  37009. let themeDefaults = undefined;
  37010. let showTimeoutId = undefined;
  37011. const getViewPortElement = () => document.querySelector("meta[name=viewport]");
  37012. const getThemeElements = () => Array.from(document.querySelectorAll("meta[name=theme-color]"));
  37013. const show = () => {
  37014. // is visible, or busy becoming visible
  37015. if (showing || !hidden) return;
  37016. // now in 'showing' transition
  37017. $$invalidate(19, showing = true);
  37018. // store default viewport element values
  37019. const viewportElement = getViewPortElement() || h("meta", { name: "viewport" });
  37020. viewportDefaults = !viewportDefaults && viewportElement.getAttribute("content");
  37021. viewportElement.setAttribute("content", viewportRules + ((/cover/).test(viewportDefaults)
  37022. ? ",viewport-fit=cover"
  37023. : ""));
  37024. if (!viewportElement.parentNode) head.append(viewportElement);
  37025. // store default theme element values
  37026. const backgroundColor = getComputedStyle(root).getPropertyValue("--color-background");
  37027. const themeElements = getThemeElements();
  37028. if (themeElements.length) {
  37029. // store defaults
  37030. themeDefaults = themeElements.map(element => element.getAttribute("content"));
  37031. } else {
  37032. // create element
  37033. const themeElement = h("meta", { name: "theme-color" });
  37034. head.append(themeElement);
  37035. themeElements.push(themeElement);
  37036. }
  37037. // update colors
  37038. themeElements.forEach(element => element.setAttribute("content", `rgb(${backgroundColor})`));
  37039. clearTimeout(showTimeoutId);
  37040. showTimeoutId = setTimeout(() => opacity.set(1), 250);
  37041. };
  37042. const hide = () => {
  37043. // is hiding or already hidden
  37044. if (hiding || hidden) return;
  37045. // if previous command was show, we need to prevent the timeout from kicking off
  37046. clearTimeout(showTimeoutId);
  37047. // now in 'hiding' transition
  37048. $$invalidate(18, hiding = true);
  37049. // get a reference to the viewport element, it should be there as we created it earlier,
  37050. // we restore defaults if the viewport metatag was defined, if not, we destroy it
  37051. const viewportElement = getViewPortElement();
  37052. if (viewportDefaults) viewportElement.setAttribute("content", viewportDefaults); else viewportElement.remove();
  37053. // restore colors
  37054. const themeElements = getThemeElements();
  37055. if (themeDefaults) {
  37056. themeElements.forEach((element, index) => {
  37057. element.setAttribute("content", themeDefaults[index]);
  37058. });
  37059. } else themeElements.forEach(element => element.remove());
  37060. // let's hide!
  37061. opacity.set(0);
  37062. };
  37063. //
  37064. // handle soft keyboard impact on window height
  37065. //
  37066. let focusOutTimer;
  37067. let focusInWindowHeight;
  37068. const handleFocusIn = e => {
  37069. // test if is text input element
  37070. if (!(/textarea/i).test(e.target)) return;
  37071. // now focussing a field
  37072. $$invalidate(2, hasFocussedTextField = true);
  37073. focusInWindowHeight = windowHeight;
  37074. };
  37075. const handleFocusOut = e => {
  37076. // test if is text input element
  37077. if (!(/textarea/i).test(e.target)) return;
  37078. // prevent accidentally setting two timers
  37079. clearTimeout(focusOutTimer);
  37080. // test if window height changed, if not, no soft keyboard appeared and we can set false to focus state immidiately
  37081. if (focusInWindowHeight === windowHeight) {
  37082. $$invalidate(2, hasFocussedTextField = false);
  37083. } else // soft keyboard might have appeared, test for window height change before setting unfocus state
  37084. {
  37085. const windowCurrentHeight = windowHeight;
  37086. runWhen(() => windowHeight !== windowCurrentHeight, () => $$invalidate(2, hasFocussedTextField = false));
  37087. }
  37088. };
  37089. const runWhen = (test, cb) => {
  37090. const frame = () => {
  37091. if (test()) {
  37092. cb();
  37093. return;
  37094. }
  37095. requestAnimationFrame(frame);
  37096. };
  37097. requestAnimationFrame(frame);
  37098. };
  37099. //
  37100. // end soft keyboard logic
  37101. //
  37102. // prevent mousewheel from scrolling content behind modal
  37103. const handleWheel = e => e.preventDefault();
  37104. // handle escape to close modal
  37105. const handleKey = e => {
  37106. // get key type
  37107. const { key } = e;
  37108. // only deal with escape key
  37109. if (!(/escape/i).test(key)) return;
  37110. // don't close when in an input or textuarea
  37111. const targetElement = e.target;
  37112. if (targetElement && (/input|textarea/i).test(targetElement.nodeName)) return;
  37113. // only close if I'm the top modal
  37114. const modals = document.querySelectorAll(".PinturaModal");
  37115. if (modals[modals.length - 1] !== root) return;
  37116. // request close
  37117. dispatch("close");
  37118. };
  37119. // this logic scales modal to fit viewport height
  37120. let windowHeight = 0;
  37121. let windowHeightComputed;
  37122. // iOS measure actual page height so we can make optional use of available space
  37123. let measureElement;
  37124. let measureElementHeight = undefined;
  37125. const spawnMeasureElement = () => {
  37126. // can't spawn more than one
  37127. if (measureElement) return;
  37128. // create measure element and append to body
  37129. measureElement = h("div", {
  37130. style: "position:fixed;height:100vh;top:0"
  37131. });
  37132. body.append(measureElement);
  37133. };
  37134. onMount(() => {
  37135. // no need to run this logic if is not on iOS
  37136. if (!preventFooterOverlapIfNeeded || !isIOS()) return;
  37137. // will be used in first read to determine page height and bottom padding
  37138. spawnMeasureElement();
  37139. });
  37140. afterUpdate(() => {
  37141. // will only run on iOS
  37142. if (!measureElement) return;
  37143. // get height and store
  37144. $$invalidate(21, measureElementHeight = measureElement.offsetHeight);
  37145. // remove measure element
  37146. measureElement.remove();
  37147. measureElement = undefined;
  37148. });
  37149. //
  37150. // document lock style for iOS 15.0
  37151. //
  37152. let scrollOffsetY = undefined;
  37153. // syncs height of doc lock with window
  37154. const syncHeight = () => doc.style.setProperty("--pintura-document-height", `${window.innerHeight}px`);
  37155. const toggleDocumentLock = isOpaque => {
  37156. if (isOpaque) {
  37157. scrollOffsetY = window.scrollY;
  37158. // prevents safari on iOS 15.0 from scrolling body and showing footer on drag interaction
  37159. doc.classList.add("PinturaDocumentLock");
  37160. // need to do this to sync height of initial window
  37161. syncHeight();
  37162. // also sync on resize
  37163. window.addEventListener("resize", syncHeight);
  37164. } else {
  37165. // stop syncing height
  37166. window.removeEventListener("resize", syncHeight);
  37167. // clean up
  37168. doc.classList.remove("PinturaDocumentLock");
  37169. isNumber(scrollOffsetY) && window.scrollTo(0, scrollOffsetY);
  37170. scrollOffsetY = undefined;
  37171. }
  37172. };
  37173. function onwindowresize() {
  37174. $$invalidate(3, windowHeight = window_1.innerHeight);
  37175. }
  37176. function div_binding($$value) {
  37177. binding_callbacks[$$value ? "unshift" : "push"](() => {
  37178. root = $$value;
  37179. $$invalidate(0, root);
  37180. });
  37181. }
  37182. $$self.$$set = $$props => {
  37183. if ("root" in $$props) $$invalidate(0, root = $$props.root);
  37184. if ("preventZoomViewport" in $$props) $$invalidate(12, preventZoomViewport = $$props.preventZoomViewport);
  37185. if ("preventScrollBodyIfNeeded" in $$props) $$invalidate(13, preventScrollBodyIfNeeded = $$props.preventScrollBodyIfNeeded);
  37186. if ("preventFooterOverlapIfNeeded" in $$props) $$invalidate(14, preventFooterOverlapIfNeeded = $$props.preventFooterOverlapIfNeeded);
  37187. if ("class" in $$props) $$invalidate(15, klass = $$props.class);
  37188. };
  37189. $$self.$$.update = () => {
  37190. if ($$self.$$.dirty[0] & /*showing, hiding, $opacity, hidden*/ 9175042) {
  37191. $$invalidate(22, o = showing || hiding ? $opacity : hidden ? 0 : 1);
  37192. }
  37193. if ($$self.$$.dirty[0] & /*preventZoomViewport*/ 4096) {
  37194. viewportRules = "width=device-width,height=device-height,initial-scale=1" + (preventZoomViewport
  37195. ? ",maximum-scale=1,user-scalable=0"
  37196. : "");
  37197. }
  37198. if ($$self.$$.dirty[0] & /*showing, hidden, hiding*/ 786434) {
  37199. $$invalidate(24, isOpaque = !showing && !hidden && !hiding);
  37200. }
  37201. if ($$self.$$.dirty[0] & /*hasFocussedTextField, windowHeight*/ 12) {
  37202. if (!hasFocussedTextField) $$invalidate(20, windowHeightComputed = windowHeight);
  37203. }
  37204. if ($$self.$$.dirty[0] & /*measureElementHeight, windowHeight*/ 2097160) {
  37205. $$invalidate(25, isIOSFooterVisible = isNumber(measureElementHeight)
  37206. ? `--viewport-pad-footer:${measureElementHeight > windowHeight ? 0 : 1}`
  37207. : "");
  37208. }
  37209. if ($$self.$$.dirty[0] & /*o, windowHeightComputed, isIOSFooterVisible*/ 38797312) {
  37210. $$invalidate(4, style = `opacity:${o};height:${windowHeightComputed}px;--editor-modal:1;${isIOSFooterVisible}`);
  37211. }
  37212. if ($$self.$$.dirty[0] & /*klass*/ 32768) {
  37213. $$invalidate(5, className = arrayJoin(["pintura-editor", "PinturaModal", klass]));
  37214. }
  37215. if ($$self.$$.dirty[0] & /*preventScrollBodyIfNeeded*/ 8192) {
  37216. $$invalidate(26, scrollsBodyOnInteraction = preventScrollBodyIfNeeded && isIOS() && (/15_/).test(navigator.userAgent));
  37217. }
  37218. if ($$self.$$.dirty[0] & /*scrollsBodyOnInteraction, isOpaque*/ 83886080) {
  37219. scrollsBodyOnInteraction && toggleDocumentLock(isOpaque);
  37220. }
  37221. };
  37222. return [
  37223. root,
  37224. hidden,
  37225. hasFocussedTextField,
  37226. windowHeight,
  37227. style,
  37228. className,
  37229. opacity,
  37230. handleFocusIn,
  37231. handleFocusOut,
  37232. handleWheel,
  37233. handleKey,
  37234. spawnMeasureElement,
  37235. preventZoomViewport,
  37236. preventScrollBodyIfNeeded,
  37237. preventFooterOverlapIfNeeded,
  37238. klass,
  37239. show,
  37240. hide,
  37241. hiding,
  37242. showing,
  37243. windowHeightComputed,
  37244. measureElementHeight,
  37245. o,
  37246. $opacity,
  37247. isOpaque,
  37248. isIOSFooterVisible,
  37249. scrollsBodyOnInteraction,
  37250. onwindowresize,
  37251. div_binding
  37252. ];
  37253. }
  37254. class Modal extends SvelteComponent {
  37255. constructor(options) {
  37256. super();
  37257. init(
  37258. this,
  37259. options,
  37260. instance,
  37261. create_fragment,
  37262. safe_not_equal,
  37263. {
  37264. root: 0,
  37265. preventZoomViewport: 12,
  37266. preventScrollBodyIfNeeded: 13,
  37267. preventFooterOverlapIfNeeded: 14,
  37268. class: 15,
  37269. show: 16,
  37270. hide: 17
  37271. },
  37272. [-1, -1]
  37273. );
  37274. }
  37275. get root() {
  37276. return this.$$.ctx[0];
  37277. }
  37278. set root(root) {
  37279. this.$set({ root });
  37280. flush();
  37281. }
  37282. get preventZoomViewport() {
  37283. return this.$$.ctx[12];
  37284. }
  37285. set preventZoomViewport(preventZoomViewport) {
  37286. this.$set({ preventZoomViewport });
  37287. flush();
  37288. }
  37289. get preventScrollBodyIfNeeded() {
  37290. return this.$$.ctx[13];
  37291. }
  37292. set preventScrollBodyIfNeeded(preventScrollBodyIfNeeded) {
  37293. this.$set({ preventScrollBodyIfNeeded });
  37294. flush();
  37295. }
  37296. get preventFooterOverlapIfNeeded() {
  37297. return this.$$.ctx[14];
  37298. }
  37299. set preventFooterOverlapIfNeeded(preventFooterOverlapIfNeeded) {
  37300. this.$set({ preventFooterOverlapIfNeeded });
  37301. flush();
  37302. }
  37303. get class() {
  37304. return this.$$.ctx[15];
  37305. }
  37306. set class(klass) {
  37307. this.$set({ class: klass });
  37308. flush();
  37309. }
  37310. get show() {
  37311. return this.$$.ctx[16];
  37312. }
  37313. get hide() {
  37314. return this.$$.ctx[17];
  37315. }
  37316. }
  37317. // @ts-ignore
  37318. // we export a function that renders the view as to not export svelte component related code to outside the ui dir
  37319. var createModal = (options = {}, parent) => new Modal({
  37320. target: parent || document.body,
  37321. props: {
  37322. class: options.class,
  37323. preventZoomViewport: options.preventZoomViewport,
  37324. preventScrollBodyIfNeeded: options.preventScrollBodyIfNeeded,
  37325. preventFooterOverlapIfNeeded: options.preventFooterOverlapIfNeeded,
  37326. },
  37327. });
  37328. var _openEditor = (options = {}, parent) => {
  37329. // set up pub/sub for the app layer
  37330. const { sub, pub } = pubsub();
  37331. const accessors = {};
  37332. const modal = createModal(options, parent);
  37333. const hide = () => {
  37334. if (!modal.hide)
  37335. return; // was destroyed
  37336. modal.hide();
  37337. };
  37338. const show = () => {
  37339. if (!modal.show)
  37340. return; // was destroyed
  37341. modal.show();
  37342. };
  37343. const view = initEditorView(modal.root);
  37344. linkAccessors(view, accessors);
  37345. // link up handle event
  37346. accessors.handleEvent = noop$1;
  37347. view.handleEvent = (type, detail) => accessors.handleEvent(type, detail);
  37348. // route close request from view to modal
  37349. view.on('close', async () => {
  37350. const { willClose } = options;
  37351. if (!willClose)
  37352. return hide();
  37353. const shouldClose = await willClose();
  37354. if (shouldClose)
  37355. hide();
  37356. });
  37357. const subscribe = (event, cb) => {
  37358. // capture modal related events
  37359. if (/show|hide/.test(event))
  37360. return sub(event, cb);
  37361. // route rest of events to view
  37362. return view.on(event, cb);
  37363. };
  37364. const modalHandleEventUnsubs = ['show', 'hide'].map((type) => subscribe(type, (detail) => accessors.handleEvent(type, detail)));
  37365. // cleans up view
  37366. const destroy = () => {
  37367. // unsub
  37368. modalHandleEventUnsubs.forEach((unsub) => unsub());
  37369. // remove
  37370. hide();
  37371. modal.$destroy();
  37372. view.destroy();
  37373. };
  37374. defineMethods(accessors, {
  37375. on: subscribe,
  37376. destroy,
  37377. hide,
  37378. show,
  37379. });
  37380. // add element root query
  37381. Object.defineProperty(accessors, 'modal', {
  37382. get: () => modal.root,
  37383. set: () => undefined,
  37384. });
  37385. // route modal events
  37386. modal.$on('close', view.close);
  37387. modal.$on('show', () => pub('show'));
  37388. modal.$on('hide', () => {
  37389. pub('hide');
  37390. if (options.enableAutoDestroy !== false)
  37391. destroy();
  37392. });
  37393. // modal behavior
  37394. if (options.enableAutoHide !== false)
  37395. view.on('process', hide);
  37396. view.on('loadstart', show);
  37397. // test if should
  37398. if (options.enableButtonClose !== false)
  37399. options.enableButtonClose = true;
  37400. // delete class
  37401. delete options.class;
  37402. // update props
  37403. Object.assign(accessors, options);
  37404. return accessors;
  37405. };
  37406. var _overlayEditor = (target, options) => {
  37407. const editor = _appendEditor(target, {
  37408. ...options,
  37409. layout: 'overlay',
  37410. });
  37411. return editor;
  37412. };
  37413. // helper method to calculate end style params that are passed to lineEnd style functions
  37414. const getLineEndParams = (start, end, strokeWidth, isSolid) => {
  37415. const direction = vectorCreate(end.x - start.x, end.y - start.y);
  37416. const normal = vectorNormalize(direction);
  37417. const scaledSize = 5 * strokeWidth;
  37418. let scaledSizeHalf;
  37419. // solid
  37420. if (isSolid) {
  37421. scaledSizeHalf = scaledSize * 0.5;
  37422. }
  37423. // stroke
  37424. else {
  37425. scaledSizeHalf = Math.ceil((scaledSize - 1) * 0.5);
  37426. }
  37427. const offset = vectorMultiply(vectorClone(normal), scaledSizeHalf);
  37428. return {
  37429. anchor: vectorClone(start),
  37430. offset,
  37431. normal,
  37432. solid: isSolid,
  37433. size: scaledSize,
  37434. sizeHalf: scaledSizeHalf,
  37435. };
  37436. };
  37437. // various available styles
  37438. const lineEndStyleArrow = ({ anchor, solid, normal, offset, size, sizeHalf, strokeWidth, strokeColor }, anchorRef) => {
  37439. const x = anchor.x;
  37440. const y = anchor.y;
  37441. const tipOffset = vectorMultiply(vectorClone(normal), size);
  37442. const inset = vectorCreate(x + tipOffset.x, y + tipOffset.y);
  37443. vectorMultiply(tipOffset, 0.55);
  37444. if (solid) {
  37445. // move back so arrow triangle overlaps with end of line (otherwise line sticks out of triangle tip)
  37446. vectorAdd(anchorRef, offset);
  37447. const arrowOffset = vectorMultiply(vectorClone(normal), sizeHalf * 0.5);
  37448. return [
  37449. {
  37450. points: [
  37451. vectorCreate(x - arrowOffset.x, y - arrowOffset.y),
  37452. vectorCreate(inset.x - tipOffset.y, inset.y + tipOffset.x),
  37453. vectorCreate(inset.x + tipOffset.y, inset.y - tipOffset.x),
  37454. ],
  37455. backgroundColor: strokeColor,
  37456. },
  37457. ];
  37458. }
  37459. else {
  37460. // this prevents trouble with sharp line rendering in webgl
  37461. const p = vectorMultiply(vectorPerpendicular(vectorClone(normal)), 0.5);
  37462. const tipLeft = vectorCreate(x - p.x, y - p.y);
  37463. const tipRight = vectorCreate(x + p.x, y + p.y);
  37464. return [
  37465. {
  37466. points: [
  37467. vectorCreate(inset.x + tipOffset.y, inset.y - tipOffset.x),
  37468. tipLeft,
  37469. vectorCreate(x, y),
  37470. tipRight,
  37471. vectorCreate(inset.x - tipOffset.y, inset.y + tipOffset.x),
  37472. ],
  37473. strokeWidth: strokeWidth,
  37474. strokeColor: strokeColor,
  37475. },
  37476. ];
  37477. }
  37478. };
  37479. const lineEndStyleCircle = ({ anchor, solid, offset, normal, sizeHalf, strokeWidth, strokeColor }, anchorRef) => {
  37480. // update anchor point position
  37481. vectorAdd(anchorRef, offset);
  37482. // if solid, move line slightly towards circle as to make them overlap
  37483. if (solid)
  37484. vectorAdd(anchorRef, vectorInvert(vectorClone(normal)));
  37485. return [
  37486. {
  37487. x: anchor.x,
  37488. y: anchor.y,
  37489. rx: sizeHalf,
  37490. ry: sizeHalf,
  37491. backgroundColor: solid ? strokeColor : undefined,
  37492. strokeWidth: solid ? undefined : strokeWidth,
  37493. strokeColor: solid ? undefined : strokeColor,
  37494. },
  37495. ];
  37496. };
  37497. const lineEndStyleBar = ({ anchor, offset, strokeWidth, strokeColor }) => {
  37498. return [
  37499. {
  37500. points: [
  37501. vectorCreate(anchor.x - offset.y, anchor.y + offset.x),
  37502. vectorCreate(anchor.x + offset.y, anchor.y - offset.x),
  37503. ],
  37504. strokeWidth,
  37505. strokeColor,
  37506. },
  37507. ];
  37508. };
  37509. const lineEndStyleSquare = ({ anchor, solid, offset, normal, sizeHalf, strokeWidth, strokeColor }, anchorRef) => {
  37510. // update anchor point position
  37511. vectorAdd(anchorRef, offset);
  37512. return [
  37513. {
  37514. x: anchor.x - sizeHalf,
  37515. y: anchor.y - sizeHalf,
  37516. width: sizeHalf * 2,
  37517. height: sizeHalf * 2,
  37518. rotation: vectorAngle(normal),
  37519. backgroundColor: solid ? strokeColor : undefined,
  37520. strokeWidth: solid ? undefined : strokeWidth,
  37521. strokeColor: solid ? undefined : strokeColor,
  37522. },
  37523. ];
  37524. };
  37525. // this method parses the shape and checks if lineStart or lineEnd is being used
  37526. const createLineEndProcessor = (styles = {}) => (shape) => {
  37527. if (!hasProp(shape, 'lineStart') && !hasProp(shape, 'lineEnd'))
  37528. return;
  37529. // resulting shapes
  37530. const res = [];
  37531. const { lineStart, lineEnd, strokeWidth, strokeColor } = shape;
  37532. const start = vectorCreate(shape.x1, shape.y1);
  37533. const end = vectorCreate(shape.x2, shape.y2);
  37534. const points = [start, end];
  37535. // handle lineStart
  37536. if (lineStart) {
  37537. const [style, solid] = lineStart.split('-');
  37538. const process = styles[style];
  37539. if (process) {
  37540. const params = getLineEndParams(start, end, strokeWidth, !!solid);
  37541. res.push(...process({
  37542. ...params,
  37543. strokeColor,
  37544. strokeWidth,
  37545. }, start));
  37546. }
  37547. }
  37548. // handle lineEnd
  37549. if (lineEnd) {
  37550. const [style, solid] = lineEnd.split('-');
  37551. const process = styles[style];
  37552. if (process) {
  37553. const params = getLineEndParams(end, start, strokeWidth, !!solid);
  37554. res.push(...process({
  37555. ...params,
  37556. strokeColor,
  37557. strokeWidth,
  37558. }, end));
  37559. }
  37560. }
  37561. return [
  37562. // return inner path
  37563. {
  37564. points,
  37565. strokeWidth,
  37566. strokeColor,
  37567. },
  37568. // add line end styles
  37569. ...res,
  37570. ];
  37571. };
  37572. // the default line end styles available, can import and extend
  37573. const createDefaultLineEndStyles = () => ({
  37574. arrow: lineEndStyleArrow,
  37575. circle: lineEndStyleCircle,
  37576. square: lineEndStyleSquare,
  37577. bar: lineEndStyleBar,
  37578. });
  37579. const safeFactor = (value, factor) => {
  37580. const v = parseFloat(value) * factor;
  37581. return isString(value) ? `${v}%` : v;
  37582. };
  37583. const toValue = (value, total) => (isString(value) ? toPixelValue(value, total) : value);
  37584. // const toFraction = (value, total) => toValue(value, total) / total;
  37585. const frameStyleSolid = (shape) => [
  37586. {
  37587. ...shape,
  37588. frameStyle: 'line',
  37589. frameInset: 0,
  37590. frameOffset: 0,
  37591. frameSize: shape.frameSize ? safeFactor(shape.frameSize, 2) : '2.5%',
  37592. frameRadius: shape.frameRound ? safeFactor(shape.frameSize, 2) : 0,
  37593. },
  37594. ];
  37595. const frameStyleLine = ({ x, y, width, height, frameInset = '3.5%', frameSize = '.25%', frameColor = [1, 1, 1], frameOffset = '5%', frameAmount = 1, frameRadius = 0, expandsCanvas = false, }, { isPreview }) => {
  37596. const size = Math.sqrt(width * height);
  37597. let frameSizeValue = toValue(frameSize, size);
  37598. const frameInsetValue = toValue(frameInset, size);
  37599. const frameOffsetValue = toValue(frameOffset, size);
  37600. let center = 0;
  37601. if (!isPreview) {
  37602. frameSizeValue = Math.max(1, Math.round(frameSizeValue));
  37603. center = frameSizeValue % 2 == 0 ? 0 : 0.5;
  37604. }
  37605. const r = toValue(safeFactor(frameRadius, frameAmount), size);
  37606. return new Array(frameAmount).fill(undefined).map((_, index) => {
  37607. const offset = frameOffsetValue * index;
  37608. let left = x + frameInsetValue + offset;
  37609. let top = y + frameInsetValue + offset;
  37610. let right = x + width - frameInsetValue - offset;
  37611. let bottom = y + height - frameInsetValue - offset;
  37612. if (!isPreview) {
  37613. left = Math.round(left);
  37614. top = Math.round(top);
  37615. right = Math.round(right);
  37616. bottom = Math.round(bottom);
  37617. }
  37618. const radius = r > 0 ? r - offset : 0;
  37619. return {
  37620. x: left + center,
  37621. y: top + center,
  37622. width: right - left,
  37623. height: bottom - top,
  37624. cornerRadius: radius,
  37625. strokeWidth: frameSizeValue,
  37626. strokeColor: frameColor,
  37627. expandsCanvas,
  37628. };
  37629. });
  37630. };
  37631. const frameStyleEdge = ({ x, y, width, height, frameSize = '.25%', frameOffset = 0, frameInset = '2.5%', frameColor = [1, 1, 1], }, { isPreview }) => {
  37632. const size = Math.sqrt(width * height);
  37633. let frameSizeValue = toValue(frameSize, size);
  37634. let frameInsetValue = toValue(frameInset, size);
  37635. let frameOffsetValue = toValue(frameOffset, size);
  37636. let center = 0;
  37637. if (!isPreview) {
  37638. frameSizeValue = Math.max(1, Math.round(frameSizeValue));
  37639. frameInsetValue = Math.round(frameInsetValue);
  37640. frameOffsetValue = Math.round(frameOffsetValue);
  37641. center = frameSizeValue % 2 == 0 ? 0 : 0.5;
  37642. }
  37643. const offset = frameOffsetValue - frameInsetValue;
  37644. const left = x + frameInsetValue + center;
  37645. const top = y + frameInsetValue + center;
  37646. const right = x + width - frameInsetValue - center;
  37647. const bottom = y + height - frameInsetValue - center;
  37648. return [
  37649. // top
  37650. {
  37651. points: [vectorCreate(left + offset, top), vectorCreate(right - offset, top)],
  37652. },
  37653. {
  37654. points: [vectorCreate(right, top + offset), vectorCreate(right, bottom - offset)],
  37655. },
  37656. {
  37657. points: [vectorCreate(right - offset, bottom), vectorCreate(left + offset, bottom)],
  37658. },
  37659. {
  37660. points: [vectorCreate(left, bottom - offset), vectorCreate(left, top + offset)],
  37661. },
  37662. ].map((shape) => {
  37663. shape.strokeWidth = frameSizeValue;
  37664. shape.strokeColor = frameColor;
  37665. return shape;
  37666. });
  37667. };
  37668. const frameStyleHook = ({ x, y, width, height, frameSize = '.25%', frameInset = '2.5%', frameLength = '2.5%', frameColor = [1, 1, 1], }, { isPreview }) => {
  37669. const size = Math.sqrt(width * height);
  37670. let frameSizeValue = toValue(frameSize, size);
  37671. let frameInsetValue = toValue(frameInset, size);
  37672. let frameLengthValue = toValue(frameLength, size);
  37673. let center = 0;
  37674. if (!isPreview) {
  37675. frameSizeValue = Math.max(1, Math.round(frameSizeValue));
  37676. frameInsetValue = Math.round(frameInsetValue);
  37677. frameLengthValue = Math.round(frameLengthValue);
  37678. center = frameSizeValue % 2 == 0 ? 0 : 0.5;
  37679. }
  37680. const left = x + frameInsetValue + center;
  37681. const top = y + frameInsetValue + center;
  37682. const right = x + width - frameInsetValue - center;
  37683. const bottom = y + height - frameInsetValue - center;
  37684. return [
  37685. // top
  37686. {
  37687. points: [
  37688. vectorCreate(left, top + frameLengthValue),
  37689. vectorCreate(left, top),
  37690. vectorCreate(left + frameLengthValue, top),
  37691. ],
  37692. },
  37693. {
  37694. points: [
  37695. vectorCreate(right - frameLengthValue, top),
  37696. vectorCreate(right, top),
  37697. vectorCreate(right, top + frameLengthValue),
  37698. ],
  37699. },
  37700. {
  37701. points: [
  37702. vectorCreate(right, bottom - frameLengthValue),
  37703. vectorCreate(right, bottom),
  37704. vectorCreate(right - frameLengthValue, bottom),
  37705. ],
  37706. },
  37707. {
  37708. points: [
  37709. vectorCreate(left + frameLengthValue, bottom),
  37710. vectorCreate(left, bottom),
  37711. vectorCreate(left, bottom - frameLengthValue),
  37712. ],
  37713. },
  37714. ].map((shape) => {
  37715. shape.strokeWidth = frameSizeValue;
  37716. shape.strokeColor = frameColor;
  37717. return shape;
  37718. });
  37719. };
  37720. const frameStylePolaroid = ({ x, y, width, height, frameColor = [1, 1, 1] }, { isPreview }) => {
  37721. const size = Math.sqrt(width * height);
  37722. const borderWidth = 0.1 * size;
  37723. let chinHeight = 0.2 * size;
  37724. const borderWidthHalf = 0.5 * borderWidth;
  37725. let strokeWidth = 0.0025 * size;
  37726. if (!isPreview) {
  37727. // borderWidthHalf = Math.round(borderWidthHalf);
  37728. // borderWidth = Math.round(borderWidth);
  37729. chinHeight = Math.ceil(chinHeight);
  37730. strokeWidth = Math.max(2, strokeWidth);
  37731. }
  37732. // always remove opacity
  37733. frameColor.length = 3;
  37734. return [
  37735. // border
  37736. {
  37737. id: 'border',
  37738. x: x - borderWidthHalf,
  37739. y: y - borderWidthHalf,
  37740. width: width + borderWidth,
  37741. height: height + chinHeight,
  37742. frameStyle: 'line',
  37743. frameInset: 0,
  37744. frameOffset: 0,
  37745. frameSize: borderWidth,
  37746. frameColor,
  37747. expandsCanvas: true,
  37748. },
  37749. // chin
  37750. {
  37751. id: 'chin',
  37752. x: x - borderWidthHalf,
  37753. y: height,
  37754. width: width + borderWidth,
  37755. height: chinHeight,
  37756. backgroundColor: frameColor,
  37757. expandsCanvas: true,
  37758. },
  37759. // for preview only
  37760. isPreview && {
  37761. x,
  37762. y,
  37763. width,
  37764. height,
  37765. strokeWidth,
  37766. strokeColor: frameColor,
  37767. },
  37768. ].filter(Boolean);
  37769. };
  37770. const createFrameStyleProcessor = (styles = {}) => (shape, options) => {
  37771. // handle solid frameStyle
  37772. if (!hasProp(shape, 'frameStyle'))
  37773. return;
  37774. const style = shape.frameStyle;
  37775. // get parser for style
  37776. const process = styles[style];
  37777. if (!process)
  37778. return;
  37779. // remove frameStyle property so we don't get endless looops
  37780. const { frameStyle, ...shapeReadyToParse } = shape;
  37781. return process(shapeReadyToParse, options);
  37782. };
  37783. // the default frame styles available, can import and extend
  37784. const createDefaultFrameStyles = () => ({
  37785. solid: frameStyleSolid,
  37786. hook: frameStyleHook,
  37787. line: frameStyleLine,
  37788. edge: frameStyleEdge,
  37789. polaroid: frameStylePolaroid,
  37790. });
  37791. // the default lineEnd parser to use
  37792. const createDefaultLineEndProcessors = () => createLineEndProcessor(createDefaultLineEndStyles());
  37793. const createDefaultFrameStyleProcessor = () => createFrameStyleProcessor(createDefaultFrameStyles());
  37794. const createDefaultShapeProcessors = () => [
  37795. createDefaultFrameStyleProcessor(),
  37796. createDefaultLineEndProcessors(),
  37797. ];
  37798. const createShapePreprocessor$1 = (processors) => {
  37799. const processShape = (shape, options = { isPreview: true }) => {
  37800. const res = processors
  37801. .map((process) => {
  37802. const res = process(shape, options);
  37803. // processor wasn't a match?
  37804. if (!res)
  37805. return;
  37806. return res.map((shape) => processShape(shape, options));
  37807. })
  37808. .filter(Boolean)
  37809. .flat();
  37810. return !res.length ? shape : res.flat();
  37811. };
  37812. return processShape;
  37813. };
  37814. const createDefaultImageReader = createDefaultImageReader$1;
  37815. const createDefaultImageWriter = createDefaultImageWriter$1;
  37816. const createDefaultImageOrienter = () => ({
  37817. read: getImageOrientationFromFile,
  37818. apply: orientImageData,
  37819. });
  37820. const createDefaultImageScrambler = (configurationOptions = {}) => {
  37821. // default configuration
  37822. const { blurAmount, scrambleAmount, enableSmoothing, backgroundColor } = configurationOptions;
  37823. // as called from editor ui
  37824. return (imageData, uiOptions) =>
  37825. imageDataScramble(imageData, {
  37826. blurAmount,
  37827. scrambleAmount,
  37828. enableSmoothing,
  37829. backgroundColor,
  37830. ...uiOptions,
  37831. });
  37832. };
  37833. const createEditor = createImageEditor;
  37834. const getEditorProps = () => getEditorProps$1().concat(getEditorViewProps()); // private api for framework components
  37835. const createMarkupEditorToolbar = createToolbar;
  37836. const createMarkupEditorToolStyles = createToolStyles;
  37837. // markup editor style controls
  37838. const createMarkupEditorShapeStyleControls = createShapeStyleControls;
  37839. const markup_editor_defaults = {
  37840. markupEditorToolbar: createToolbar(),
  37841. markupEditorToolStyles: createToolStyles(),
  37842. markupEditorShapeStyleControls: createShapeStyleControls(),
  37843. };
  37844. const setPlugins = setEditorViewPlugins;
  37845. const plugin_crop = _plugin_crop;
  37846. const plugin_filter = _plugin_filter;
  37847. const plugin_finetune = _plugin_finetune;
  37848. const plugin_annotate = _plugin_annotate;
  37849. const plugin_decorate = _plugin_decorate;
  37850. const plugin_sticker = _plugin_sticker;
  37851. const plugin_frame = _plugin_frame;
  37852. const plugin_redact = _plugin_redact;
  37853. const plugin_resize = _plugin_resize;
  37854. const plugin_finetune_defaults = _plugin_finetune_defaults;
  37855. const plugin_filter_defaults = _plugin_filter_defaults;
  37856. const plugin_frame_defaults = _plugin_frame_defaults;
  37857. const locale_en_gb = _locale_en_gb;
  37858. const markup_editor_locale_en_gb = MarkupEditor;
  37859. const plugin_crop_locale_en_gb = _plugin_crop_locale_en_gb;
  37860. const plugin_filter_locale_en_gb = _plugin_filter_locale_en_gb;
  37861. const plugin_finetune_locale_en_gb = _plugin_finetune_locale_en_gb;
  37862. const plugin_resize_locale_en_gb = _plugin_resize_locale_en_gb;
  37863. const plugin_decorate_locale_en_gb = _plugin_decorate_locale_en_gb;
  37864. const plugin_annotate_locale_en_gb = _plugin_annotate_locale_en_gb;
  37865. const plugin_sticker_locale_en_gb = _plugin_sticker_locale_en_gb;
  37866. const plugin_frame_locale_en_gb = _plugin_frame_locale_en_gb;
  37867. const plugin_redact_locale_en_gb = _plugin_redact_locale_en_gb;
  37868. const elementsToEditor = (factory, targets, options = {}) => {
  37869. const elements = isString(targets) ? Array.from(document.querySelectorAll(targets)) : targets;
  37870. return elements.filter(Boolean).map((element) => factory(element, deepCopy(options)));
  37871. };
  37872. const appendEditor = _appendEditor;
  37873. const openEditor = _openEditor;
  37874. const overlayEditor = _overlayEditor;
  37875. const appendEditors = (targets, options) => elementsToEditor(appendEditor, targets, options);
  37876. const getEditorDefaultReadWriteOptions = (options = {}) => {
  37877. // allow passing reader / writer / scrambler options as object
  37878. let readerProps = undefined;
  37879. if (!Array.isArray(options.imageWriter)) {
  37880. readerProps = options.imageWriter;
  37881. delete options.imageReader;
  37882. }
  37883. let writerProps = undefined;
  37884. if (!Array.isArray(options.imageWriter)) {
  37885. writerProps = options.imageWriter;
  37886. delete options.imageWriter;
  37887. }
  37888. let scramblerProps = undefined;
  37889. if (!isFunction(options.imageScrambler)) {
  37890. scramblerProps = options.imageScrambler;
  37891. delete options.imageScrambler;
  37892. }
  37893. return {
  37894. // default handling of images
  37895. imageReader: createDefaultImageReader(readerProps),
  37896. imageWriter: createDefaultImageWriter(writerProps),
  37897. imageOrienter: createDefaultImageOrienter(),
  37898. imageScrambler: createDefaultImageScrambler(scramblerProps),
  37899. };
  37900. };
  37901. const createShapePreprocessor = createShapePreprocessor$1;
  37902. const createDefaultShapePreprocessor = () =>
  37903. createShapePreprocessor$1(createDefaultShapeProcessors());
  37904. const processDefaultImage = (src, options = {}) =>
  37905. processImage(src, { ...getEditorDefaultReadWriteOptions(options), ...options });
  37906. const getEditorDefaults = (options = {}) => {
  37907. // load all plugins
  37908. setEditorViewPlugins(
  37909. ...[
  37910. plugin_crop,
  37911. plugin_filter,
  37912. plugin_finetune,
  37913. plugin_annotate,
  37914. plugin_decorate,
  37915. plugin_sticker,
  37916. plugin_frame,
  37917. plugin_redact,
  37918. plugin_resize,
  37919. ].filter(Boolean)
  37920. );
  37921. // auto hide stickers util if no stickers defined
  37922. const utils = [
  37923. 'crop',
  37924. 'filter',
  37925. 'finetune',
  37926. 'annotate',
  37927. 'decorate',
  37928. options.stickers && 'sticker',
  37929. 'frame',
  37930. 'redact',
  37931. 'resize',
  37932. ].filter(Boolean);
  37933. // get default read/write options object
  37934. const defaultReadWriteOptions = getEditorDefaultReadWriteOptions(options);
  37935. // locale
  37936. const locale = {
  37937. ...locale_en_gb,
  37938. ...markup_editor_locale_en_gb,
  37939. ...plugin_crop_locale_en_gb,
  37940. ...plugin_filter_locale_en_gb,
  37941. ...plugin_finetune_locale_en_gb,
  37942. ...plugin_frame_locale_en_gb,
  37943. ...plugin_redact_locale_en_gb,
  37944. ...plugin_resize_locale_en_gb,
  37945. ...plugin_decorate_locale_en_gb,
  37946. ...plugin_annotate_locale_en_gb,
  37947. ...plugin_sticker_locale_en_gb,
  37948. ...options.locale,
  37949. };
  37950. delete options.locale;
  37951. // create huge config object
  37952. return mergeObjects([
  37953. {
  37954. // set reader / writer / orienter
  37955. ...defaultReadWriteOptions,
  37956. // shape preprocessor
  37957. shapePreprocessor: createDefaultShapePreprocessor(),
  37958. // default utils
  37959. utils,
  37960. // default plugin options
  37961. ...plugin_finetune_defaults,
  37962. ...plugin_filter_defaults,
  37963. ...plugin_frame_defaults,
  37964. ...markup_editor_defaults,
  37965. // stickers stick to image by default
  37966. stickerStickToImage: true,
  37967. // locale
  37968. locale,
  37969. },
  37970. options,
  37971. ]);
  37972. };
  37973. const defineCustomElements = async (options = {}) => {
  37974. const elements = await _defineCustomElements();
  37975. elements.forEach((editor) => Object.assign(editor, deepCopy(options)));
  37976. return elements;
  37977. };
  37978. const defineDefaultCustomElements = (options) =>
  37979. defineCustomElements(getEditorDefaults(options));
  37980. const openDefaultEditor = (options) => openEditor(getEditorDefaults(options));
  37981. const appendDefaultEditor = (element, options) =>
  37982. appendEditor(element, getEditorDefaults(options));
  37983. const overlayDefaultEditor = (element, options) =>
  37984. overlayEditor(element, getEditorDefaults(options));
  37985. const appendDefaultEditors = (targets, options) =>
  37986. elementsToEditor(appendDefaultEditor, targets, options);
  37987. export { appendDefaultEditor, appendDefaultEditors, appendEditor, appendEditors, appendNode, blobToFile, colorStringToColorArray, createDefaultColorOptions, createDefaultFontFamilyOptions, createDefaultFontScaleOptions, createDefaultFontSizeOptions, createDefaultFontStyleOptions, createDefaultImageOrienter, createDefaultImageReader, createDefaultImageScrambler, createDefaultImageWriter, createDefaultLineEndStyleOptions, createDefaultShapePreprocessor, createDefaultStrokeScaleOptions, createDefaultStrokeWidthOptions, createDefaultTextAlignOptions, createEditor, createBackgroundColorControl as createMarkupEditorBackgroundColorControl, createColorControl as createMarkupEditorColorControl, createColorOptions as createMarkupEditorColorOptions, createFontColorControl as createMarkupEditorFontColorControl, createFontFamilyControl as createMarkupEditorFontFamilyControl, createFontFamilyOptions as createMarkupEditorFontFamilyOptions, createFontScaleOptions as createMarkupEditorFontScaleOptions, createFontSizeControl as createMarkupEditorFontSizeControl, createFontSizeOptions as createMarkupEditorFontSizeOptions, createFontStyleControl as createMarkupEditorFontStyleControl, createFontStyleOptions as createMarkupEditorFontStyleOptions, createLineEndStyleControl as createMarkupEditorLineEndStyleControl, createLineEndStyleOptions as createMarkupEditorLineEndStyleOptions, createLineHeightControl as createMarkupEditorLineHeightControl, createLineStartStyleControl as createMarkupEditorLineStartStyleControl, createMarkupEditorShapeStyleControls, createStrokeColorControl as createMarkupEditorStrokeColorControl, createStrokeScaleOptions as createMarkupEditorStrokeScaleOptions, createStrokeWidthControl as createMarkupEditorStrokeWidthControl, createStrokeWidthOptions as createMarkupEditorStrokeWidthOptions, createTextAlignControl as createMarkupEditorTextAlignControl, createToolStyle as createMarkupEditorToolStyle, createMarkupEditorToolStyles, createMarkupEditorToolbar, createNode, createShapePreprocessor, defineCustomElements, defineDefaultCustomElements, degToRad, dispatchEditorEvents, brightness as effectBrightness, clarity as effectClarity, contrast as effectContrast, exposure as effectExposure, gamma as effectGamma, saturation as effectSaturation, temperature as effectTemperature, vignette as effectVignette, chrome as filterChrome, cold as filterCold, fade as filterFade, invert as filterInvert, monoDefault as filterMonoDefault, monoNoir as filterMonoNoir, monoStark as filterMonoStark, monoWash as filterMonoWash, pastel as filterPastel, sepiaBlues as filterSepiaBlues, sepiaColor as filterSepiaColor, sepiaDefault as filterSepiaDefault, sepiaRust as filterSepiaRust, warm as filterWarm, findNode, edgeCross as frameEdgeCross, edgeOverlap as frameEdgeOverlap, edgeSeparate as frameEdgeSeparate, hook as frameHook, lineMultiple as frameLineMultiple, lineSingle as frameLineSingle, polaroid as framePolaroid, solidRound as frameSolidRound, solidSharp as frameSolidSharp, getEditorDefaults, getEditorProps, insertNodeAfter, insertNodeBefore, isModernBrowser as isSupported, legacyDataToImageState, locale_en_gb, markup_editor_defaults, markup_editor_locale_en_gb, openDefaultEditor, openEditor, overlayDefaultEditor, overlayEditor, plugin_annotate, plugin_annotate_locale_en_gb, plugin_crop, plugin_crop_locale_en_gb, plugin_decorate, plugin_decorate_locale_en_gb, plugin_filter, plugin_filter_defaults, plugin_filter_locale_en_gb, plugin_finetune, plugin_finetune_defaults, plugin_finetune_locale_en_gb, plugin_frame, plugin_frame_defaults, plugin_frame_locale_en_gb, plugin_redact, plugin_redact_locale_en_gb, plugin_resize, plugin_resize_locale_en_gb, plugin_sticker, plugin_sticker_locale_en_gb, processDefaultImage, processImage, removeNode, setPlugins, supportsWebGL };